Sane C++ Libraries
C++ Platform Abstraction Libraries
Loading...
Searching...
No Matches
Async.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_ASYNC
7#define SC_EXPORT_LIBRARY_ASYNC 0
8#endif
9#define SC_ASYNC_EXPORT SC_COMPILER_LIBRARY_EXPORT(SC_EXPORT_LIBRARY_ASYNC)
10
11#include "../Async/Internal/IntrusiveDoubleLinkedList.h"
12#include "../File/File.h"
13#include "../FileSystem/FileSystem.h"
14#include "../Foundation/Function.h"
15#include "../Foundation/OpaqueObject.h"
16#include "../Socket/Socket.h"
17#include "../Threading/Atomic.h"
18#include "../Threading/ThreadPool.h"
19
20namespace SC
21{
22struct ThreadPool;
23struct ThreadPoolTask;
24struct EventObject;
25} // namespace SC
50
53namespace SC
54{
55struct AsyncEventLoop;
56struct AsyncResult;
57struct AsyncSequence;
58struct AsyncTaskSequence;
59
60namespace detail
61{
62struct AsyncWinOverlapped;
63struct AsyncWinOverlappedDefinition
64{
65 static constexpr int Windows = sizeof(void*) * 4 + sizeof(uint64_t);
66 static constexpr size_t Alignment = alignof(void*);
67
68 using Object = AsyncWinOverlapped;
69};
70using WinOverlappedOpaque = OpaqueObject<AsyncWinOverlappedDefinition>;
71
72struct AsyncWinWaitDefinition
73{
74 using Handle = FileDescriptor::Handle; // fd
75 static constexpr Handle Invalid = FileDescriptor::Invalid; // invalid fd
76
77 static Result releaseHandle(Handle& waitHandle);
78};
79struct SC_ASYNC_EXPORT WinWaitHandle : public UniqueHandle<AsyncWinWaitDefinition>
80{
81};
82} // namespace detail
83
122struct SC_ASYNC_EXPORT AsyncRequest
123{
124 AsyncRequest* next = nullptr;
125 AsyncRequest* prev = nullptr;
126
127 void setDebugName(const char* newDebugName);
128
130 void executeOn(AsyncSequence& sequence);
131
136
139
141 enum class Type : uint8_t
142 {
143 LoopTimeout,
144 LoopWakeUp,
145 LoopWork,
146 ProcessExit,
147 Signal,
148 SocketAccept,
149 SocketConnect,
150 SocketSend,
151 SocketSendTo,
152 SocketReceive,
153 SocketReceiveFrom,
154 FileRead,
155 FileWrite,
156 FileSend,
157 FilePoll,
158 FileSystemOperation,
159 };
160
163 AsyncRequest(Type type) : state(State::Free), type(type), flags(0), unused(0), userFlags(0) {}
164
171 Result stop(AsyncEventLoop& eventLoop, Function<void(AsyncResult&)>* afterStopped = nullptr);
172
174 [[nodiscard]] bool isFree() const;
175
177 [[nodiscard]] bool isCancelling() const;
178
180 [[nodiscard]] bool isActive() const;
181
183 [[nodiscard]] Type getType() const { return type; }
184
187
189 void setUserFlags(uint16_t externalFlags) { userFlags = externalFlags; }
190
192 uint16_t getUserFlags() const { return userFlags; }
193
195 [[nodiscard]] Function<void(AsyncResult&)>* getCloseCallback() { return closeCallback; }
196
197 [[nodiscard]] const Function<void(AsyncResult&)>* getCloseCallback() const { return closeCallback; }
198
199 protected:
200 Result checkState();
201
202 void queueSubmission(AsyncEventLoop& eventLoop);
203
204 AsyncSequence* sequence = nullptr;
205
206 AsyncTaskSequence* getTask();
207
208 private:
209 Function<void(AsyncResult&)>* closeCallback = nullptr;
210
211 friend struct AsyncEventLoop;
212 friend struct AsyncResult;
213
214 void markAsFree();
215
216 [[nodiscard]] static const char* TypeToString(Type type);
217 enum class State : uint8_t
218 {
219 Free, // not in any queue, this can be started with an async.start(...)
220 Setup, // when in submission queue waiting to be setup (after an async.start(...))
221 Submitting, // when in submission queue waiting to be activated or re-activated
222 Active, // when monitored by OS syscall or in activeLoopWakeUps / activeTimeouts queues
223 Reactivate, // when flagged for reactivation inside the callback (after a result.reactivateRequest(true))
224 Cancelling, // when in cancellation queue waiting for a cancelAsync (on active async)
225 };
226
227#if SC_ASYNC_ENABLE_LOG
228 const char* debugName = "None";
229#endif
230 State state; // 1 byte
231 Type type; // 1 byte
232 int16_t flags; // 2 bytes
233
234 uint16_t unused; // 2 bytes
235 uint16_t userFlags; // 2 bytes
236};
237
242struct SC_ASYNC_EXPORT AsyncSequence
243{
244 AsyncSequence* next = nullptr;
245 AsyncSequence* prev = nullptr;
246
247 bool clearSequenceOnCancel = true;
248 bool clearSequenceOnError = true;
249 private:
250 friend struct AsyncEventLoop;
251 bool runningAsync = false; // true if an async from this sequence is being run
252 bool tracked = false;
253
254 IntrusiveDoubleLinkedList<AsyncRequest> submissions;
255};
256
258struct SC_ASYNC_EXPORT AsyncCompletionData
259{
260};
261
264struct SC_ASYNC_EXPORT AsyncResult
265{
267 AsyncResult(AsyncEventLoop& eventLoop, AsyncRequest& request, SC::Result& res, bool* hasBeenReactivated = nullptr)
268 : eventLoop(eventLoop), async(request), hasBeenReactivated(hasBeenReactivated), returnCode(res)
269 {}
270
273 void reactivateRequest(bool shouldBeReactivated);
274
276 [[nodiscard]] const SC::Result& isValid() const { return returnCode; }
277
278 AsyncEventLoop& eventLoop;
279 AsyncRequest& async;
280
281 protected:
282 friend struct AsyncEventLoop;
283
284 bool shouldCallCallback = true;
285 bool* hasBeenReactivated = nullptr;
286
287 SC::Result& returnCode;
288};
289
293template <typename T, typename C>
295{
296 T& getAsync() { return static_cast<T&>(AsyncResult::async); }
297 const T& getAsync() const { return static_cast<const T&>(AsyncResult::async); }
298
300
301 C completionData;
302 int32_t eventIndex = 0;
303};
304
309struct SC_ASYNC_EXPORT AsyncLoopTimeout : public AsyncRequest
310{
311 AsyncLoopTimeout() : AsyncRequest(Type::LoopTimeout) {}
312
315 using AsyncRequest::start;
316
318 SC::Result start(AsyncEventLoop& eventLoop, TimeMs relativeTimeout);
319
321
323
325 TimeMs getExpirationTime() const { return expirationTime; }
326
327 private:
328 SC::Result validate(AsyncEventLoop&);
329 friend struct AsyncEventLoop;
330 TimeMs expirationTime;
331};
332
335{
338 bool coalesce = true;
339};
340
357struct SC_ASYNC_EXPORT AsyncLoopWakeUp : public AsyncRequest
358{
359 AsyncLoopWakeUp() : AsyncRequest(Type::LoopWakeUp) {}
360
362 {
363 uint32_t deliveryCount = 1;
364 };
365
367
370
372 SC::Result start(AsyncEventLoop& eventLoop, EventObject& eventObject, AsyncLoopWakeUpOptions options = {});
373
376
378 EventObject* eventObject = nullptr;
379
380 private:
381 friend struct AsyncEventLoop;
382 SC::Result validate(AsyncEventLoop&);
383 int32_t consumePendingWakeUps();
384 int32_t getPendingWakeUps() const;
385
386 AsyncLoopWakeUpOptions wakeUpOptions;
387 Atomic<int32_t> pendingWakeUps = 0;
388};
389
394struct SC_ASYNC_EXPORT AsyncProcessExit : public AsyncRequest
395{
396 AsyncProcessExit() : AsyncRequest(Type::ProcessExit) {}
397
399 {
400 int exitStatus;
401 };
402
403 struct Result : public AsyncResultOf<AsyncProcessExit, CompletionData>
404 {
405 using AsyncResultOf<AsyncProcessExit, CompletionData>::AsyncResultOf;
406
407 SC::Result get(int& status)
408 {
409 status = completionData.exitStatus;
410 return returnCode;
411 }
412 };
413 using AsyncRequest::start;
414
418 SC::Result start(AsyncEventLoop& eventLoop, FileDescriptor::Handle process);
419
421
422 private:
423 friend struct AsyncEventLoop;
424 SC::Result validate(AsyncEventLoop&);
425
426 FileDescriptor::Handle handle = FileDescriptor::Invalid;
427#if SC_PLATFORM_WINDOWS
429 detail::WinWaitHandle waitHandle;
430 AsyncEventLoop* eventLoop = nullptr;
431#elif SC_PLATFORM_LINUX
432 FileDescriptor pidFd;
433#endif
434};
435
438{
440 enum class Mode : uint8_t
441 {
442 Persistent,
443 OneShot
444 };
446 bool coalesce = true;
447};
448
456struct SC_ASYNC_EXPORT AsyncSignal : public AsyncRequest
457{
458 AsyncSignal() : AsyncRequest(Type::Signal) {}
459
461 {
462 int signalNumber = 0;
463 uint32_t deliveryCount = 1;
464 };
465
466 struct Result : public AsyncResultOf<AsyncSignal, CompletionData>
467 {
468 using AsyncResultOf<AsyncSignal, CompletionData>::AsyncResultOf;
469 };
470 using AsyncRequest::start;
471
473 SC::Result start(AsyncEventLoop& eventLoop, int num, AsyncSignalOptions options = {});
474
476
477 private:
478 friend struct AsyncEventLoop;
479 SC::Result validate(AsyncEventLoop&);
480
481 int signalNumber = 0;
482 AsyncSignalOptions signalOptions;
483#if SC_PLATFORM_WINDOWS
485 AsyncEventLoop* eventLoop = nullptr;
486#elif SC_PLATFORM_LINUX
487 FileDescriptor signalFd;
488 FileDescriptor::Handle signalFdHandle = FileDescriptor::Invalid;
489#endif
490};
491
492struct AsyncSocketAccept;
493namespace detail
494{
497struct SC_ASYNC_EXPORT AsyncSocketAcceptData
498{
499#if SC_PLATFORM_WINDOWS
500 void (*pAcceptEx)() = nullptr;
502 SocketDescriptor clientSocket;
503 uint8_t acceptBuffer[288] = {0};
504#elif SC_PLATFORM_LINUX
505 AlignedStorage<28> sockAddrHandle;
506 uint32_t sockAddrLen;
507#endif
508};
509
511struct SC_ASYNC_EXPORT AsyncSocketAcceptBase : public AsyncRequest
512{
513 AsyncSocketAcceptBase() : AsyncRequest(Type::SocketAccept) {}
514
515 struct CompletionData : public AsyncCompletionData
516 {
517 SocketDescriptor acceptedClient;
518 };
519
520 struct Result : public AsyncResultOf<AsyncSocketAccept, CompletionData>
521 {
522 using AsyncResultOf<AsyncSocketAccept, CompletionData>::AsyncResultOf;
523
524 SC::Result moveTo(SocketDescriptor& client)
525 {
526 SC_TRY(returnCode);
527 return client.assign(move(completionData.acceptedClient));
528 }
529 };
530 using AsyncRequest::start;
531
533 SC::Result start(AsyncEventLoop& eventLoop, const SocketDescriptor& socketDescriptor, AsyncSocketAcceptData& data);
534 SC::Result validate(AsyncEventLoop&);
535
536 Function<void(Result&)> callback;
537 SocketDescriptor::Handle handle = SocketDescriptor::Invalid;
538 SocketFlags::AddressFamily addressFamily = SocketFlags::AddressFamilyIPV4;
539 AsyncSocketAcceptData* acceptData = nullptr;
540};
541
542} // namespace detail
543
553struct SC_ASYNC_EXPORT AsyncSocketAccept : public detail::AsyncSocketAcceptBase
554{
555 AsyncSocketAccept() { AsyncSocketAcceptBase::acceptData = &data; }
556 using AsyncSocketAcceptBase::start;
557
559 SC::Result start(AsyncEventLoop& eventLoop, const SocketDescriptor& socketDescriptor);
560
561 private:
562 detail::AsyncSocketAcceptData data;
563};
564
573struct SC_ASYNC_EXPORT AsyncSocketConnect : public AsyncRequest
574{
575 AsyncSocketConnect() : AsyncRequest(Type::SocketConnect) {}
576
579 using AsyncRequest::start;
580
582 SC::Result start(AsyncEventLoop& eventLoop, const SocketDescriptor& descriptor, SocketIPAddress address);
583
585
586 SocketDescriptor::Handle handle = SocketDescriptor::Invalid;
587 SocketIPAddress ipAddress;
588
589 private:
590 friend struct AsyncEventLoop;
591 SC::Result validate(AsyncEventLoop&);
592
593#if SC_PLATFORM_WINDOWS
594 void (*pConnectEx)() = nullptr;
596#endif
597};
598
607struct SC_ASYNC_EXPORT AsyncSocketSend : public AsyncRequest
608{
609 AsyncSocketSend() : AsyncRequest(Type::SocketSend) {}
611 {
612 size_t numBytes = 0;
613 };
615 using AsyncRequest::start;
616
619
622
624
625 SocketDescriptor::Handle handle = SocketDescriptor::Invalid;
626
627 SC::Result closeHandle() { return detail::SocketDescriptorDefinition::releaseHandle(handle); }
628
631 bool singleBuffer = true;
632
633 protected:
634 AsyncSocketSend(Type type) : AsyncRequest(type) {}
635 friend struct AsyncEventLoop;
636 SC::Result validate(AsyncEventLoop&);
637
638 size_t totalBytesWritten = 0;
639#if SC_PLATFORM_WINDOWS
641#endif
642};
643
653struct SC_ASYNC_EXPORT AsyncSocketSendTo : public AsyncSocketSend
654{
655 AsyncSocketSendTo() : AsyncSocketSend(Type::SocketSendTo) {}
656
657 SocketIPAddress address;
658
659 SC::Result start(AsyncEventLoop& eventLoop, const SocketDescriptor& descriptor, SocketIPAddress ipAddress,
660 Span<const char> data);
661
662 SC::Result start(AsyncEventLoop& eventLoop, const SocketDescriptor& descriptor, SocketIPAddress ipAddress,
663 Span<Span<const char>> data);
664
665 private:
666 using AsyncSocketSend::start;
667 friend struct AsyncEventLoop;
668 SC::Result validate(AsyncEventLoop&);
669#if SC_PLATFORM_LINUX
670 AlignedStorage<56> typeErasedMsgHdr;
671#endif
672};
673
685struct SC_ASYNC_EXPORT AsyncSocketReceive : public AsyncRequest
686{
687 AsyncSocketReceive() : AsyncRequest(Type::SocketReceive) {}
688
690 {
691 size_t numBytes = 0;
692 bool disconnected = false;
693 };
694
695 struct Result : public AsyncResultOf<AsyncSocketReceive, CompletionData>
696 {
697 using AsyncResultOf<AsyncSocketReceive, CompletionData>::AsyncResultOf;
698
699 bool isEnded() const { return completionData.disconnected; }
700
705 {
706 SC_TRY(getAsync().buffer.sliceStartLength(0, completionData.numBytes, outData));
707 return returnCode;
708 }
709
710 SocketIPAddress getSourceAddress() const;
711 };
712 using AsyncRequest::start;
713
715 SC::Result start(AsyncEventLoop& eventLoop, const SocketDescriptor& descriptor, Span<char> data);
716
718
720 SocketDescriptor::Handle handle = SocketDescriptor::Invalid;
721
722 SC::Result closeHandle() { return detail::SocketDescriptorDefinition::releaseHandle(handle); }
723
724 protected:
725 AsyncSocketReceive(Type type) : AsyncRequest(type) {}
726 friend struct AsyncEventLoop;
727 SC::Result validate(AsyncEventLoop&);
728#if SC_PLATFORM_WINDOWS
729 detail::WinOverlappedOpaque overlapped;
730#endif
731};
732
742struct SC_ASYNC_EXPORT AsyncSocketReceiveFrom : public AsyncSocketReceive
743{
744 AsyncSocketReceiveFrom() : AsyncSocketReceive(Type::SocketReceiveFrom) {}
745 using AsyncSocketReceive::start;
746
747 private:
748 SocketIPAddress address;
749 friend struct AsyncSocketReceive;
750 friend struct AsyncEventLoop;
751#if SC_PLATFORM_LINUX
752 AlignedStorage<56> typeErasedMsgHdr;
753#endif
754};
755
777struct SC_ASYNC_EXPORT AsyncFileRead : public AsyncRequest
778{
779 AsyncFileRead() : AsyncRequest(Type::FileRead) { handle = FileDescriptor::Invalid; }
780
782 {
783 size_t numBytes = 0;
784 bool endOfFile = false;
785 };
786
787 struct Result : public AsyncResultOf<AsyncFileRead, CompletionData>
788 {
789 using AsyncResultOf<AsyncFileRead, CompletionData>::AsyncResultOf;
790
791 bool isEnded() const { return completionData.endOfFile; }
792
793 SC::Result get(Span<char>& data)
794 {
795 SC_TRY(getAsync().buffer.sliceStartLength(0, completionData.numBytes, data));
796 return returnCode;
797 }
798 };
799 using AsyncRequest::start;
800
802 SC::Result start(AsyncEventLoop& eventLoop, const FileDescriptor& descriptor, Span<char> data);
803
804 Function<void(Result&)> callback;
806 FileDescriptor::Handle handle;
808
809 SC::Result closeHandle() { return detail::FileDescriptorDefinition::releaseHandle(handle); }
810
812 uint64_t getOffset() const { return offset; }
813
816 void setOffset(uint64_t fileOffset)
817 {
818 useOffset = true;
819 offset = fileOffset;
820 }
821
822 private:
823 friend struct AsyncEventLoop;
824 SC::Result validate(AsyncEventLoop&);
825
826 bool useOffset = false;
827 bool endedSync = false;
828
829 uint64_t offset = 0;
830#if SC_PLATFORM_WINDOWS
831 uint64_t readCursor = 0;
833#endif
834};
835
853struct SC_ASYNC_EXPORT AsyncFileWrite : public AsyncRequest
854{
855 AsyncFileWrite() : AsyncRequest(Type::FileWrite) { handle = FileDescriptor::Invalid; }
856
858 {
859 size_t numBytes = 0;
860 };
861
862 struct Result : public AsyncResultOf<AsyncFileWrite, CompletionData>
863 {
864 using AsyncResultOf<AsyncFileWrite, CompletionData>::AsyncResultOf;
865
866 SC::Result get(size_t& writtenSizeInBytes)
867 {
868 writtenSizeInBytes = completionData.numBytes;
869 return returnCode;
870 }
871 };
872
873 using AsyncRequest::start;
874
876 SC::Result start(AsyncEventLoop& eventLoop, const FileDescriptor& descriptor, Span<Span<const char>> data);
877
880
882 SC::Result start(AsyncEventLoop& eventLoop, const FileDescriptor& descriptor, Span<const char> data);
883
886
888
889 FileDescriptor::Handle handle;
891
892 SC::Result closeHandle() { return detail::FileDescriptorDefinition::releaseHandle(handle); }
893
896 bool singleBuffer = true;
897
899 uint64_t getOffset() const { return offset; }
900
903 void setOffset(uint64_t fileOffset)
904 {
905 useOffset = true;
906 offset = fileOffset;
907 }
908
909 private:
910 friend struct AsyncEventLoop;
911 SC::Result validate(AsyncEventLoop&);
912
913#if SC_PLATFORM_WINDOWS
914 bool endedSync = false;
915#else
916 bool isWatchable = false;
917#endif
918 bool useOffset = false;
919 uint64_t offset = 0xffffffffffffffff;
920
921 size_t totalBytesWritten = 0;
922#if SC_PLATFORM_WINDOWS
924#endif
925};
926
931struct SC_ASYNC_EXPORT AsyncFilePoll : public AsyncRequest
932{
933 AsyncFilePoll() : AsyncRequest(Type::FilePoll) {}
934
937
939 SC::Result start(AsyncEventLoop& eventLoop, FileDescriptor::Handle fileDescriptor);
940
941#if SC_PLATFORM_WINDOWS
942 [[nodiscard]] void* getOverlappedPtr();
943#endif
944
945 Function<void(Result&)> callback;
946
947 private:
948 friend struct AsyncEventLoop;
949 SC::Result validate(AsyncEventLoop&);
950
951 FileDescriptor::Handle handle = FileDescriptor::Invalid;
952#if SC_PLATFORM_WINDOWS
954#endif
955};
956
981struct SC_ASYNC_EXPORT AsyncFileSend : public AsyncRequest
982{
983 AsyncFileSend() : AsyncRequest(Type::FileSend) {}
984
986 {
987 size_t bytesTransferred = 0;
988 bool usedZeroCopy = false;
989 };
990
991 struct Result : public AsyncResultOf<AsyncFileSend, CompletionData>
992 {
993 using AsyncResultOf<AsyncFileSend, CompletionData>::AsyncResultOf;
994
996 [[nodiscard]] size_t getBytesTransferred() const { return completionData.bytesTransferred; }
997
999 [[nodiscard]] bool usedZeroCopy() const { return completionData.usedZeroCopy; }
1000
1002 [[nodiscard]] bool isComplete() const
1003 {
1004 return returnCode && completionData.bytesTransferred == getAsync().length;
1005 }
1006 };
1007
1008 using AsyncRequest::start;
1009
1019 SC::Result start(AsyncEventLoop& eventLoop, const FileDescriptor& file, const SocketDescriptor& socket,
1020 int64_t offset = 0, size_t length = 0, size_t pipeSize = 0);
1021
1023
1024 // Internal handles (set by start())
1025 FileDescriptor::Handle fileHandle = FileDescriptor::Invalid;
1026 SocketDescriptor::Handle socketHandle = SocketDescriptor::Invalid;
1027
1028 int64_t offset = 0;
1029 size_t length = 0;
1030 size_t bytesSent = 0;
1031 private:
1032 friend struct AsyncEventLoop;
1033 SC::Result validate(AsyncEventLoop&);
1034
1035#if SC_PLATFORM_WINDOWS
1036 detail::WinOverlappedOpaque overlapped;
1037#elif SC_PLATFORM_LINUX
1038 size_t pipeBufferSize = 0;
1039 PipeDescriptor splicePipe;
1040#endif
1041};
1042
1043// forward declared because it must be defined after AsyncTaskSequence
1044struct AsyncLoopWork;
1046
1048{
1049 FileDescriptor::Handle handle = FileDescriptor::Invalid; // for open
1050
1051 int code = 0; // for open/close
1052 size_t numBytes = 0; // for read
1053};
1054
1055namespace detail
1056{
1057// A simple hand-made variant of all completion types
1058struct SC_ASYNC_EXPORT AsyncCompletionVariant
1059{
1060 AsyncCompletionVariant() {}
1061 ~AsyncCompletionVariant() { destroy(); }
1062
1063 AsyncCompletionVariant(const AsyncCompletionVariant&) = delete;
1064 AsyncCompletionVariant(AsyncCompletionVariant&&) = delete;
1065 AsyncCompletionVariant& operator=(const AsyncCompletionVariant&) = delete;
1066 AsyncCompletionVariant& operator=(AsyncCompletionVariant&&) = delete;
1067
1068 bool inited = false;
1069
1070 AsyncRequest::Type type;
1071 union
1072 {
1073 AsyncCompletionData completionDataLoopWork; // Defined after AsyncCompletionVariant / AsyncTaskSequence
1074 AsyncLoopTimeout::CompletionData completionDataLoopTimeout;
1075 AsyncLoopWakeUp::CompletionData completionDataLoopWakeUp;
1076 AsyncProcessExit::CompletionData completionDataProcessExit;
1077 AsyncSignal::CompletionData completionDataSignal;
1078 AsyncSocketAccept::CompletionData completionDataSocketAccept;
1079 AsyncSocketConnect::CompletionData completionDataSocketConnect;
1080 AsyncSocketSend::CompletionData completionDataSocketSend;
1081 AsyncSocketSendTo::CompletionData completionDataSocketSendTo;
1082 AsyncSocketReceive::CompletionData completionDataSocketReceive;
1083 AsyncSocketReceiveFrom::CompletionData completionDataSocketReceiveFrom;
1084 AsyncFileRead::CompletionData completionDataFileRead;
1085 AsyncFileWrite::CompletionData completionDataFileWrite;
1086 AsyncFileSend::CompletionData completionDataFileSend;
1087 AsyncFilePoll::CompletionData completionDataFilePoll;
1088
1089 AsyncFileSystemOperationCompletionData completionDataFileSystemOperation;
1090 };
1091
1092 auto& getCompletion(AsyncLoopWork&) { return completionDataLoopWork; }
1093 auto& getCompletion(AsyncLoopTimeout&) { return completionDataLoopTimeout; }
1094 auto& getCompletion(AsyncLoopWakeUp&) { return completionDataLoopWakeUp; }
1095 auto& getCompletion(AsyncProcessExit&) { return completionDataProcessExit; }
1096 auto& getCompletion(AsyncSignal&) { return completionDataSignal; }
1097 auto& getCompletion(AsyncSocketAccept&) { return completionDataSocketAccept; }
1098 auto& getCompletion(AsyncSocketConnect&) { return completionDataSocketConnect; }
1099 auto& getCompletion(AsyncSocketSend&) { return completionDataSocketSend; }
1100 auto& getCompletion(AsyncSocketReceive&) { return completionDataSocketReceive; }
1101 auto& getCompletion(AsyncFileRead&) { return completionDataFileRead; }
1102 auto& getCompletion(AsyncFileWrite&) { return completionDataFileWrite; }
1103 auto& getCompletion(AsyncFileSend&) { return completionDataFileSend; }
1104 auto& getCompletion(AsyncFilePoll&) { return completionDataFilePoll; }
1105 auto& getCompletion(AsyncFileSystemOperation&) { return completionDataFileSystemOperation; }
1106
1107 template <typename T>
1108 auto& construct(T& t)
1109 {
1110 destroy();
1111 placementNew(getCompletion(t));
1112 inited = true;
1113 type = t.getType();
1114 return getCompletion(t);
1115 }
1116 void destroy();
1117};
1118} // namespace detail
1119
1123struct SC_ASYNC_EXPORT AsyncTaskSequence : public AsyncSequence
1124{
1125 protected:
1126 ThreadPoolTask task;
1127 ThreadPool* threadPool = nullptr;
1128
1129 friend struct AsyncEventLoop;
1130 friend struct AsyncRequest;
1131
1132 detail::AsyncCompletionVariant completion;
1133
1134 SC::Result returnCode = SC::Result(true);
1135};
1136
1142struct SC_ASYNC_EXPORT AsyncLoopWork : public AsyncRequest
1143{
1144 AsyncLoopWork() : AsyncRequest(Type::LoopWork) {}
1145
1148
1152
1153 Function<SC::Result()> work;
1155
1156 private:
1157 friend struct AsyncEventLoop;
1158 SC::Result validate(AsyncEventLoop&);
1159 AsyncTaskSequence task;
1160};
1161
1195struct SC_ASYNC_EXPORT AsyncFileSystemOperation : public AsyncRequest
1196{
1197 AsyncFileSystemOperation() : AsyncRequest(Type::FileSystemOperation) {}
1198 ~AsyncFileSystemOperation() { destroy(); }
1199#ifdef CopyFile
1200#undef CopyFile
1201#endif
1202#ifdef RemoveDirectory
1203#undef RemoveDirectory
1204#endif
1205 enum class Operation
1206 {
1207 None = 0,
1208 Open,
1209 Close,
1210 Read,
1211 Write,
1212 CopyFile,
1213 CopyDirectory,
1214 Rename,
1215 RemoveDirectory,
1216 RemoveFile,
1217 };
1218
1221
1224
1226
1233
1238 SC::Result close(AsyncEventLoop& eventLoop, FileDescriptor::Handle handle);
1239
1246 SC::Result read(AsyncEventLoop& eventLoop, FileDescriptor::Handle handle, Span<char> buffer, uint64_t offset);
1247
1254 SC::Result write(AsyncEventLoop& eventLoop, FileDescriptor::Handle handle, Span<const char> buffer,
1255 uint64_t offset);
1256
1263 SC::Result copyFile(AsyncEventLoop& eventLoop, StringSpan path, StringSpan destinationPath,
1265
1274
1281
1288
1294
1295 private:
1296 friend struct AsyncEventLoop;
1297 Operation operation = Operation::None;
1298 AsyncLoopWork loopWork;
1299 CompletionData completionData;
1300
1301 void onOperationCompleted(AsyncLoopWork::Result& res);
1302
1303 struct FileDescriptorData
1304 {
1305 FileDescriptor::Handle handle;
1306 };
1307
1308 struct OpenData
1309 {
1310 StringSpan path;
1311 FileOpen mode;
1312 };
1313
1314 struct ReadData
1315 {
1316 FileDescriptor::Handle handle;
1317 Span<char> buffer;
1318 uint64_t offset;
1319 };
1320
1321 struct WriteData
1322 {
1323 FileDescriptor::Handle handle;
1324 Span<const char> buffer;
1325 uint64_t offset;
1326 };
1327
1328 struct CopyFileData
1329 {
1330 StringSpan path;
1331 StringSpan destinationPath;
1332 FileSystemCopyFlags copyFlags;
1333 };
1334
1335 using CopyDirectoryData = CopyFileData;
1336
1337 using CloseData = FileDescriptorData;
1338
1339 struct RenameData
1340 {
1341 StringSpan path;
1342 StringSpan newPath;
1343 };
1344
1345 struct RemoveData
1346 {
1347 StringSpan path;
1348 };
1349
1350 union
1351 {
1352 OpenData openData;
1353 CloseData closeData;
1354 ReadData readData;
1355 WriteData writeData;
1356 CopyFileData copyFileData;
1357 CopyDirectoryData copyDirectoryData;
1358 RenameData renameData;
1359 RemoveData removeData;
1360 };
1361
1362 void destroy();
1363
1364 SC::Result start(AsyncEventLoop& eventLoop, FileDescriptor::Handle fileDescriptor);
1365 SC::Result validate(AsyncEventLoop&);
1366};
1367
1371struct SC_ASYNC_EXPORT AsyncKernelEvents
1372{
1374
1375 private:
1376 int numberOfEvents = 0;
1377 friend struct AsyncEventLoop;
1378};
1379
1381struct SC_ASYNC_EXPORT AsyncEventLoopListeners
1382{
1383 Function<void(AsyncEventLoop&)> beforeBlockingPoll;
1384 Function<void(AsyncEventLoop&)> afterBlockingPoll;
1385};
1386
1393struct SC_ASYNC_EXPORT AsyncEventLoop
1394{
1396 struct Options
1397 {
1398 enum class ApiType : uint8_t
1399 {
1400 Automatic = 0,
1401 ForceUseIOURing,
1402 ForceUseEpoll,
1403 };
1405
1406 Options() { apiType = ApiType::Automatic; }
1407 };
1408
1410
1411 AsyncEventLoop(const AsyncEventLoop&) = delete;
1412 AsyncEventLoop(AsyncEventLoop&&) = delete;
1413 AsyncEventLoop& operator=(AsyncEventLoop&&) = delete;
1414 AsyncEventLoop& operator=(const AsyncEventLoop&) = delete;
1415
1418
1421
1425
1428
1430 [[nodiscard]] bool isInitialized() const;
1431
1433 [[nodiscard]] bool needsThreadPoolForFileOperations() const;
1434
1441
1452
1459
1465
1485
1492
1496
1499
1502
1505
1508
1510 Result associateExternallyCreatedSocketHandle(SocketDescriptor::Handle handle);
1511
1514
1517
1520
1522 static Result removeAllAssociationsForSocketHandle(SocketDescriptor::Handle handle);
1523
1526
1528 static Result removeAllAssociationsForFileDescriptorHandle(FileDescriptor::Handle handle);
1529
1532
1534 [[nodiscard]] TimeMs getLoopTime() const;
1535
1537 [[nodiscard]] int getNumberOfActiveRequests() const;
1538
1540 [[nodiscard]] int getNumberOfSubmittedRequests() const;
1541
1545
1548
1551
1553 void enumerateRequests(Function<void(AsyncRequest&)> enumerationCallback);
1554
1558
1560 [[nodiscard]] static bool isExcludedFromActiveCount(const AsyncRequest& async);
1561
1564 [[nodiscard]] static bool tryLoadingLiburing();
1565
1568
1569 struct Internal;
1570
1572 using LoopWork = AsyncLoopWork;
1575 using Signal = AsyncSignal;
1582 using FileRead = AsyncFileRead;
1583 using FileWrite = AsyncFileWrite;
1584 using FileSend = AsyncFileSend;
1585 using FilePoll = AsyncFilePoll;
1588 using ResultType = AsyncResult;
1589
1590 public:
1591 struct SC_ASYNC_EXPORT InternalDefinition
1592 {
1593 static constexpr int Windows = 552;
1594 static constexpr int Apple = 520;
1595 static constexpr int Linux = 736;
1596 static constexpr int Default = Linux;
1597
1598 static constexpr size_t Alignment = 8;
1599
1600 using Object = Internal;
1601 };
1602
1604
1605 private:
1606 InternalOpaque internalOpaque;
1607 Internal& internal;
1608
1609 friend struct AsyncRequest;
1610 friend struct AsyncFileWrite;
1611 friend struct AsyncFileRead;
1612 friend struct AsyncFileSystemOperation;
1613 friend struct AsyncResult;
1614};
1615
1619struct SC_ASYNC_EXPORT AsyncEventLoopMonitor
1620{
1622
1626
1629
1637
1643
1644 private:
1645#if SC_COMPILER_MSVC
1646#pragma warning(push)
1647#pragma warning(disable : 4324) // useless warning on 32 bit... (structure was padded due to __declspec(align()))
1648#endif
1649 alignas(uint64_t) uint8_t eventsMemory[8 * 1024]; // 8 Kb of kernel events
1650#if SC_COMPILER_MSVC
1651#pragma warning(pop)
1652#endif
1653
1654 AsyncKernelEvents asyncKernelEvents;
1655 AsyncEventLoop* eventLoop = nullptr;
1656 AsyncLoopWakeUp eventLoopWakeUp;
1657
1658 Thread eventLoopThread;
1659 EventObject eventObjectEnterBlockingMode;
1660 EventObject eventObjectExitBlockingMode;
1661
1662 Atomic<bool> finished = false;
1663 Atomic<bool> needsWakeUp = true;
1664
1665 bool wakeUpHasBeenCalled = false;
1666
1667 Result monitoringLoopThread(Thread& thread);
1668};
1669
1670} // namespace SC
@ Write
Check if path is writable.
@ Read
Check if path is readable.
unsigned short uint16_t
Platform independent (2) bytes unsigned int.
Definition PrimitiveTypes.h:37
constexpr T && move(T &value)
Converts an lvalue to an rvalue reference.
Definition Compiler.h:274
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:36
unsigned long long uint64_t
Platform independent (8) bytes unsigned int.
Definition PrimitiveTypes.h:42
unsigned int uint32_t
Platform independent (4) bytes unsigned int.
Definition PrimitiveTypes.h:38
short int16_t
Platform independent (2) bytes signed int.
Definition PrimitiveTypes.h:45
long long int64_t
Platform independent (8) bytes signed int.
Definition PrimitiveTypes.h:50
int int32_t
Platform independent (4) bytes signed int.
Definition PrimitiveTypes.h:46
#define SC_TRY(expression)
Checks the value of the given expression and if failed, returns this value to caller.
Definition Result.h:49
A buffer of bytes with given alignment.
Definition AlignedStorage.h:29
Empty base struct for all AsyncRequest-derived CompletionData (internal) structs.
Definition Async.h:259
Allow library user to provide callbacks signaling different phases of async event loop cycle.
Definition Async.h:1382
Monitors Async I/O events from a background thread using a blocking kernel function (no CPU usage on ...
Definition Async.h:1620
Function< void(void)> onNewEventsAvailable
Informs to call dispatchCompletions on GUI Event Loop.
Definition Async.h:1621
Result startMonitoring()
Queue all async requests submissions and start monitoring loop events on a background thread.
Result close()
Stop monitoring the AsyncEventLoop, disposing all resources.
Result stopMonitoringAndDispatchCompletions()
Stops monitoring events on the background thread and dispatches callbacks for completed requests.
Result create(AsyncEventLoop &eventLoop)
Create the monitoring thread for an AsyncEventLoop.
Options given to AsyncEventLoop::create.
Definition Async.h:1397
ApiType apiType
Criteria to choose Async IO API.
Definition Async.h:1404
ApiType
Definition Async.h:1399
Asynchronous I/O (files, sockets, timers, processes, fs events, threads wake-up) (see Async) AsyncEve...
Definition Async.h:1394
bool needsThreadPoolForFileOperations() const
Returns true if backend needs a thread pool for non-blocking fs operations (anything but io_uring bas...
Result associateExternallyCreatedFileDescriptor(FileDescriptor &outDescriptor)
Associates a previously created File Descriptor with the eventLoop.
Result wakeUpFromExternalThread()
Wake up the event loop from a thread different than the one where run() is called (and potentially bl...
Result runNoWait()
Process active requests if any, dispatching their completions, or returns immediately without blockin...
static Result removeAllAssociationsFor(SocketDescriptor &outDescriptor)
Removes association of a TCP Socket with any event loop.
void updateTime()
Updates loop time to "now".
static bool isExcludedFromActiveCount(const AsyncRequest &async)
Checks if excludeFromActiveCount() has been called on the given request.
Result associateExternallyCreatedSocket(SocketDescriptor &outDescriptor)
Associates a previously created TCP / UDP socket with the eventLoop.
Result associateExternallyCreatedFileDescriptorHandle(FileDescriptor::Handle handle)
Associates a previously created File Descriptor handle with the eventLoop.
Result blockingPoll(AsyncKernelEvents &kernelEvents)
Blocks until at least one event happens, ensuring forward progress, without executing completions.
void clearSequence(AsyncSequence &sequence)
Clears the sequence.
int getNumberOfSubmittedRequests() const
Obtain the total number of submitted requests.
Result submitRequests(AsyncKernelEvents &kernelEvents)
Submits all queued async requests.
void enumerateRequests(Function< void(AsyncRequest &)> enumerationCallback)
Enumerates all requests objects associated with this loop.
TimeMs getLoopTime() const
Get Loop time (monotonic)
Result associateExternallyCreatedSocketHandle(SocketDescriptor::Handle handle)
Associates a previously created TCP / UDP socket handle with the eventLoop.
Result start(AsyncRequest &async)
Queues an async request request that has been correctly setup.
AsyncLoopTimeout * findEarliestLoopTimeout() const
Returns the next AsyncLoopTimeout that will be executed (shortest relativeTimeout)
void setListeners(AsyncEventLoopListeners *listeners)
Sets reference to listeners that will signal different events in loop lifetime.
Result dispatchCompletions(AsyncKernelEvents &kernelEvents)
Invokes completions for the AsyncKernelEvents collected by a call to AsyncEventLoop::blockingPoll.
void interrupt()
Interrupts the event loop even if it has active request on it.
Result wakeUpFromExternalThread(AsyncLoopWakeUp &wakeUp)
Wake up the event loop from a thread different than the one where run() is called (and potentially bl...
bool isInitialized() const
Returns true if create has been already called (successfully)
static Result removeAllAssociationsForSocketHandle(SocketDescriptor::Handle handle)
Removes association of a TCP Socket handle with any event loop.
Result create(Options options=Options())
Creates the event loop kernel object.
static bool tryLoadingLiburing()
Check if liburing is loadable (only on Linux)
Result createAsyncTCPSocket(SocketFlags::AddressFamily family, SocketDescriptor &outDescriptor)
Creates an async TCP (IPV4 / IPV6) socket registered with the eventLoop.
Result close()
Closes the event loop kernel object.
static Result removeAllAssociationsForFileDescriptorHandle(FileDescriptor::Handle handle)
Removes association of a File Descriptor handle with any event loop.
Result createAsyncUDPSocket(SocketFlags::AddressFamily family, SocketDescriptor &outDescriptor)
Creates an async UCP (IPV4 / IPV6) socket registered with the eventLoop.
static Result removeAllAssociationsFor(FileDescriptor &outDescriptor)
Removes association of a File Descriptor with any event loop.
Result runOnce()
Blocks until at least one request proceeds, ensuring forward progress, dispatching all completions.
void excludeFromActiveCount(AsyncRequest &async)
Excludes the request from active handles count (to avoid it keeping event loop alive)
Result run()
Blocks until there are no more active queued requests, dispatching all completions.
void includeInActiveCount(AsyncRequest &async)
Reverses the effect of excludeFromActiveCount for the request.
int getNumberOfActiveRequests() const
Obtain the total number of active requests.
Starts an handle polling operation.
Definition Async.h:932
SC::Result start(AsyncEventLoop &eventLoop, FileDescriptor::Handle fileDescriptor)
Starts a file descriptor poll operation, monitoring its readiness with appropriate OS API.
Definition Async.h:782
Definition Async.h:788
Starts a file read operation, reading bytes from a file (or pipe).
Definition Async.h:778
FileDescriptor::Handle handle
The writeable span of memory where to data will be written.
Definition Async.h:806
Span< char > buffer
Callback called when some data has been read from the file into the buffer.
Definition Async.h:805
SC::Result closeHandle()
The file/pipe descriptor handle to read data from.
Definition Async.h:809
void setOffset(uint64_t fileOffset)
Sets the offset in bytes at which start reading.
Definition Async.h:816
SC::Result start(AsyncEventLoop &eventLoop, const FileDescriptor &descriptor, Span< char > data)
Sets async request members and calls AsyncEventLoop::start.
uint64_t getOffset() const
Returns the last offset set with AsyncFileRead::setOffset.
Definition Async.h:812
Definition Async.h:986
Definition Async.h:992
size_t getBytesTransferred() const
Get the number of bytes transferred.
Definition Async.h:996
bool usedZeroCopy() const
Check if zero-copy was used for this transfer.
Definition Async.h:999
bool isComplete() const
Check if the entire requested range was sent.
Definition Async.h:1002
Sends file contents to a socket using zero-copy when available (sendfile, TransmitFile).
Definition Async.h:982
Function< void(Result &)> callback
Called when send completes or fails.
Definition Async.h:1022
SC::Result start(AsyncEventLoop &eventLoop, const FileDescriptor &file, const SocketDescriptor &socket, int64_t offset=0, size_t length=0, size_t pipeSize=0)
Start the file send operation.
Starts an asynchronous file system operation (open, close, read, write, sendFile, stat,...
Definition Async.h:1196
SC::Result copyDirectory(AsyncEventLoop &eventLoop, StringSpan path, StringSpan destinationPath, FileSystemCopyFlags copyFlags=FileSystemCopyFlags())
Copies a directory from one location to another.
SC::Result removeEmptyDirectory(AsyncEventLoop &eventLoop, StringSpan path)
Removes a directory asynchronously.
SC::Result rename(AsyncEventLoop &eventLoop, StringSpan path, StringSpan newPath)
Renames a file.
SC::Result removeFile(AsyncEventLoop &eventLoop, StringSpan path)
Removes a file asynchronously.
SC::Result setThreadPool(ThreadPool &threadPool)
Sets the thread pool to use for the operation.
SC::Result read(AsyncEventLoop &eventLoop, FileDescriptor::Handle handle, Span< char > buffer, uint64_t offset)
Reads data from a file descriptor at a given offset.
SC::Result write(AsyncEventLoop &eventLoop, FileDescriptor::Handle handle, Span< const char > buffer, uint64_t offset)
Writes data to a file descriptor at a given offset.
SC::Result close(AsyncEventLoop &eventLoop, FileDescriptor::Handle handle)
Closes a file descriptor asynchronously.
Function< void(Result &)> callback
Called after the operation is completed, on the event loop thread.
Definition Async.h:1225
SC::Result copyFile(AsyncEventLoop &eventLoop, StringSpan path, StringSpan destinationPath, FileSystemCopyFlags copyFlags=FileSystemCopyFlags())
Copies a file from one location to another.
SC::Result open(AsyncEventLoop &eventLoop, StringSpan path, FileOpen mode)
Opens a file asynchronously and returns its corresponding file descriptor.
Definition Async.h:863
Starts a file write operation, writing bytes to a file (or pipe).
Definition Async.h:854
uint64_t getOffset() const
Returns the last offset set with AsyncFileWrite::setOffset.
Definition Async.h:899
FileDescriptor::Handle handle
The file/pipe descriptor to write data to.
Definition Async.h:889
SC::Result start(AsyncEventLoop &eventLoop, Span< const char > data)
Sets async request members and calls AsyncEventLoop::start.
SC::Result start(AsyncEventLoop &eventLoop, const FileDescriptor &descriptor, Span< Span< const char > > data)
Sets async request members and calls AsyncEventLoop::start.
void setOffset(uint64_t fileOffset)
Sets the offset in bytes at which start writing.
Definition Async.h:903
Function< void(Result &)> callback
Callback called when descriptor is ready to be written with more data.
Definition Async.h:887
SC::Result start(AsyncEventLoop &eventLoop, const FileDescriptor &descriptor, Span< const char > data)
Sets async request members and calls AsyncEventLoop::start.
Span< Span< const char > > buffers
The read-only spans of memory where to read the data from.
Definition Async.h:895
SC::Result start(AsyncEventLoop &eventLoop, Span< Span< const char > > data)
Sets async request members and calls AsyncEventLoop::start.
Span< const char > buffer
The read-only span of memory where to read the data from.
Definition Async.h:894
Allows user to supply a block of memory that will store kernel I/O events retrieved from AsyncEventLo...
Definition Async.h:1372
Span< uint8_t > eventsMemory
User supplied block of memory used to store kernel I/O events.
Definition Async.h:1373
Starts a Timeout that is invoked only once after expiration (relative) time has passed.
Definition Async.h:310
TimeMs getExpirationTime() const
Gets computed absolute expiration time that determines when this timeout get executed.
Definition Async.h:325
SC::Result start(AsyncEventLoop &eventLoop, TimeMs relativeTimeout)
Sets async request members and calls AsyncEventLoop::start.
TimeMs relativeTimeout
First timer expiration (relative) time in milliseconds.
Definition Async.h:322
Function< void(Result &)> callback
Called after given expiration time since AsyncLoopTimeout::start has passed.
Definition Async.h:320
Options for AsyncLoopWakeUp configuration.
Definition Async.h:335
bool coalesce
Merge repeated pending wakeUp() calls into a single callback (default true, matching libuv uv_async_t...
Definition Async.h:338
Starts a wake-up operation, allowing threads to execute callbacks on loop thread.
Definition Async.h:358
SC::Result start(AsyncEventLoop &eventLoop, EventObject &eventObject, AsyncLoopWakeUpOptions options={})
Sets async request members and calls AsyncEventLoop::start.
Function< void(Result &)> callback
Callback called by SC::AsyncEventLoop::run after SC::AsyncLoopWakeUp::wakeUp.
Definition Async.h:377
SC::Result wakeUp(AsyncEventLoop &eventLoop)
Wakes up event loop, scheduling AsyncLoopWakeUp::callback on next AsyncEventLoop::run (or its variati...
SC::Result start(AsyncEventLoop &eventLoop, AsyncLoopWakeUpOptions options={})
Sets async request members and calls AsyncEventLoop::start.
Executes work in a thread pool and then invokes a callback on the event loop thread.
Definition Async.h:1143
Function< void(Result &)> callback
Called to execute the work in a background threadpool thread.
Definition Async.h:1154
SC::Result setThreadPool(ThreadPool &threadPool)
Sets the ThreadPool that will supply the thread to run the async work on.
Definition Async.h:404
Starts monitoring a process, notifying about its termination.
Definition Async.h:395
SC::Result start(AsyncEventLoop &eventLoop, FileDescriptor::Handle process)
Sets async request members and calls AsyncEventLoop::start.
Function< void(Result &)> callback
Called when process has exited.
Definition Async.h:420
Base class for all async requests, holding state and type.
Definition Async.h:123
bool isCancelling() const
Returns true if this request is being cancelled.
AsyncRequest(Type type)
Constructs a free async request of given type.
Definition Async.h:163
Result start(AsyncEventLoop &eventLoop)
Shortcut for AsyncEventLoop::start.
uint16_t getUserFlags() const
Gets user flags, holding some meaningful data for the caller.
Definition Async.h:192
Function< void(AsyncResult &)> * getCloseCallback()
Returns currently set close callback (if any) passed to AsyncRequest::stop.
Definition Async.h:195
bool isActive() const
Returns true if this request is active or being reactivated.
bool isFree() const
Returns true if this request is free.
void disableThreadPool()
Disables the thread-pool usage for this request.
Type getType() const
Returns request type.
Definition Async.h:183
void setUserFlags(uint16_t externalFlags)
Sets user flags, holding some meaningful data for the caller.
Definition Async.h:189
Result executeOn(AsyncTaskSequence &task, ThreadPool &pool)
Adds the request to be executed on a specific AsyncTaskSequence.
Result stop(AsyncEventLoop &eventLoop, Function< void(AsyncResult &)> *afterStopped=nullptr)
Ask to stop current async operation.
void executeOn(AsyncSequence &sequence)
Adds the request to be executed on a specific AsyncSequence.
Type
Type of async request.
Definition Async.h:142
Helper holding CompletionData for a specific AsyncRequest-derived class.
Definition Async.h:295
Base class for all async results (argument of completion callbacks).
Definition Async.h:265
const SC::Result & isValid() const
Check if the returnCode of this result is valid.
Definition Async.h:276
AsyncResult(AsyncEventLoop &eventLoop, AsyncRequest &request, SC::Result &res, bool *hasBeenReactivated=nullptr)
Constructs an async result from a request and a result.
Definition Async.h:267
void reactivateRequest(bool shouldBeReactivated)
Ask the event loop to re-activate this request after it was already completed.
Execute AsyncRequests serially, by submitting the next one after the previous one is completed.
Definition Async.h:243
Options for AsyncSignal request configuration.
Definition Async.h:438
Mode
Mode of signal watching.
Definition Async.h:441
@ Persistent
Callback runs on every delivery until stopped (default)
@ OneShot
Request auto-stops after first successful callback dispatch.
Mode mode
Default mode is Persistent.
Definition Async.h:445
bool coalesce
Merge repeated pending deliveries (default true)
Definition Async.h:446
Definition Async.h:461
Definition Async.h:467
Starts monitoring a signal, notifying about its reception.
Definition Async.h:457
Function< void(Result &)> callback
Called when the signal is raised.
Definition Async.h:475
SC::Result start(AsyncEventLoop &eventLoop, int num, AsyncSignalOptions options={})
Sets async request members and calls AsyncEventLoop::start.
Starts a socket accept operation, obtaining a new socket from a listening socket.
Definition Async.h:554
SC::Result start(AsyncEventLoop &eventLoop, const SocketDescriptor &socketDescriptor)
Sets async request members and calls AsyncEventLoop::start.
Starts a socket connect operation, connecting to a remote endpoint.
Definition Async.h:574
Function< void(Result &)> callback
Called after socket is finally connected to endpoint.
Definition Async.h:584
SC::Result start(AsyncEventLoop &eventLoop, const SocketDescriptor &descriptor, SocketIPAddress address)
Sets async request members and calls AsyncEventLoop::start.
Starts an unconnected socket receive from operation, receiving bytes from a remote endpoint.
Definition Async.h:743
Definition Async.h:696
SC::Result get(Span< char > &outData)
Get a Span of the actually read data.
Definition Async.h:704
Starts a socket receive operation, receiving bytes from a remote endpoint.
Definition Async.h:686
SC::Result start(AsyncEventLoop &eventLoop, const SocketDescriptor &descriptor, Span< char > data)
Sets async request members and calls AsyncEventLoop::start.
SC::Result closeHandle()
The Socket Descriptor handle to read data from.
Definition Async.h:722
Span< char > buffer
The writeable span of memory where to data will be written.
Definition Async.h:719
Function< void(Result &)> callback
Called after data has been received.
Definition Async.h:717
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
Function< void(Result &)> callback
Called when socket is ready to send more data.
Definition Async.h:623
SC::Result start(AsyncEventLoop &eventLoop, const SocketDescriptor &descriptor, Span< const char > data)
Sets async request members and calls AsyncEventLoop::start.
Span< Span< const char > > buffers
Spans of bytes to send (singleBuffer == false)
Definition Async.h:630
Span< const char > buffer
Span of bytes to send (singleBuffer == true)
Definition Async.h:629
SC::Result start(AsyncEventLoop &eventLoop, const SocketDescriptor &descriptor, Span< Span< const char > > data)
Sets async request members and calls AsyncEventLoop::start.
An AsyncSequence using a SC::ThreadPool to execute one or more SC::AsyncRequest in a background threa...
Definition Async.h:1124
Atomic variables (only for int and bool for now).
Definition Atomic.h:42
An automatically reset event object to synchronize two threads.
Definition Threading.h:235
[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
Hides implementation details from public headers (static PIMPL).
Definition OpaqueObject.h:31
Read / Write pipe (Process stdin/stdout and IPC communication)
Definition File.h:300
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
AddressFamily
Sets the address family of an IP Address (IPv4 or IPV6)
Definition Socket.h:66
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
A small task containing a function to execute that can be queued in the thread pool.
Definition ThreadPool.h:16
Simple thread pool that executes tasks in a fixed number of worker threads.
Definition ThreadPool.h:38
A native OS thread.
Definition Threading.h:119
A vocabulary type representing a time interval in milliseconds since epoch.
Definition PrimitiveTypes.h:63