@@ -181,7 +181,7 @@ void TaskLocal::Storage::initializeLinkParent(AsyncTask* task,
181
181
if (!item)
182
182
return ;
183
183
184
- auto tail = TaskLocal::ParentTaskMarkerItem::create (task);
184
+ auto tail = TaskLocal::MarkerItem::createParentTaskMarker (task);
185
185
head = tail;
186
186
187
187
// Set of keys for which we already have copied to the new task.
@@ -234,18 +234,24 @@ void TaskLocal::Storage::initializeLinkParent(AsyncTask* task,
234
234
item = item->getNext ();
235
235
}
236
236
237
+ if (item && item->getKind () == Item::Kind::StopLookupMarker) {
238
+ // Stop marker also could have been created inside task group body
239
+ // But we don't need to copy it. Instead we can break the chain.
240
+ item = nullptr ;
241
+ }
242
+
237
243
// The next item is not the "risky one" so we can directly link to it,
238
244
// as we would have within normal child task relationships. E.g. this is
239
245
// a parent or next pointer to a "safe" (withValue { withTaskGroup { ... } })
240
246
// binding, so we re-link our current head to point at this item.
241
247
tail->setNext (item);
242
248
}
243
249
244
- TaskLocal::ParentTaskMarkerItem *
245
- TaskLocal::ParentTaskMarkerItem::create (AsyncTask *task ) {
246
- size_t amountToAllocate = sizeof (ParentTaskMarkerItem );
250
+ TaskLocal::MarkerItem * TaskLocal::MarkerItem::create (AsyncTask *task,
251
+ Item *next, Kind kind ) {
252
+ size_t amountToAllocate = sizeof (MarkerItem );
247
253
void *allocation = _swift_task_alloc_specific (task, amountToAllocate);
248
- return new (allocation) ParentTaskMarkerItem ( nullptr );
254
+ return new (allocation) MarkerItem (next, kind );
249
255
}
250
256
251
257
TaskLocal::ValueItem *TaskLocal::ValueItem::create (AsyncTask *task,
@@ -367,11 +373,12 @@ bool TaskLocal::Item::destroy(AsyncTask *task) {
367
373
cast<ValueItem>(this )->~ValueItem ();
368
374
break ;
369
375
case Kind::ParentTaskMarker:
370
- cast<ParentTaskMarkerItem>(this )->~ParentTaskMarkerItem ();
371
-
372
376
// we're done here; as we must not proceed into the parent owned values.
373
377
// we do have to destroy the item pointing at the parent/edge itself though.
374
378
stop = true ;
379
+ LLVM_FALLTHROUGH;
380
+ case Kind::StopLookupMarker:
381
+ cast<MarkerItem>(this )->~MarkerItem ();
375
382
break ;
376
383
}
377
384
@@ -442,6 +449,21 @@ bool TaskLocal::Storage::popValue(AsyncTask *task) {
442
449
return head != nullptr ;
443
450
}
444
451
452
+ void TaskLocal::Storage::pushStopLookup (AsyncTask *task) {
453
+ head = MarkerItem::createStopLookupMarker (task, head);
454
+ SWIFT_TASK_LOCAL_DEBUG_LOG (nullptr , " push stop node item:%p" , head);
455
+ }
456
+
457
+ void TaskLocal::Storage::popStopLookup (AsyncTask *task) {
458
+ assert (head && " attempted to pop stop node off empty task-local stack" );
459
+ assert (head->getKind () == Item::Kind::StopLookupMarker &&
460
+ " attempted to pop wrong node type" );
461
+ auto old = head;
462
+ SWIFT_TASK_LOCAL_DEBUG_LOG (nullptr , " pop stop node item:%p" , old);
463
+ head = head->getNext ();
464
+ old->destroy (task);
465
+ }
466
+
445
467
OpaqueValue* TaskLocal::Storage::getValue (AsyncTask *task,
446
468
const HeapObject *key) {
447
469
assert (key && " TaskLocal key must not be null." );
@@ -452,6 +474,8 @@ OpaqueValue* TaskLocal::Storage::getValue(AsyncTask *task,
452
474
if (valueItem->key == key) {
453
475
return valueItem->getStoragePtr ();
454
476
}
477
+ } else if (item->getKind () == Item::Kind::StopLookupMarker) {
478
+ break ;
455
479
}
456
480
457
481
item = item->getNext ();
@@ -487,10 +511,30 @@ void TaskLocal::Storage::copyTo(AsyncTask *target) {
487
511
" skip copy, already copied most recent value, value was [%p]" ,
488
512
valueItem->getStoragePtr ());
489
513
}
514
+ } else if (item->getKind () == Item::Kind::StopLookupMarker) {
515
+ break ;
490
516
}
491
517
item = item->getNext ();
492
518
}
493
519
}
494
520
521
+ TaskLocal::StopLookupScope::StopLookupScope () {
522
+ task = swift_task_getCurrent ();
523
+ storage = Storage::getCurrent (task);
524
+ if (storage && storage->isEmpty ()) {
525
+ storage = nullptr ;
526
+ }
527
+
528
+ if (storage) {
529
+ storage->pushStopLookup (task);
530
+ }
531
+ }
532
+
533
+ TaskLocal::StopLookupScope::~StopLookupScope () {
534
+ if (storage) {
535
+ storage->popStopLookup (task);
536
+ }
537
+ }
538
+
495
539
#define OVERRIDE_TASK_LOCAL COMPATIBILITY_OVERRIDE
496
540
#include " ../CompatibilityOverride/CompatibilityOverrideIncludePath.h"
0 commit comments