Files
swift-mirror/stdlib/public/Concurrency/TaskLocal.cpp
2021-02-13 20:09:11 +09:00

98 lines
3.2 KiB
C++

//===--- TaskLocal.cpp - Task Local Values --------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2020 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
#include "swift/Runtime/Concurrency.h"
#include "swift/ABI/Task.h"
#include "swift/ABI/Metadata.h"
using namespace swift;
using TaskLocalValuesFragment = AsyncTask::TaskLocalValuesFragment;
// =============================================================================
// ==== destroy ----------------------------------------------------------------
void TaskLocalValuesFragment::destroy() {
auto item = head;
head = nullptr;
TaskLocalItem *next;
while (item) {
switch (item->getNextLinkType()) {
case TaskLocalValuesFragment::NextLinkType::IsNext:
next = item->getNext();
item->destroy();
free(item);
item = next;
break;
case TaskLocalValuesFragment::NextLinkType::IsParent:
case TaskLocalValuesFragment::NextLinkType::IsTerminal:
// we're done here, we must not destroy values owned by the parent task.
return;
}
}
}
// =============================================================================
// ==== Initialization ---------------------------------------------------------
void TaskLocalValuesFragment::initializeLinkParent(AsyncTask* task,
AsyncTask* parent) {
assert(!head && "fragment was already initialized");
if (parent) {
head = TaskLocalItem::createParentLink(task, parent);
}
}
// =============================================================================
// ==== push / pop / get -------------------------------------------------------
void TaskLocalValuesFragment::pushValue(AsyncTask *task,
const Metadata *keyType,
/* +1 */ OpaqueValue *value,
const Metadata *valueType) {
assert(value && "Task local value must not be nil");
auto item = TaskLocalItem::createLink(task, keyType, valueType);
valueType->vw_initializeWithTake(item->getStoragePtr(), value);
head = item;
}
void TaskLocalValuesFragment::popValue(AsyncTask *task) {
assert(head && "attempted to pop value off empty task-local stack");
head->destroy();
head = head->getNext();
}
OpaqueValue *TaskLocalValuesFragment::get(
const Metadata *keyType,
const TaskLocalInheritance inherit) {
assert(keyType && "Task.Local key must not be null.");
auto item = head;
while (item) {
if (item->keyType == keyType) {
return item->getStoragePtr();
}
// if the key is an `inherit = .never` type, we stop our search the first
// time we would be jumping to a parent task to continue the search.
if (item->getNextLinkType() == NextLinkType::IsParent &&
inherit == TaskLocalInheritance::Never)
return nullptr;
item = item->getNext();
}
return nullptr;
}