Files
swift-mirror/stdlib/public/Concurrency/TaskLocal.cpp
2021-02-13 10:39:22 +09:00

115 lines
4.2 KiB
C++

//===--- TaskGroup.cpp - Task Group internal message channel ------------===//
//
// 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
//
//===----------------------------------------------------------------------===//
//
// Object management for task local values.
//
//===----------------------------------------------------------------------===//
#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();
fprintf(stderr, "FREE: %d\n", item);
free(item);
item = next;
break;
case TaskLocalValuesFragment::NextLinkType::IsParent:
case TaskLocalValuesFragment::NextLinkType::IsTerminal:
fprintf(stderr, "error: %s [%s:%d] done destroying [fragment:%d] type=%d\n", __FUNCTION__, __FILE_NAME__, __LINE__,
this, item->getNextLinkType());
// 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);
fprintf(stderr, "error: %s [%s:%d] PUSH bound item: task=%d item=%d -> item.next=%d keyType=%d item->getStoragePtr=%d\n", __FUNCTION__, __FILE_NAME__, __LINE__,
task, item, item->getNext(), keyType, item->getStoragePtr());
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;
fprintf(stderr, "error: %s [%s:%d] get @ [%d] keyType %d\n", __FUNCTION__, __FILE_NAME__, __LINE__,
item, keyType);
while (item) {
fprintf(stderr, "error: %s [%s:%d] loop, get; keyType=%d item=%d value=%d\n", __FUNCTION__, __FILE_NAME__, __LINE__,
keyType, item, item->getStoragePtr());
if (item->keyType == keyType) {
return item->getStoragePtr();
}
// if the hey 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();
}
fprintf(stderr, "error: %s [%s:%d] not found, get @ [%d] keyType %d\n", __FUNCTION__, __FILE_NAME__, __LINE__,
item, keyType);
return nullptr;
}