Skip to content

Commit 655d8f1

Browse files
committed
cleanup after rebase; this is likely incorrect in some way
1 parent 6f4fca8 commit 655d8f1

File tree

7 files changed

+81
-82
lines changed

7 files changed

+81
-82
lines changed

include/swift/ABI/TaskGroup.h

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
//===--- Task.h - ABI structures for asynchronous tasks ---------*- C++ -*-===//
1+
//===--- TaskGroup.h - ABI structures for task groups -00--------*- C++ -*-===//
22
//
33
// This source file is part of the Swift.org open source project
44
//
@@ -53,7 +53,7 @@ namespace swift {
5353
Error = 0b11,
5454
};
5555

56-
enum class GroupPollStatus : uintptr_t {
56+
enum class PollStatus : uintptr_t {
5757
/// The channel is known to be empty and we can immediately return nil.
5858
Empty = 0,
5959

@@ -70,7 +70,7 @@ namespace swift {
7070

7171
/// The result of waiting on a Channel (TaskGroup).
7272
struct PollResult {
73-
GroupPollStatus status; // TODO: pack it into storage pointer or not worth it?
73+
PollStatus status; // TODO: pack it into storage pointer or not worth it?
7474

7575
/// Storage for the result of the future.
7676
///
@@ -91,18 +91,18 @@ namespace swift {
9191
AsyncTask *retainedTask;
9292

9393
bool isStorageAccessible() {
94-
return status == GroupPollStatus::Success ||
95-
status == GroupPollStatus::Error ||
96-
status == GroupPollStatus::Empty;
94+
return status == PollStatus::Success ||
95+
status == PollStatus::Error ||
96+
status == PollStatus::Empty;
9797
}
9898

9999
static PollResult get(AsyncTask *asyncTask, bool hadErrorResult,
100100
bool needsSwiftRelease) {
101101
auto fragment = asyncTask->futureFragment();
102102
return PollResult{
103103
/*status*/ hadErrorResult ?
104-
TaskGroup::GroupPollStatus::Error :
105-
TaskGroup::GroupPollStatus::Success,
104+
TaskGroup::PollStatus::Error :
105+
TaskGroup::PollStatus::Success,
106106
/*storage*/ hadErrorResult ?
107107
reinterpret_cast<OpaqueValue *>(fragment->getError()) :
108108
fragment->getStoragePtr(),
@@ -380,9 +380,9 @@ namespace swift {
380380
/// Attempt to dequeue ready tasks and complete the waitingTask.
381381
///
382382
/// If unable to complete the waiting task immediately (with an readily
383-
/// available completed task), either returns an `GroupPollStatus::Empty`
383+
/// available completed task), either returns an `PollStatus::Empty`
384384
/// result if it is known that no pending tasks in the group,
385-
/// or a `GroupPollStatus::MustWait` result if there are tasks in flight
385+
/// or a `PollStatus::MustWait` result if there are tasks in flight
386386
/// and the waitingTask eventually be woken up by a completion.
387387
TaskGroup::PollResult poll(AsyncTask *waitingTask);
388388

include/swift/Runtime/Concurrency.h

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -161,19 +161,25 @@ SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swiftasync)
161161
TaskFutureWaitThrowingSignature::FunctionType
162162
swift_task_future_wait_throwing;
163163

164+
//using TaskFutureWaitSignature =
165+
// AsyncSignature<void(AsyncTask *, OpaqueValue *), /*throws*/ false>;
166+
167+
using TaskGroupFutureWaitSignature =
168+
AsyncSignature<void(AsyncTask *, TaskGroup *, OpaqueValue *), /*throws*/ true>; // TODO: is this correct?
169+
164170
/// Wait for a readyQueue of a Channel to become non empty.
165171
///
166172
/// This can be called from any thread. Its Swift signature is
167173
///
168174
/// \code
169-
/// func swift_task_group_wait_next(
175+
/// func swift_task_group_wait_next_throwing(
170176
/// waitingTask: Builtin.NativeObject, // current task
171177
/// group: Builtin.NativeObject,
172-
/// ) async -> (hadErrorResult: Bool, storage: UnsafeRawPointer?)
178+
/// ) async -> T
173179
/// \endcode
174180
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swiftasync)
175-
TaskFutureWaitSignature::FunctionType
176-
swift_task_group_wait_next;
181+
TaskGroupFutureWaitSignature::FunctionType
182+
swift_task_group_wait_next_throwing;
177183

178184
/// Create a new `TaskGroup` using the task's allocator.
179185
/// The caller is responsible for retaining and managing the group's lifecycle.

lib/IRGen/IRGenSIL.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2290,7 +2290,7 @@ static FunctionPointer::Kind classifyFunctionPointerKind(SILFunction *fn) {
22902290
return SpecialKind::TaskFutureWait;
22912291
if (name.equals("swift_task_future_wait_throwing"))
22922292
return SpecialKind::TaskFutureWaitThrowing;
2293-
if (name.equals("swift_task_group_wait_next"))
2293+
if (name.equals("swift_task_group_wait_next_throwing"))
22942294
return SpecialKind::TaskGroupWaitNext;
22952295
}
22962296

stdlib/public/Concurrency/TaskGroup.cpp

Lines changed: 32 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ void TaskGroup::destroy(AsyncTask *task) {
9393
bool taskDequeued = readyQueue.dequeue(item);
9494
while (taskDequeued) {
9595
swift_release(item.getTask());
96-
bool taskDequeued = readyQueue.dequeue(item);
96+
taskDequeued = readyQueue.dequeue(item);
9797
}
9898
mutex.unlock(); // TODO: remove fragment lock, and use status for synchronization
9999

@@ -105,17 +105,18 @@ void TaskGroup::destroy(AsyncTask *task) {
105105
// ==== offer ------------------------------------------------------------------
106106

107107
static void fillGroupNextResult(TaskFutureWaitAsyncContext *context,
108-
AsyncTask::GroupFragment::GroupPollResult result) {
108+
TaskGroup::PollResult result) {
109+
/// Fill in the result value
109110
switch (result.status) {
110-
case GroupFragment::GroupPollStatus::Waiting:
111+
case TaskGroup::PollStatus::MustWait:
111112
assert(false && "filling a waiting status?");
112113
return;
113114

114-
case GroupFragment::GroupPollStatus::Error:
115+
case TaskGroup::PollStatus::Error:
115116
context->fillWithError(reinterpret_cast<SwiftError*>(result.storage));
116117
return;
117118

118-
case GroupFragment::GroupPollStatus::Success: {
119+
case TaskGroup::PollStatus::Success: {
119120
// Initialize the result as an Optional<Success>.
120121
const Metadata *successType = context->successType;
121122
OpaqueValue *destPtr = context->successResultPointer;
@@ -127,7 +128,7 @@ static void fillGroupNextResult(TaskFutureWaitAsyncContext *context,
127128
return;
128129
}
129130

130-
case GroupFragment::GroupPollStatus::Empty: {
131+
case TaskGroup::PollStatus::Empty: {
131132
// Initialize the result as a nil Optional<Success>.
132133
const Metadata *successType = context->successType;
133134
OpaqueValue *destPtr = context->successResultPointer;
@@ -182,7 +183,14 @@ void TaskGroup::offer(AsyncTask *completedTask, AsyncContext *context,
182183
completedTask, hadErrorResult, /*needsRelease*/ false);
183184

184185
mutex.unlock(); // TODO: remove fragment lock, and use status for synchronization
185-
swift::runTaskWithPollResult(waitingTask, completingExecutor, result);
186+
// swift::runTaskWithPollResult(waitingTask, completingExecutor, result);
187+
auto waitingContext =
188+
static_cast<TaskFutureWaitAsyncContext *>(
189+
waitingTask->ResumeContext);
190+
fillGroupNextResult(waitingContext, result);
191+
192+
// TODO: allow the caller to suggest an executor
193+
swift_task_enqueueGlobal(waitingTask);
186194
return;
187195
} // else, try again
188196

@@ -216,31 +224,33 @@ void TaskGroup::offer(AsyncTask *completedTask, AsyncContext *context,
216224
// ==== group.next() implementation (wait_next and groupPoll) ------------------
217225

218226
SWIFT_CC(swiftasync)
219-
void swift::swift_task_group_wait_next(
227+
void swift::swift_task_group_wait_next_throwing(
220228
AsyncTask *waitingTask,
221229
ExecutorRef executor,
222230
SWIFT_ASYNC_CONTEXT AsyncContext *rawContext) {
223231
waitingTask->ResumeTask = rawContext->ResumeParent;
224232
waitingTask->ResumeContext = rawContext;
225233

226-
auto context = static_cast<TaskGroupNextWaitAsyncContext *>(rawContext);
234+
auto context = static_cast<TaskFutureWaitAsyncContext *>(rawContext);
227235
auto task = context->task;
228236
auto group = context->group;
229-
TaskGroup::PollResult polled = group->poll(waitingTask);
237+
fprintf(stderr, "[%s:%d](%s) group: %d\n", __FILE_NAME__, __LINE__, __FUNCTION__, group);
238+
239+
assert(group && "swift_task_group_wait_next_throwing was passed context without group!");
230240

231-
if (polled.status == TaskGroup::GroupPollStatus::MustWait) {
241+
TaskGroup::PollResult polled = group->poll(waitingTask);
242+
switch (polled.status) {
243+
case TaskGroup::PollStatus::MustWait:
232244
// The waiting task has been queued on the channel,
233245
// there were pending tasks so it will be woken up eventually.
234246
return;
235247

236-
case GroupFragment::GroupPollStatus::Empty:
237-
case GroupFragment::GroupPollStatus::Error:
238-
case GroupFragment::GroupPollStatus::Success:
248+
case TaskGroup::PollStatus::Empty:
249+
case TaskGroup::PollStatus::Error:
250+
case TaskGroup::PollStatus::Success:
239251
fillGroupNextResult(context, polled);
240252
return waitingTask->runInFullyEstablishedContext(executor);
241253
}
242-
243-
runTaskWithPollResult(waitingTask, executor, polled);
244254
}
245255

246256
TaskGroup::PollResult TaskGroup::poll(AsyncTask *waitingTask) {
@@ -257,7 +267,7 @@ TaskGroup::PollResult TaskGroup::poll(AsyncTask *waitingTask) {
257267
// was issued, and if we parked here we'd potentially never be woken up.
258268
// Bail out and return `nil` from `group.next()`.
259269
statusRemoveWaiting();
260-
result.status = TaskGroup::GroupPollStatus::Empty;
270+
result.status = TaskGroup::PollStatus::Empty;
261271
mutex.unlock(); // TODO: remove group lock, and use status for synchronization
262272
return result;
263273
}
@@ -277,7 +287,7 @@ TaskGroup::PollResult TaskGroup::poll(AsyncTask *waitingTask) {
277287
ReadyQueueItem item;
278288
bool taskDequeued = readyQueue.dequeue(item);
279289
if (!taskDequeued) {
280-
result.status = TaskGroup::GroupPollStatus::MustWait;
290+
result.status = TaskGroup::PollStatus::MustWait;
281291
result.storage = nullptr;
282292
result.retainedTask = nullptr;
283293
mutex.unlock(); // TODO: remove group lock, and use status for synchronization
@@ -294,23 +304,23 @@ TaskGroup::PollResult TaskGroup::poll(AsyncTask *waitingTask) {
294304
switch (item.getStatus()) {
295305
case ReadyStatus::Success:
296306
// Immediately return the polled value
297-
result.status = TaskGroup::GroupPollStatus::Success;
307+
result.status = TaskGroup::PollStatus::Success;
298308
result.storage = futureFragment->getStoragePtr();
299309
assert(result.retainedTask && "polled a task, it must be not null");
300310
mutex.unlock(); // TODO: remove fragment lock, and use status for synchronization
301311
return result;
302312

303313
case ReadyStatus::Error:
304314
// Immediately return the polled value
305-
result.status = TaskGroup::GroupPollStatus::Error;
315+
result.status = TaskGroup::PollStatus::Error;
306316
result.storage =
307317
reinterpret_cast<OpaqueValue *>(futureFragment->getError());
308318
assert(result.retainedTask && "polled a task, it must be not null");
309319
mutex.unlock(); // TODO: remove fragment lock, and use status for synchronization
310320
return result;
311321

312322
case ReadyStatus::Empty:
313-
result.status = TaskGroup::GroupPollStatus::Empty;
323+
result.status = TaskGroup::PollStatus::Empty;
314324
result.storage = nullptr;
315325
result.retainedTask = nullptr;
316326
mutex.unlock(); // TODO: remove fragment lock, and use status for synchronization
@@ -330,7 +340,7 @@ TaskGroup::PollResult TaskGroup::poll(AsyncTask *waitingTask) {
330340
/*failure*/ std::memory_order_acquire)) {
331341
mutex.unlock(); // TODO: remove fragment lock, and use status for synchronization
332342
// no ready tasks, so we must wait.
333-
result.status = TaskGroup::GroupPollStatus::MustWait;
343+
result.status = TaskGroup::PollStatus::MustWait;
334344
return result;
335345
} // else, try again
336346
}

stdlib/public/Concurrency/TaskGroup.swift

Lines changed: 27 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -219,29 +219,30 @@ extension Task {
219219
""")
220220
#endif
221221

222-
let rawResult = await _taskGroupWaitNext(waitingTask: _task, group: _group)
223-
224-
// FIXME: we are now in the parent task again, and can safely modify the
225-
// records again; we should remove this specific child from the
226-
// group->record
227-
228-
if rawResult.hadErrorResult {
229-
// Throw the result on error.
230-
let error = unsafeBitCast(rawResult.storage, to: Error.self)
231-
throw error
232-
}
233-
234-
guard let storage = rawResult.storage else {
235-
// The group was empty, return nil
236-
return nil
237-
}
238-
239-
// Take the value on success.
240-
let storagePtr =
241-
storage.bindMemory(to: TaskResult.self, capacity: 1)
242-
let value = UnsafeMutablePointer<TaskResult>(mutating: storagePtr).pointee
243-
244-
return value
222+
return try await _taskGroupWaitNext(waitingTask: _task, group: _group)
223+
// let rawResult = await _taskGroupWaitNext(waitingTask: _task, group: _group)
224+
//
225+
// // FIXME: we are now in the parent task again, and can safely modify the
226+
// // records again; we should remove this specific child from the
227+
// // group->record
228+
//
229+
// if rawResult.hadErrorResult {
230+
// // Throw the result on error.
231+
// let error = unsafeBitCast(rawResult.storage, to: Error.self)
232+
// throw error
233+
// }
234+
//
235+
// guard let storage = rawResult.storage else {
236+
// // The group was empty, return nil
237+
// return nil
238+
// }
239+
//
240+
// // Take the value on success.
241+
// let storagePtr =
242+
// storage.bindMemory(to: TaskResult.self, capacity: 1)
243+
// let value = UnsafeMutablePointer<TaskResult>(mutating: storagePtr).pointee
244+
//
245+
// return value
245246
}
246247

247248
/// Query whether the group has any remaining tasks.
@@ -363,13 +364,6 @@ func _taskGroupCreate(
363364
task: Builtin.NativeObject
364365
) -> Builtin.NativeObject
365366

366-
///// Attach the group to the task.
367-
//@_silgen_name("swift_task_group_attach")
368-
//func _taskGroupAttach(
369-
// group: Builtin.NativeObject,
370-
// to task: Builtin.NativeObject
371-
//) -> UnsafeRawPointer /*TaskGroupTaskStatusRecord*/
372-
373367
/// Attach task group child to the group group to the task.
374368
@_silgen_name("swift_task_group_attachChild")
375369
func _taskGroupAttachChild(
@@ -378,16 +372,6 @@ func _taskGroupAttachChild(
378372
child: Builtin.NativeObject
379373
) -> UnsafeRawPointer /*ChildTaskStatusRecord*/
380374

381-
///// Detach the group to the task.
382-
/////
383-
///// - Parameters:
384-
///// - record: the TaskGroupTaskStatusRecord returned by _taskGroupAttach
385-
//@_silgen_name("swift_task_group_detach")
386-
//func _taskGroupDetach(
387-
// record: UnsafeRawPointer,
388-
// from task: Builtin.NativeObject
389-
//)
390-
391375
@_silgen_name("swift_task_group_destroy")
392376
func _taskGroupDestroy(
393377
task: Builtin.NativeObject,
@@ -413,13 +397,13 @@ func _taskGroupIsCancelled(
413397
group: Builtin.NativeObject
414398
) -> Bool
415399

416-
@_silgen_name("swift_task_group_wait_next")
400+
@_silgen_name("swift_task_group_wait_next_throwing")
417401
func _taskGroupWaitNext<T>(
418402
waitingTask: Builtin.NativeObject,
419403
group: Builtin.NativeObject
420-
) async -> (hadErrorResult: Bool, storage: UnsafeRawPointer?)
404+
) async throws -> T?
421405

422-
enum GroupPollStatus: Int {
406+
enum PollStatus: Int {
423407
case empty = 0
424408
case waiting = 1
425409
case success = 2

stdlib/public/Concurrency/TaskPrivate.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ class TaskFutureWaitAsyncContext : public AsyncContext {
8282
AsyncTask *task;
8383

8484
// Only in swift_task_group_next
85+
TaskGroup *group;
8586
const Metadata *successType;
8687

8788
using AsyncContext::AsyncContext;

test/Concurrency/Runtime/async_taskgroup_next_on_completed.swift

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@ func test_sum_nextOnCompleted() async {
3333
var sum = 0
3434
do {
3535
while let r = try await group.next() {
36-
fputs("error: \(#function)[\(#file):\(#line)]: next: \(r)\n", stderr)
3736
print("next: \(r)")
3837
sum += r
3938
print("sum: \(sum)")
@@ -44,7 +43,6 @@ func test_sum_nextOnCompleted() async {
4443

4544
assert(group.isEmpty, "Group must be empty after we consumed all tasks")
4645

47-
fputs("error: \(#function)[\(#file):\(#line)]: group returning: \(sum)", stderr)
4846
print("task group returning: \(sum)")
4947
return sum
5048
}

0 commit comments

Comments
 (0)