Sane C++ Libraries
C++ Platform Abstraction Libraries
Loading...
Searching...
No Matches
Await.h
1// Copyright (c) Stefano Cristiano
2// SPDX-License-Identifier: MIT
3#pragma once
4
5#include "../Foundation/Compiler.h"
6#ifndef SC_EXPORT_LIBRARY_AWAIT
7#define SC_EXPORT_LIBRARY_AWAIT 0
8#endif
9#define SC_AWAIT_EXPORT SC_COMPILER_LIBRARY_EXPORT(SC_EXPORT_LIBRARY_AWAIT)
10
11#ifndef SC_AWAIT_REQUIRE_ARENA
12#define SC_AWAIT_REQUIRE_ARENA 0
13#endif
14
15#include "../Async/Async.h"
16#include "../Foundation/Result.h"
17#include "Internal/AwaitCoroutine.h"
18
25
28namespace SC
29{
30struct AwaitEventLoop;
31struct AwaitArena;
32struct AwaitTask;
33struct AwaitCancellationHandler;
34struct AwaitSleepAwaiter;
35struct AwaitSocketAcceptAwaiter;
36struct AwaitSocketConnectAwaiter;
37struct AwaitSocketSendAwaiter;
38struct AwaitSocketSendToAwaiter;
39struct AwaitSocketSendAllAwaiter;
40struct AwaitSocketSendAllBuffersAwaiter;
41struct AwaitSocketReceiveAwaiter;
42struct AwaitSocketReceiveExactAwaiter;
43struct AwaitSocketReceiveLineAwaiter;
44struct AwaitSocketReceiveFromAwaiter;
45struct AwaitLoopWakeUp;
46struct AwaitLoopWakeUpAwaiter;
47struct AwaitFileReadAwaiter;
48struct AwaitFileReadUntilFullOrEOFAwaiter;
49struct AwaitFileWriteAwaiter;
50struct AwaitFileSendAwaiter;
51struct AwaitFilePollAwaiter;
52struct AwaitFileSystemOperationAwaiter;
53struct AwaitProcessExitAwaiter;
54struct AwaitSignalAwaiter;
55struct AwaitTaskGroup;
56struct AwaitTaskGroupWaitAllAwaiter;
57struct AwaitTaskGroupWaitAnyAwaiter;
58struct AwaitTaskSpawnAwaiter;
59struct AwaitTaskTimeoutAwaiter;
60struct AwaitLoopWorkAwaiter;
61
62SC_AWAIT_EXPORT const char* AwaitCancellationMessage();
63SC_AWAIT_EXPORT Result AwaitCancelledResult();
64SC_AWAIT_EXPORT bool AwaitIsCancelled(Result result);
65
67#define SC_CO_TRY(expression) \
68 { \
69 if (auto _exprResConv = SC::Result(expression)) \
70 SC_LANGUAGE_LIKELY { (void)0; } \
71 else \
72 { \
73 co_return _exprResConv; \
74 } \
75 }
76
78{
79 size_t numBytes = 0;
80};
81
84{
85 Span<char> data;
86 bool disconnected = false;
87};
88
91{
92 Span<char> line;
93 bool disconnected = false;
94 bool lineComplete = false;
95};
96
99{
100 Span<char> data;
101 SocketIPAddress sourceAddress;
102 bool disconnected = false;
103};
104
107{
108 Span<char> data;
109 bool endOfFile = false;
110};
111
113{
114 size_t numBytes = 0;
115};
116
118{
119 ThreadPool* threadPool = nullptr;
120 uint64_t offset = 0;
121 bool useOffset = false;
122};
123
125{
126 ThreadPool* threadPool = nullptr;
127 uint64_t offset = 0;
128 bool useOffset = false;
129};
130
132{
133 int64_t offset = 0;
134 size_t length = 0;
135 size_t pipeSize = 0;
136 ThreadPool* threadPool = nullptr;
137};
138
140{
141 size_t bytesTransferred = 0;
142 bool usedZeroCopy = false;
143 bool complete = false;
144};
145
147{
148 bool timedOut = false;
149};
150
152{
153 int exitStatus = -1;
154};
155
157{
158 int signalNumber = 0;
159 uint32_t deliveryCount = 0;
160};
161
163{
164 uint32_t deliveryCount = 0;
165};
166
168{
169 size_t index = size_t(-1);
170 AwaitTask* task = nullptr;
171};
172
174{
175 size_t numTasks = 0;
176 size_t numCompleted = 0;
177 size_t numSucceeded = 0;
178 size_t numFailed = 0;
179 size_t firstFailureIndex = size_t(-1);
180 AwaitTask* firstFailureTask = nullptr;
181 Result firstFailure = Result(true);
182};
183
184enum class AwaitTaskGroupCancelPolicy : uint8_t
185{
186 CancelChildren,
187 LeaveChildrenRunning,
188};
189
190enum class AwaitTaskGroupWaitAnyPolicy : uint8_t
191{
192 CancelRemaining,
193 LeaveRemainingRunning,
194};
195
196enum class AwaitFileSystemOperationType : uint8_t
197{
198 Open,
199 Close,
200 Read,
201 Write,
202 CopyFile,
203 CopyDirectory,
204 Rename,
205 RemoveEmptyDirectory,
206 RemoveFile,
207};
208
211{
212 void* object = nullptr;
213
214 Result (*cancel)(void* object, AwaitEventLoop& eventLoop) = nullptr;
215};
216
218struct SC_AWAIT_EXPORT AwaitArena
219{
220 explicit AwaitArena(Span<char> memory);
221
222 [[nodiscard]] void* allocate(size_t size, size_t alignment);
223 void reset();
224
225 [[nodiscard]] size_t used() const;
226 [[nodiscard]] size_t capacity() const;
227 [[nodiscard]] size_t peakUsed() const;
228 [[nodiscard]] size_t failedAllocationSize() const;
229
230 private:
231 Span<char> storage;
232 size_t offset = 0;
233 size_t peakOffset = 0;
234 size_t lastFailedAllocationSize = 0;
235};
236
238struct SC_AWAIT_EXPORT AwaitTask
239{
240 struct Promise;
241 using promise_type = Promise;
242 using Handle = AwaitCoroutineTypedHandle<Promise>;
243
244 AwaitTask() = default;
245 explicit AwaitTask(Handle newHandle);
246
247 AwaitTask(const AwaitTask&) = delete;
248 AwaitTask& operator=(const AwaitTask&) = delete;
249
250 AwaitTask(AwaitTask&& other) noexcept;
251 AwaitTask& operator=(AwaitTask&& other) noexcept;
252 ~AwaitTask();
253
254 [[nodiscard]] bool isValid() const;
255 [[nodiscard]] bool isStarted() const;
256 [[nodiscard]] bool isCompleted() const;
257 [[nodiscard]] bool isActive() const;
258 [[nodiscard]] bool isCancellationRequested() const;
259
260 [[nodiscard]] Result result() const;
261
262 Result cancel(AwaitEventLoop& await);
263
264 bool await_ready() const;
265 bool await_suspend(Handle continuation);
266 Result await_resume() const;
267
268 private:
269 friend struct AwaitEventLoop;
270 friend struct AwaitTaskGroup;
271 friend struct AwaitTaskGroupWaitAllAwaiter;
272 friend struct AwaitTaskGroupWaitAnyAwaiter;
273 friend struct AwaitTaskSpawnAwaiter;
274 friend struct AwaitTaskTimeoutAwaiter;
275
276 Result start();
277 void resume();
278 void destroy();
279
280 Handle handle = {};
281};
282
284struct SC_AWAIT_EXPORT AwaitTask::Promise
285{
286 Promise();
287
288 template <typename First, typename... Rest>
289 Promise(First& first, Rest&... rest) : Promise()
290 {
291 eventLoop = findEventLoop(first, rest...);
292 }
293
294 static AwaitEventLoop* findEventLoop();
295 static AwaitEventLoop* findEventLoop(AwaitEventLoop& await);
296
297 template <typename First, typename... Rest>
298 static AwaitEventLoop* findEventLoop(First&, Rest&... rest)
299 {
300 return findEventLoop(rest...);
301 }
302
303 static void* allocateFrame(size_t size, AwaitEventLoop* eventLoop) noexcept;
304 static void deallocateFrame(void* frame) noexcept;
305
306 static void* operator new(size_t size) noexcept;
307
308 template <typename First, typename... Rest>
309 static void* operator new(size_t size, First& first, Rest&... rest) noexcept
310 {
311 return allocateFrame(size, findEventLoop(first, rest...));
312 }
313
314 static void operator delete(void* frame, size_t) noexcept;
315
316 static AwaitTask get_return_object_on_allocation_failure();
317
318 AwaitTask get_return_object();
319
320 AwaitSuspendAlways initial_suspend() noexcept;
321
323 {
324 bool await_ready() noexcept;
325 void await_suspend(AwaitTask::Handle handle) noexcept;
326 void await_resume() noexcept;
327 };
328
329 FinalSuspend final_suspend() noexcept;
330
331 void return_value(Result newResult) noexcept;
332
333 void unhandled_exception() noexcept;
334
335 Result taskResult;
336
337 AwaitTask::Handle continuation;
338 AwaitTask::Handle deferredDestroyNext;
339 AwaitCancellationHandler cancellation;
340 AwaitEventLoop* eventLoop;
341 void* completionObject;
342 void (*completionCallback)(void* object);
343
344 bool started;
345 bool completed;
346 bool cancellationRequested;
347 bool inCompletionCallback;
348 bool destroyDeferred;
349};
350
352struct SC_AWAIT_EXPORT AwaitEventLoop
353{
354 explicit AwaitEventLoop(AsyncEventLoop& asyncEventLoop, AwaitArena* arena = nullptr);
355
356 [[nodiscard]] AsyncEventLoop& asyncEventLoop();
357 [[nodiscard]] const AsyncEventLoop& asyncEventLoop() const;
358 [[nodiscard]] AwaitArena* arena();
359 [[nodiscard]] bool hasArena() const;
360
361 Result spawn(AwaitTask& task);
362
363 Result run();
364 Result runOnce();
365 Result runNoWait();
366
367 AwaitSleepAwaiter sleep(TimeMs duration);
368 AwaitSocketAcceptAwaiter accept(const SocketDescriptor& serverSocket, SocketDescriptor& outClient);
369 AwaitSocketConnectAwaiter connect(const SocketDescriptor& socket, SocketIPAddress address);
371 AwaitSocketSendResult* outResult = nullptr);
373 AwaitSocketSendResult* outResult = nullptr);
375 AwaitSocketSendResult* outResult = nullptr);
376 AwaitSocketSendToAwaiter sendTo(const SocketDescriptor& socket, SocketIPAddress address,
377 Span<Span<const char>> data, AwaitSocketSendResult* outResult = nullptr);
379 AwaitSocketSendResult* outResult = nullptr);
381 AwaitSocketSendResult* outResult = nullptr);
382 AwaitSocketReceiveAwaiter receive(const SocketDescriptor& socket, Span<char> buffer,
383 AwaitSocketReceiveResult& outResult);
384 AwaitSocketReceiveExactAwaiter receiveExact(const SocketDescriptor& socket, Span<char> buffer,
385 AwaitSocketReceiveResult* outResult = nullptr);
386 AwaitSocketReceiveLineAwaiter receiveLine(const SocketDescriptor& socket, Span<char> buffer,
388 AwaitSocketReceiveFromAwaiter receiveFrom(const SocketDescriptor& socket, Span<char> buffer,
390
391 AwaitFileReadAwaiter fileRead(const FileDescriptor& file, Span<char> buffer, AwaitFileReadResult& outResult,
392 AwaitFileReadOptions options = {});
393 AwaitFileReadUntilFullOrEOFAwaiter fileReadUntilFullOrEOF(const FileDescriptor& file, Span<char> buffer,
394 AwaitFileReadResult& outResult,
395 AwaitFileReadOptions options = {});
396
397 AwaitFileWriteAwaiter fileWrite(const FileDescriptor& file, Span<const char> data,
398 AwaitFileWriteResult* outResult = nullptr, AwaitFileWriteOptions options = {});
399 AwaitFileWriteAwaiter fileWrite(const FileDescriptor& file, Span<Span<const char>> data,
400 AwaitFileWriteResult* outResult = nullptr, AwaitFileWriteOptions options = {});
401 AwaitFileSendAwaiter fileSend(const FileDescriptor& file, const SocketDescriptor& socket,
402 AwaitFileSendResult& outResult, AwaitFileSendOptions options = {});
403 AwaitFilePollAwaiter filePoll(const FileDescriptor& file);
404
406 AsyncLoopWakeUpOptions options = {});
407
408 AwaitFileSystemOperationAwaiter fsOpen(ThreadPool& threadPool, StringSpan path, FileOpen mode,
409 FileDescriptor& outFile);
412 AwaitFileReadResult& outResult, uint64_t offset = 0);
414 AwaitFileWriteResult* outResult = nullptr, uint64_t offset = 0);
415 AwaitFileSystemOperationAwaiter fsCopyFile(ThreadPool& threadPool, StringSpan path, StringSpan destinationPath,
417 AwaitFileSystemOperationAwaiter fsCopyDirectory(ThreadPool& threadPool, StringSpan path, StringSpan destinationPath,
419 AwaitFileSystemOperationAwaiter fsRename(ThreadPool& threadPool, StringSpan path, StringSpan newPath);
420 AwaitFileSystemOperationAwaiter fsRemoveEmptyDirectory(ThreadPool& threadPool, StringSpan path);
421 AwaitFileSystemOperationAwaiter fsRemoveFile(ThreadPool& threadPool, StringSpan path);
422 AwaitProcessExitAwaiter processExit(FileDescriptor::Handle process, AwaitProcessExitResult& outResult);
423 AwaitSignalAwaiter signal(int signalNumber, AwaitSignalResult& outResult);
424 AwaitTaskSpawnAwaiter spawnAndWait(AwaitTask& task);
425 AwaitTaskTimeoutAwaiter waitFor(AwaitTask& task, TimeMs timeout, AwaitTimeoutResult* outResult = nullptr);
426 AwaitLoopWorkAwaiter loopWork(ThreadPool& threadPool, Function<Result()> work);
427
428 private:
429 friend struct AwaitTask;
430
431 void deferDestroy(AwaitTask::Handle handle);
432 void drainDeferredDestroys();
433
434 AsyncEventLoop& eventLoop;
435 AwaitArena* frameArena;
436 AwaitTask::Handle deferredDestroyList;
437};
438
440struct SC_AWAIT_EXPORT AwaitLoopWakeUp
441{
442 Result wakeUp(AwaitEventLoop& await);
443 Result wakeUp(AsyncEventLoop& eventLoop);
444
445 [[nodiscard]] bool isActive() const;
446
447 private:
448 friend struct AwaitLoopWakeUpAwaiter;
449
450 AsyncLoopWakeUp request;
451};
452
454struct SC_AWAIT_EXPORT AwaitSleepAwaiter
455{
456 AwaitSleepAwaiter(AwaitEventLoop& await, TimeMs duration);
457
458 AwaitEventLoop& await;
459 TimeMs duration;
460 AsyncLoopTimeout request;
461 Result operationResult = Result(true);
462
463 bool await_ready() const;
464 bool await_suspend(AwaitTask::Handle continuation);
465 Result await_resume();
466
467 private:
468 static Result cancel(void* object, AwaitEventLoop& eventLoop);
469
470 Result cancel(AwaitEventLoop& eventLoop);
471
472 AwaitTask::Handle continuation;
473 Function<void(AsyncResult&)> stopCallback;
474};
475
477struct SC_AWAIT_EXPORT AwaitLoopWakeUpAwaiter
478{
480 AsyncLoopWakeUpOptions options);
481
482 AwaitEventLoop& await;
483 AwaitLoopWakeUp& wakeUp;
484 AwaitLoopWakeUpResult& outResult;
486 Result operationResult = Result(true);
487
488 bool await_ready() const;
489 bool await_suspend(AwaitTask::Handle continuation);
490 Result await_resume();
491
492 private:
493 static Result cancel(void* object, AwaitEventLoop& eventLoop);
494
495 Result cancel(AwaitEventLoop& eventLoop);
496
497 AwaitTask::Handle continuation;
498 Function<void(AsyncResult&)> stopCallback;
499};
500
502struct SC_AWAIT_EXPORT AwaitSocketAcceptAwaiter
503{
504 AwaitSocketAcceptAwaiter(AwaitEventLoop& await, const SocketDescriptor& serverSocket, SocketDescriptor& outClient);
505
506 AwaitEventLoop& await;
507 const SocketDescriptor& serverSocket;
508 SocketDescriptor& outClient;
509 AsyncSocketAccept request;
510 Result operationResult = Result(true);
511
512 bool await_ready() const;
513 bool await_suspend(AwaitTask::Handle continuation);
514 Result await_resume();
515
516 private:
517 static Result cancel(void* object, AwaitEventLoop& eventLoop);
518
519 Result cancel(AwaitEventLoop& eventLoop);
520
521 AwaitTask::Handle continuation;
522 Function<void(AsyncResult&)> stopCallback;
523};
524
526struct SC_AWAIT_EXPORT AwaitSocketConnectAwaiter
527{
529
530 AwaitEventLoop& await;
531 const SocketDescriptor& socket;
532 SocketIPAddress address;
533 AsyncSocketConnect request;
534 Result operationResult = Result(true);
535
536 bool await_ready() const;
537 bool await_suspend(AwaitTask::Handle continuation);
538 Result await_resume();
539
540 private:
541 static Result cancel(void* object, AwaitEventLoop& eventLoop);
542
543 Result cancel(AwaitEventLoop& eventLoop);
544
545 AwaitTask::Handle continuation;
546 Function<void(AsyncResult&)> stopCallback;
547};
548
550struct SC_AWAIT_EXPORT AwaitSocketSendAwaiter
551{
553 AwaitSocketSendResult* outResult);
555 AwaitSocketSendResult* outResult);
556
557 AwaitEventLoop& await;
558 const SocketDescriptor& socket;
559 Span<const char> data;
560 Span<Span<const char>> buffers;
561 AwaitSocketSendResult* outResult = nullptr;
562 AsyncSocketSend request;
563 Result operationResult = Result(true);
564 bool singleBuffer = true;
565
566 bool await_ready() const;
567 bool await_suspend(AwaitTask::Handle continuation);
568 Result await_resume();
569
570 private:
571 static Result cancel(void* object, AwaitEventLoop& eventLoop);
572
573 Result cancel(AwaitEventLoop& eventLoop);
574
575 AwaitTask::Handle continuation;
576 Function<void(AsyncResult&)> stopCallback;
577};
578
580struct SC_AWAIT_EXPORT AwaitSocketSendToAwaiter
581{
583 Span<const char> data, AwaitSocketSendResult* outResult);
586
587 AwaitEventLoop& await;
588 const SocketDescriptor& socket;
589 SocketIPAddress address;
590 Span<const char> data;
591 Span<Span<const char>> buffers;
592 AwaitSocketSendResult* outResult = nullptr;
593 AsyncSocketSendTo request;
594 Result operationResult = Result(true);
595 bool singleBuffer = true;
596
597 bool await_ready() const;
598 bool await_suspend(AwaitTask::Handle continuation);
599 Result await_resume();
600
601 private:
602 static Result cancel(void* object, AwaitEventLoop& eventLoop);
603
604 Result cancel(AwaitEventLoop& eventLoop);
605
606 AwaitTask::Handle continuation;
607 Function<void(AsyncResult&)> stopCallback;
608};
609
611struct SC_AWAIT_EXPORT AwaitSocketSendAllAwaiter
612{
614 AwaitSocketSendResult* outResult);
615
616 AwaitEventLoop& await;
617 const SocketDescriptor& socket;
618 Span<const char> data;
619 AwaitSocketSendResult* outResult = nullptr;
620 AsyncSocketSend request;
621 Result operationResult = Result(true);
622 size_t numBytesSent = 0;
623
624 bool await_ready() const;
625 bool await_suspend(AwaitTask::Handle continuation);
626 Result await_resume();
627
628 private:
629 static Result cancel(void* object, AwaitEventLoop& eventLoop);
630
631 Result cancel(AwaitEventLoop& eventLoop);
632
633 AwaitTask::Handle continuation;
634 Function<void(AsyncResult&)> stopCallback;
635};
636
639{
641 AwaitSocketSendResult* outResult);
642
643 AwaitEventLoop& await;
644 const SocketDescriptor& socket;
646 AwaitSocketSendResult* outResult = nullptr;
647 AsyncSocketSend request;
648 AsyncLoopTimeout deferredStart;
649 Result operationResult = Result(true);
650 size_t numBytesSent = 0;
651 size_t bufferIndex = 0;
652 size_t bufferOffset = 0;
653
654 bool await_ready() const;
655 bool await_suspend(AwaitTask::Handle continuation);
656 Result await_resume();
657
658 private:
659 static Result cancel(void* object, AwaitEventLoop& eventLoop);
660
661 Result cancel(AwaitEventLoop& eventLoop);
662 bool findNextBuffer();
663 Result startCurrentBuffer();
664 Result updateRequestBuffer();
665
666 AwaitTask::Handle continuation;
667 Function<void(AsyncResult&)> stopCallback;
668};
669
671struct SC_AWAIT_EXPORT AwaitSocketReceiveAwaiter
672{
674 AwaitSocketReceiveResult& outResult);
675
676 AwaitEventLoop& await;
677 const SocketDescriptor& socket;
678 Span<char> buffer;
679 AwaitSocketReceiveResult& outResult;
680 AsyncSocketReceive request;
681 Result operationResult = Result(true);
682
683 bool await_ready() const;
684 bool await_suspend(AwaitTask::Handle continuation);
685 Result await_resume();
686
687 private:
688 static Result cancel(void* object, AwaitEventLoop& eventLoop);
689
690 Result cancel(AwaitEventLoop& eventLoop);
691
692 AwaitTask::Handle continuation;
693 Function<void(AsyncResult&)> stopCallback;
694};
695
697struct SC_AWAIT_EXPORT AwaitSocketReceiveExactAwaiter
698{
700 AwaitSocketReceiveResult* outResult);
701
702 AwaitEventLoop& await;
703 const SocketDescriptor& socket;
704 Span<char> buffer;
705 AwaitSocketReceiveResult* outResult = nullptr;
706 AsyncSocketReceive request;
707 Result operationResult = Result(true);
708 size_t numBytesReceived = 0;
709
710 bool await_ready() const;
711 bool await_suspend(AwaitTask::Handle continuation);
712 Result await_resume();
713
714 private:
715 static Result cancel(void* object, AwaitEventLoop& eventLoop);
716
717 Result cancel(AwaitEventLoop& eventLoop);
718 Result startRemainingReceive();
719 Result updateRequestBuffer();
720 Result updateOutResult(bool disconnected);
721
722 AwaitTask::Handle continuation;
723 Function<void(AsyncResult&)> stopCallback;
724};
725
727struct SC_AWAIT_EXPORT AwaitSocketReceiveLineAwaiter
728{
731
732 AwaitEventLoop& await;
733 const SocketDescriptor& socket;
734 Span<char> buffer;
736 AsyncSocketReceive request;
737 Result operationResult = Result(true);
738 size_t numBytesReceived = 0;
739 char currentByte = 0;
740 bool lineComplete = false;
741
742 bool await_ready() const;
743 bool await_suspend(AwaitTask::Handle continuation);
744 Result await_resume();
745
746 private:
747 static Result cancel(void* object, AwaitEventLoop& eventLoop);
748
749 Result cancel(AwaitEventLoop& eventLoop);
750 Result startNextByte();
751 Result updateOutResult(bool disconnected);
752
753 AwaitTask::Handle continuation;
754 Function<void(AsyncResult&)> stopCallback;
755};
756
758struct SC_AWAIT_EXPORT AwaitSocketReceiveFromAwaiter
759{
762
763 AwaitEventLoop& await;
764 const SocketDescriptor& socket;
765 Span<char> buffer;
768 Result operationResult = Result(true);
769
770 bool await_ready() const;
771 bool await_suspend(AwaitTask::Handle continuation);
772 Result await_resume();
773
774 private:
775 static Result cancel(void* object, AwaitEventLoop& eventLoop);
776
777 Result cancel(AwaitEventLoop& eventLoop);
778
779 AwaitTask::Handle continuation;
780 Function<void(AsyncResult&)> stopCallback;
781};
782
784struct SC_AWAIT_EXPORT AwaitFileReadAwaiter
785{
787 AwaitFileReadResult& outResult, AwaitFileReadOptions options);
788
789 AwaitEventLoop& await;
790 const FileDescriptor& file;
791 Span<char> buffer;
792 AwaitFileReadResult& outResult;
793 AsyncFileRead request;
794 AsyncTaskSequence taskSequence;
795 AwaitFileReadOptions options;
796 Result operationResult = Result(true);
797
798 bool await_ready() const;
799 bool await_suspend(AwaitTask::Handle continuation);
800 Result await_resume();
801
802 private:
803 static Result cancel(void* object, AwaitEventLoop& eventLoop);
804
805 Result cancel(AwaitEventLoop& eventLoop);
806
807 AwaitTask::Handle continuation;
808 Function<void(AsyncResult&)> stopCallback;
809};
810
813{
815 AwaitFileReadResult& outResult, AwaitFileReadOptions options);
816
817 AwaitEventLoop& await;
818 const FileDescriptor& file;
819 Span<char> buffer;
820 AwaitFileReadResult& outResult;
821 AsyncFileRead request;
822 AsyncTaskSequence taskSequence;
823 AwaitFileReadOptions options;
824 Result operationResult = Result(true);
825 size_t numBytesRead = 0;
826
827 bool await_ready() const;
828 bool await_suspend(AwaitTask::Handle continuation);
829 Result await_resume();
830
831 private:
832 static Result cancel(void* object, AwaitEventLoop& eventLoop);
833
834 Result cancel(AwaitEventLoop& eventLoop);
835 Result startRemainingRead();
836 Result updateRequestBufferAndOffset();
837 Result updateOutResult(bool endOfFile);
838
839 AwaitTask::Handle continuation;
840 Function<void(AsyncResult&)> stopCallback;
841};
842
844struct SC_AWAIT_EXPORT AwaitFileWriteAwaiter
845{
847 AwaitFileWriteResult* outResult, AwaitFileWriteOptions options);
849 AwaitFileWriteResult* outResult, AwaitFileWriteOptions options);
850
851 AwaitEventLoop& await;
852 const FileDescriptor& file;
853 Span<const char> data;
854 Span<Span<const char>> buffers;
855 AwaitFileWriteResult* outResult = nullptr;
856 AsyncFileWrite request;
857 AsyncTaskSequence taskSequence;
858 AwaitFileWriteOptions options;
859 Result operationResult = Result(true);
860 bool singleBuffer = true;
861
862 bool await_ready() const;
863 bool await_suspend(AwaitTask::Handle continuation);
864 Result await_resume();
865
866 private:
867 static Result cancel(void* object, AwaitEventLoop& eventLoop);
868
869 Result cancel(AwaitEventLoop& eventLoop);
870
871 AwaitTask::Handle continuation;
872 Function<void(AsyncResult&)> stopCallback;
873};
874
876struct SC_AWAIT_EXPORT AwaitFileSendAwaiter
877{
878 AwaitFileSendAwaiter(AwaitEventLoop& await, const FileDescriptor& file, const SocketDescriptor& socket,
879 AwaitFileSendResult& outResult, AwaitFileSendOptions options);
880
881 AwaitEventLoop& await;
882 const FileDescriptor& file;
883 const SocketDescriptor& socket;
884 AwaitFileSendResult& outResult;
885 AwaitFileSendOptions options;
886 AsyncFileSend request;
887 AsyncTaskSequence taskSequence;
888 Result operationResult = Result(true);
889
890 bool await_ready() const;
891 bool await_suspend(AwaitTask::Handle continuation);
892 Result await_resume();
893
894 private:
895 static Result cancel(void* object, AwaitEventLoop& eventLoop);
896
897 Result cancel(AwaitEventLoop& eventLoop);
898
899 AwaitTask::Handle continuation;
900 Function<void(AsyncResult&)> stopCallback;
901};
902
904struct SC_AWAIT_EXPORT AwaitFilePollAwaiter
905{
907
908 AwaitEventLoop& await;
909 const FileDescriptor& file;
910 AsyncFilePoll request;
911 Result operationResult = Result(true);
912
913 bool await_ready() const;
914 bool await_suspend(AwaitTask::Handle continuation);
915 Result await_resume();
916
917 private:
918 static Result cancel(void* object, AwaitEventLoop& eventLoop);
919
920 Result cancel(AwaitEventLoop& eventLoop);
921
922 AwaitTask::Handle continuation;
923 Function<void(AsyncResult&)> stopCallback;
924};
925
928{
930 AwaitFileSystemOperationType operation, StringSpan path,
931 StringSpan otherPath = StringSpan(), FileOpen mode = FileOpen(),
932 FileDescriptor* outFile = nullptr,
935 AwaitFileSystemOperationType operation, FileDescriptor& file);
937 AwaitFileSystemOperationType operation, FileDescriptor& file, Span<char> buffer,
938 AwaitFileReadResult& outResult, uint64_t offset);
940 AwaitFileSystemOperationType operation, FileDescriptor& file, Span<const char> data,
941 AwaitFileWriteResult* outResult, uint64_t offset);
942
943 AwaitEventLoop& await;
944 ThreadPool& threadPool;
945 AwaitFileSystemOperationType operation;
946 StringSpan path;
947 StringSpan otherPath;
948 FileOpen mode;
949 FileDescriptor* outFile = nullptr;
950 FileDescriptor* fileToClose = nullptr;
951 FileDescriptor* fileToUse = nullptr;
952 Span<char> readBuffer;
953 Span<const char> writeBuffer;
954 AwaitFileReadResult* outReadResult = nullptr;
955 AwaitFileWriteResult* outWriteResult = nullptr;
956 uint64_t offset = 0;
957 FileSystemCopyFlags copyFlags;
959 Result operationResult = Result(true);
960
961 bool await_ready() const;
962 bool await_suspend(AwaitTask::Handle continuation);
963 Result await_resume();
964
965 private:
966 static Result cancel(void* object, AwaitEventLoop& eventLoop);
967
968 Result cancel(AwaitEventLoop& eventLoop);
969
970 AwaitTask::Handle continuation;
971 Function<void(AsyncResult&)> stopCallback;
972};
973
975struct SC_AWAIT_EXPORT AwaitTaskGroup
976{
978 AwaitTaskGroupCancelPolicy cancelPolicy = AwaitTaskGroupCancelPolicy::CancelChildren);
979
980 Result spawn(AwaitTask& task);
984 AwaitTaskGroupWaitAnyPolicy waitAnyPolicy = AwaitTaskGroupWaitAnyPolicy::CancelRemaining);
985 Result collectResults(Span<Result> outResults, AwaitTaskGroupResultSummary* outSummary = nullptr) const;
986
987 [[nodiscard]] size_t size() const;
988 [[nodiscard]] size_t capacity() const;
989
990 private:
991 friend struct AwaitTaskGroupWaitAllAwaiter;
992 friend struct AwaitTaskGroupWaitAnyAwaiter;
993
994 AwaitEventLoop& await;
995 Span<AwaitTask*> tasks;
996 AwaitTaskGroupCancelPolicy cancelPolicy;
997 size_t numTasks = 0;
998};
999
1001struct SC_AWAIT_EXPORT AwaitTaskGroupWaitAllAwaiter
1002{
1004
1005 AwaitTaskGroup& group;
1006 Result operationResult = Result(true);
1007
1008 bool await_ready() const;
1009 bool await_suspend(AwaitTask::Handle continuation);
1010 Result await_resume();
1011
1012 private:
1013 static Result cancel(void* object, AwaitEventLoop& eventLoop);
1014 static void onTaskCompleted(void* object);
1015
1016 Result cancel(AwaitEventLoop& eventLoop);
1017 void onTaskCompleted();
1018 void finish(Result result);
1019 void clearChildCallbacks();
1020 Result collectResult() const;
1021
1022 AwaitTask::Handle continuation;
1023 size_t completedTasks = 0;
1024 bool finished = false;
1025};
1026
1028struct SC_AWAIT_EXPORT AwaitTaskGroupWaitAnyAwaiter
1029{
1031 AwaitTaskGroupWaitAnyPolicy waitAnyPolicy);
1032
1033 AwaitTaskGroup& group;
1034 AwaitTaskGroupWaitAnyResult& outResult;
1035 AwaitTaskGroupWaitAnyPolicy waitAnyPolicy;
1036 Result operationResult = Result(true);
1037
1038 bool await_ready() const;
1039 bool await_suspend(AwaitTask::Handle continuation);
1040 Result await_resume();
1041
1042 private:
1043 static Result cancel(void* object, AwaitEventLoop& eventLoop);
1044 static void onTaskCompleted(void* object);
1045
1046 Result cancel(AwaitEventLoop& eventLoop);
1047 void onTaskCompleted();
1048 void finish(Result result);
1049 void clearChildCallbacks();
1050 Result setWinner(size_t index);
1051 Result cancelRemaining(AwaitEventLoop& eventLoop);
1052
1053 AwaitTask::Handle continuation;
1054 size_t completedTasks = 0;
1055 size_t winnerIndex = size_t(-1);
1056 bool cancelling = false;
1057 bool finished = false;
1058};
1059
1061struct SC_AWAIT_EXPORT AwaitProcessExitAwaiter
1062{
1063 AwaitProcessExitAwaiter(AwaitEventLoop& await, FileDescriptor::Handle process, AwaitProcessExitResult& outResult);
1064
1065 AwaitEventLoop& await;
1066 FileDescriptor::Handle process = FileDescriptor::Invalid;
1067 AwaitProcessExitResult& outResult;
1068 AsyncProcessExit request;
1069 Result operationResult = Result(true);
1070
1071 bool await_ready() const;
1072 bool await_suspend(AwaitTask::Handle continuation);
1073 Result await_resume();
1074
1075 private:
1076 static Result cancel(void* object, AwaitEventLoop& eventLoop);
1077
1078 Result cancel(AwaitEventLoop& eventLoop);
1079
1080 AwaitTask::Handle continuation;
1081 Function<void(AsyncResult&)> stopCallback;
1082};
1083
1085struct SC_AWAIT_EXPORT AwaitSignalAwaiter
1086{
1087 AwaitSignalAwaiter(AwaitEventLoop& await, int signalNumber, AwaitSignalResult& outResult);
1088
1089 AwaitEventLoop& await;
1090 int signalNumber = 0;
1091 AwaitSignalResult& outResult;
1092 AsyncSignal request;
1093 Result operationResult = Result(true);
1094
1095 bool await_ready() const;
1096 bool await_suspend(AwaitTask::Handle continuation);
1097 Result await_resume();
1098
1099 private:
1100 static Result cancel(void* object, AwaitEventLoop& eventLoop);
1101
1102 Result cancel(AwaitEventLoop& eventLoop);
1103
1104 AwaitTask::Handle continuation;
1105 Function<void(AsyncResult&)> stopCallback;
1106};
1107
1109struct SC_AWAIT_EXPORT AwaitTaskSpawnAwaiter
1110{
1112
1113 AwaitEventLoop& await;
1114 AwaitTask& task;
1115 Result operationResult = Result(true);
1116
1117 bool await_ready() const;
1118 bool await_suspend(AwaitTask::Handle continuation);
1119 Result await_resume();
1120
1121 private:
1122 static Result cancel(void* object, AwaitEventLoop& eventLoop);
1123
1124 Result cancel(AwaitEventLoop& eventLoop);
1125
1126 AwaitTask::Handle continuation;
1127};
1128
1130struct SC_AWAIT_EXPORT AwaitTaskTimeoutAwaiter
1131{
1132 AwaitTaskTimeoutAwaiter(AwaitEventLoop& await, AwaitTask& task, TimeMs timeout, AwaitTimeoutResult* outResult);
1133
1134 AwaitEventLoop& await;
1135 AwaitTask& task;
1136 TimeMs timeout;
1137 AwaitTimeoutResult* outResult = nullptr;
1138 AsyncLoopTimeout timeoutRequest;
1139 Result operationResult = Result(true);
1140
1141 bool await_ready() const;
1142 bool await_suspend(AwaitTask::Handle continuation);
1143 Result await_resume();
1144
1145 private:
1146 static Result cancel(void* object, AwaitEventLoop& eventLoop);
1147 static void onTaskCompleted(void* object);
1148
1149 Result cancel(AwaitEventLoop& eventLoop);
1150 void onTaskCompleted();
1151 void finish(Result result);
1152
1153 AwaitTask::Handle continuation;
1154 Function<void(AsyncResult&)> stopCallback;
1155 bool cancelling = false;
1156 bool childCompleted = false;
1157 bool timeoutStopped = false;
1158 bool timeoutFired = false;
1159 bool finished = false;
1160};
1161
1163struct SC_AWAIT_EXPORT AwaitLoopWorkAwaiter
1164{
1165 AwaitLoopWorkAwaiter(AwaitEventLoop& await, ThreadPool& threadPool, Function<Result()> work);
1166
1167 AwaitEventLoop& await;
1168 ThreadPool& threadPool;
1169 Function<Result()> work;
1170 AsyncLoopWork request;
1171 Result operationResult = Result(true);
1172
1173 bool await_ready() const;
1174 bool await_suspend(AwaitTask::Handle continuation);
1175 Result await_resume();
1176
1177 private:
1178 static Result cancel(void* object, AwaitEventLoop& eventLoop);
1179
1180 Result cancel(AwaitEventLoop& eventLoop);
1181
1182 AwaitTask::Handle continuation;
1183 Function<void(AsyncResult&)> stopCallback;
1184};
1185} // namespace SC
struct SC_FOUNDATION_EXPORT Function
Wraps function pointers, member functions and lambdas without ever allocating.
Definition Function.h:19
unsigned char uint8_t
Platform independent (1) byte unsigned int.
Definition PrimitiveTypes.h:27
decltype(sizeof(0)) size_t
Platform independent unsigned size type.
Definition PrimitiveTypes.h:45
unsigned long long uint64_t
Platform independent (8) bytes unsigned int.
Definition PrimitiveTypes.h:33
unsigned int uint32_t
Platform independent (4) bytes unsigned int.
Definition PrimitiveTypes.h:29
long long int64_t
Platform independent (8) bytes signed int.
Definition PrimitiveTypes.h:41
Asynchronous I/O (files, sockets, timers, processes, fs events, threads wake-up) (see Async) AsyncEve...
Definition Async.h:1397
Starts an handle polling operation.
Definition Async.h:932
Starts a file read operation, reading bytes from a file (or pipe).
Definition Async.h:778
Sends file contents to a socket using zero-copy when available (sendfile, TransmitFile).
Definition Async.h:982
Starts an asynchronous file system operation (open, close, read, write, sendFile, stat,...
Definition Async.h:1196
Starts a file write operation, writing bytes to a file (or pipe).
Definition Async.h:854
Starts a Timeout that is invoked only once after expiration (relative) time has passed.
Definition Async.h:310
Options for AsyncLoopWakeUp configuration.
Definition Async.h:335
Starts a wake-up operation, allowing threads to execute callbacks on loop thread.
Definition Async.h:358
Executes work in a thread pool and then invokes a callback on the event loop thread.
Definition Async.h:1143
Starts monitoring a process, notifying about its termination.
Definition Async.h:395
Base class for all async results (argument of completion callbacks).
Definition Async.h:265
Starts monitoring a signal, notifying about its reception.
Definition Async.h:457
Starts a socket accept operation, obtaining a new socket from a listening socket.
Definition Async.h:554
Starts a socket connect operation, connecting to a remote endpoint.
Definition Async.h:574
Starts an unconnected socket receive from operation, receiving bytes from a remote endpoint.
Definition Async.h:743
Starts a socket receive operation, receiving bytes from a remote endpoint.
Definition Async.h:686
Starts an unconnected socket send to operation, sending bytes to a remote endpoint.
Definition Async.h:654
Starts a socket send operation, sending bytes to a remote endpoint.
Definition Async.h:608
An AsyncSequence using a SC::ThreadPool to execute one or more SC::AsyncRequest in a background threa...
Definition Async.h:1124
Caller-owned monotonic arena for coroutine frame allocation.
Definition Await.h:219
Cancellation hook installed by the awaiter currently suspending an AwaitTask.
Definition Await.h:211
Coroutine-friendly wrapper around an existing AsyncEventLoop.
Definition Await.h:353
Awaiter for a single AsyncFilePoll operation.
Definition Await.h:905
Awaiter for a single AsyncFileRead operation.
Definition Await.h:785
Definition Await.h:118
Result object populated by AwaitEventLoop::fileRead.
Definition Await.h:107
Awaiter that reads until the caller buffer is full or EOF is reached.
Definition Await.h:813
Awaiter for a single AsyncFileSend operation.
Definition Await.h:877
Definition Await.h:132
Definition Await.h:140
Awaiter for selected AsyncFileSystemOperation path operations.
Definition Await.h:928
Awaiter for a single AsyncFileWrite operation.
Definition Await.h:845
Definition Await.h:125
Definition Await.h:113
Awaiter for a single AsyncLoopWakeUp delivery.
Definition Await.h:478
Definition Await.h:163
Stable wake-up object that can resume an AwaitLoopWakeUpAwaiter from another thread.
Definition Await.h:441
Awaiter for a single AsyncLoopWork operation.
Definition Await.h:1164
Awaiter for a single AsyncProcessExit operation.
Definition Await.h:1062
Definition Await.h:152
Awaiter for a single one-shot AsyncSignal operation.
Definition Await.h:1086
Definition Await.h:157
Awaiter for a single AsyncLoopTimeout operation.
Definition Await.h:455
Awaiter for a single AsyncSocketAccept operation.
Definition Await.h:503
Awaiter for a single AsyncSocketConnect operation.
Definition Await.h:527
Awaiter for a single AsyncSocketReceive operation.
Definition Await.h:672
Awaiter that reactivates AsyncSocketReceive until the whole caller buffer is filled.
Definition Await.h:698
Awaiter for a single AsyncSocketReceiveFrom operation.
Definition Await.h:759
Result object populated by AwaitEventLoop::receiveFrom.
Definition Await.h:99
Awaiter that reads a ' '-terminated line into caller-provided storage.
Definition Await.h:728
Result object populated by AwaitEventLoop::receiveLine.
Definition Await.h:91
Result object populated by AwaitEventLoop::receive.
Definition Await.h:84
Awaiter that reactivates AsyncSocketSend until the whole buffer is sent.
Definition Await.h:612
Awaiter that sends every buffer in a scatter/gather list.
Definition Await.h:639
Awaiter for a single AsyncSocketSend operation.
Definition Await.h:551
Definition Await.h:78
Awaiter for a single AsyncSocketSendTo operation.
Definition Await.h:581
Definition Await.h:174
Awaiter that waits for every active task in an AwaitTaskGroup.
Definition Await.h:1002
Awaiter that waits for the first active task in an AwaitTaskGroup to complete.
Definition Await.h:1029
Definition Await.h:168
Caller-storage structured group of child tasks owned by the current scope.
Definition Await.h:976
Awaiter that starts a child task if needed, then waits for it to complete.
Definition Await.h:1110
Awaiter that waits for a child task, cancelling it if a timeout expires first.
Definition Await.h:1131
Coroutine promise implementation used by AwaitTask.
Definition Await.h:285
Caller-owned coroutine task returning a plain SC::Result.
Definition Await.h:239
Definition Await.h:147
[UniqueHandleDeclaration2Snippet]
Definition File.h:128
Options used to open a file descriptor.
Definition File.h:99
A structure to describe copy flags.
Definition FileSystem.h:76
An ascii string used as boolean result. SC_TRY macro forwards errors to caller.
Definition Result.h:13
Low-level OS socket handle.
Definition Socket.h:159
Native representation of an IP Address.
Definition Socket.h:106
View over a contiguous sequence of items (pointer + size in elements).
Definition Span.h:29
An read-only view over a string (to avoid including Strings library when parsing is not needed).
Definition StringSpan.h:37
Simple thread pool that executes tasks in a fixed number of worker threads.
Definition ThreadPool.h:38
A vocabulary type representing a time interval in milliseconds since epoch.
Definition PrimitiveTypes.h:50