@@ -464,7 +464,19 @@ impl<B: BackingStorage> TurboTasksBackendInner<B> {
464464        self . assert_not_persistent_calling_transient ( reader,  task_id,  /* cell_id */  None ) ; 
465465
466466        let  mut  ctx = self . execute_context ( turbo_tasks) ; 
467-         let  mut  task = ctx. task ( task_id,  TaskDataCategory :: All ) ; 
467+         let  ( mut  task,  reader_task)  = if  self . should_track_dependencies ( ) 
468+             && !matches ! ( options. tracking,  ReadTracking :: Untracked ) 
469+             && let  Some ( reader_id)  = reader
470+             && reader_id != task_id
471+         { 
472+             // Having a task_pair here is not optimal, but otherwise this would lead to a race 
473+             // condition. See below. 
474+             // TODO(sokra): solve that in a more performant way. 
475+             let  ( task,  reader)  = ctx. task_pair ( task_id,  reader_id,  TaskDataCategory :: All ) ; 
476+             ( task,  Some ( reader) ) 
477+         }  else  { 
478+             ( ctx. task ( task_id,  TaskDataCategory :: All ) ,  None ) 
479+         } ; 
468480
469481        fn  listen_to_done_event < B :  BackingStorage > ( 
470482            this :  & TurboTasksBackendInner < B > , 
@@ -707,18 +719,22 @@ impl<B: BackingStorage> TurboTasksBackendInner<B> {
707719                    ) ) ) 
708720                } 
709721            } ; 
710-             if  self . should_track_dependencies ( ) 
711-                 && let  Some ( reader)  = reader
722+             if  let  Some ( mut  reader_task)  = reader_task
712723                && options. tracking . should_track ( result. is_err ( ) ) 
713724                && ( !task. is_immutable ( )  || cfg ! ( feature = "verify_immutable" ) ) 
714725            { 
726+                 let  reader = reader. unwrap ( ) ; 
715727                let  _ = task. add ( CachedDataItem :: OutputDependent  { 
716728                    task :  reader, 
717729                    value :  ( ) , 
718730                } ) ; 
719731                drop ( task) ; 
720732
721-                 let  mut  reader_task = ctx. task ( reader,  TaskDataCategory :: Data ) ; 
733+                 // Note that there is a potential race condition here, if the reader task would be 
734+                 // locked after the task is unlocked. The output might be invalidated at 
735+                 // this point, but it wouldn't find the backward dependency or see an outdated 
736+                 // dependency. This way it would loose an invalidation. 
737+ 
722738                if  reader_task
723739                    . remove ( & CachedDataItemKey :: OutdatedOutputDependency  {  target :  task_id } ) 
724740                    . is_none ( ) 
@@ -732,6 +748,7 @@ impl<B: BackingStorage> TurboTasksBackendInner<B> {
732748
733749            return  result; 
734750        } 
751+         drop ( reader_task) ; 
735752
736753        let  note = move  || { 
737754            let  reader_desc = reader. map ( |r| self . get_task_desc_fn ( r) ) ; 
@@ -768,29 +785,23 @@ impl<B: BackingStorage> TurboTasksBackendInner<B> {
768785    )  -> Result < Result < TypedCellContent ,  EventListener > >  { 
769786        self . assert_not_persistent_calling_transient ( reader,  task_id,  Some ( cell) ) ; 
770787
771-         fn  add_cell_dependency < B :   BackingStorage > ( 
772-             backend :   & TurboTasksBackendInner < B > , 
788+         fn  add_cell_dependency ( 
789+             task_id :   TaskId , 
773790            mut  task :  impl  TaskGuard , 
774791            reader :  Option < TaskId > , 
792+             reader_task :  Option < impl  TaskGuard > , 
775793            cell :  CellId , 
776-             task_id :  TaskId , 
777-             ctx :  & mut  impl  ExecuteContext < ' _ > , 
778794        )  { 
779-             if  backend. should_track_dependencies ( ) 
780-                 && let  Some ( reader)  = reader
781-                 // We never want to have a dependency on ourselves, otherwise we end up in a 
782-                 // loop of re-executing the same task. 
783-                 && reader != task_id
795+             if  let  Some ( mut  reader_task)  = reader_task
784796                && ( !task. is_immutable ( )  || cfg ! ( feature = "verify_immutable" ) ) 
785797            { 
786798                let  _ = task. add ( CachedDataItem :: CellDependent  { 
787799                    cell, 
788-                     task :  reader, 
800+                     task :  reader. unwrap ( ) , 
789801                    value :  ( ) , 
790802                } ) ; 
791803                drop ( task) ; 
792804
793-                 let  mut  reader_task = ctx. task ( reader,  TaskDataCategory :: Data ) ; 
794805                let  target = CellRef  { 
795806                    task :  task_id, 
796807                    cell, 
@@ -805,7 +816,20 @@ impl<B: BackingStorage> TurboTasksBackendInner<B> {
805816        } 
806817
807818        let  mut  ctx = self . execute_context ( turbo_tasks) ; 
808-         let  mut  task = ctx. task ( task_id,  TaskDataCategory :: Data ) ; 
819+         let  ( mut  task,  reader_task)  = if  self . should_track_dependencies ( ) 
820+             && matches ! ( options. tracking,  ReadTracking :: Tracked ) 
821+             && let  Some ( reader_id)  = reader
822+             && reader_id != task_id
823+         { 
824+             // Having a task_pair here is not optimal, but otherwise this would lead to a race 
825+             // condition. See below. 
826+             // TODO(sokra): solve that in a more performant way. 
827+             let  ( task,  reader)  = ctx. task_pair ( task_id,  reader_id,  TaskDataCategory :: Data ) ; 
828+             ( task,  Some ( reader) ) 
829+         }  else  { 
830+             ( ctx. task ( task_id,  TaskDataCategory :: Data ) ,  None ) 
831+         } ; 
832+ 
809833        let  content = if  options. final_read_hint  { 
810834            remove ! ( task,  CellData  {  cell } ) 
811835        }  else  if  let  Some ( content)  = get ! ( task,  CellData  {  cell } )  { 
@@ -816,7 +840,7 @@ impl<B: BackingStorage> TurboTasksBackendInner<B> {
816840        } ; 
817841        if  let  Some ( content)  = content { 
818842            if  options. tracking . should_track ( false )  { 
819-                 add_cell_dependency ( self ,  task,  reader,  cell ,  task_id ,   & mut  ctx ) ; 
843+                 add_cell_dependency ( task_id ,  task,  reader,  reader_task ,  cell ) ; 
820844            } 
821845            return  Ok ( Ok ( TypedCellContent ( 
822846                cell. type_id , 
@@ -843,7 +867,7 @@ impl<B: BackingStorage> TurboTasksBackendInner<B> {
843867        . copied ( ) ; 
844868        let  Some ( max_id)  = max_id else  { 
845869            if  options. tracking . should_track ( true )  { 
846-                 add_cell_dependency ( self ,  task,  reader,  cell ,  task_id ,   & mut  ctx ) ; 
870+                 add_cell_dependency ( task_id ,  task,  reader,  reader_task ,  cell ) ; 
847871            } 
848872            bail ! ( 
849873                "Cell {cell:?} no longer exists in task {} (no cell of this type exists)" , 
@@ -852,7 +876,7 @@ impl<B: BackingStorage> TurboTasksBackendInner<B> {
852876        } ; 
853877        if  cell. index  >= max_id { 
854878            if  options. tracking . should_track ( true )  { 
855-                 add_cell_dependency ( self ,  task,  reader,  cell ,  task_id ,   & mut  ctx ) ; 
879+                 add_cell_dependency ( task_id ,  task,  reader,  reader_task ,  cell ) ; 
856880            } 
857881            bail ! ( 
858882                "Cell {cell:?} no longer exists in task {} (index out of bounds)" , 
0 commit comments