@@ -21,7 +21,7 @@ use tokio::task_local;
21
21
use tracing:: Span ;
22
22
use turbo_prehash:: PreHashed ;
23
23
use turbo_tasks:: {
24
- backend:: { PersistentTaskType , TaskExecutionSpec } ,
24
+ backend:: { CellContent , PersistentTaskType , TaskExecutionSpec } ,
25
25
event:: { Event , EventListener } ,
26
26
get_invalidator, registry, CellId , Invalidator , RawVc , TaskId , TaskIdSet , TraitTypeId ,
27
27
TurboTasksBackendApi , ValueTypeId ,
@@ -32,7 +32,7 @@ use crate::{
32
32
aggregation_data, handle_new_edge, prepare_aggregation_data, query_root_info,
33
33
AggregationDataGuard , PreparedOperation ,
34
34
} ,
35
- cell:: Cell ,
35
+ cell:: { Cell , RecomputingCell } ,
36
36
edges_set:: { TaskEdge , TaskEdgesList , TaskEdgesSet } ,
37
37
gc:: { GcQueue , GcTaskState } ,
38
38
output:: { Output , OutputContent } ,
@@ -448,6 +448,11 @@ pub enum GcResult {
448
448
Unloaded ,
449
449
}
450
450
451
+ pub enum ReadCellError {
452
+ CellRemoved ,
453
+ Recomputing ( EventListener ) ,
454
+ }
455
+
451
456
impl Task {
452
457
pub ( crate ) fn new_persistent (
453
458
id : TaskId ,
@@ -1286,26 +1291,82 @@ impl Task {
1286
1291
}
1287
1292
}
1288
1293
1289
- /// Access to a cell.
1290
- pub ( crate ) fn access_cell_for_read < T > (
1294
+ /// Read a cell.
1295
+ pub ( crate ) fn read_cell (
1291
1296
& self ,
1292
1297
index : CellId ,
1293
1298
gc_queue : Option < & GcQueue > ,
1294
- func : impl FnOnce ( Option < & mut Cell > ) -> T ,
1295
- ) -> T {
1299
+ note : impl Fn ( ) -> String + Sync + Send + ' static ,
1300
+ reader : Option < TaskId > ,
1301
+ backend : & MemoryBackend ,
1302
+ turbo_tasks : & dyn TurboTasksBackendApi < MemoryBackend > ,
1303
+ ) -> Result < CellContent , ReadCellError > {
1304
+ let task_id = self . id ;
1296
1305
let mut state = self . full_state_mut ( ) ;
1297
1306
if let Some ( gc_queue) = gc_queue {
1298
1307
let generation = gc_queue. generation ( ) ;
1299
1308
if state. gc . on_read ( generation) {
1300
1309
let _ = gc_queue. task_accessed ( self . id ) ;
1301
1310
}
1302
1311
}
1303
- let list = state. cells . entry ( index. type_id ) . or_default ( ) ;
1304
- let i = index. index as usize ;
1305
- if list. len ( ) <= i {
1306
- func ( None )
1307
- } else {
1308
- func ( Some ( & mut list[ i] ) )
1312
+ match state. state_type {
1313
+ Done { .. } | InProgress ( ..) | InProgressDirty { .. } => {
1314
+ let is_done = matches ! ( state. state_type, Done { .. } ) ;
1315
+ let list = state. cells . entry ( index. type_id ) . or_default ( ) ;
1316
+ let i = index. index as usize ;
1317
+ if list. len ( ) <= i {
1318
+ if is_done {
1319
+ return Err ( ReadCellError :: CellRemoved ) ;
1320
+ } else {
1321
+ list. resize_with ( i + 1 , Default :: default) ;
1322
+ }
1323
+ }
1324
+ let cell = & mut list[ i] ;
1325
+ let description = move || format ! ( "{task_id} {index}" ) ;
1326
+ let read_result = if let Some ( reader) = reader {
1327
+ cell. read_content ( reader, description, note)
1328
+ } else {
1329
+ cell. read_content_untracked ( description, note)
1330
+ } ;
1331
+ drop ( state) ;
1332
+ match read_result {
1333
+ Ok ( content) => Ok ( content) ,
1334
+ Err ( RecomputingCell { listener, schedule } ) => {
1335
+ if schedule {
1336
+ self . recompute ( backend, turbo_tasks) ;
1337
+ }
1338
+ Err ( ReadCellError :: Recomputing ( listener) )
1339
+ }
1340
+ }
1341
+ }
1342
+ Dirty {
1343
+ ref mut outdated_edges,
1344
+ } => {
1345
+ let mut aggregation_context = TaskAggregationContext :: new ( turbo_tasks, backend) ;
1346
+ let description = self . get_event_description ( ) ;
1347
+ let event = Event :: new ( move || format ! ( "TaskState({})::event" , description( ) ) ) ;
1348
+ let listener = event. listen_with_note ( note) ;
1349
+ state. state_type = Scheduled {
1350
+ event,
1351
+ outdated_edges : take ( outdated_edges) ,
1352
+ clean : false ,
1353
+ } ;
1354
+ let change_job = state. aggregation_node . apply_change (
1355
+ & aggregation_context,
1356
+ TaskChange {
1357
+ dirty_tasks_update : vec ! [ ( self . id, -1 ) ] ,
1358
+ ..Default :: default ( )
1359
+ } ,
1360
+ ) ;
1361
+ drop ( state) ;
1362
+ turbo_tasks. schedule ( self . id ) ;
1363
+ change_job. apply ( & aggregation_context) ;
1364
+ aggregation_context. apply_queued_updates ( ) ;
1365
+ Err ( ReadCellError :: Recomputing ( listener) )
1366
+ }
1367
+ Scheduled { ref event, .. } => {
1368
+ Err ( ReadCellError :: Recomputing ( event. listen_with_note ( note) ) )
1369
+ }
1309
1370
}
1310
1371
}
1311
1372
0 commit comments