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 "../Async/Internal/IntrusiveDoubleLinkedList.h"
6#include "../File/File.h"
7#include "../FileSystem/FileSystem.h"
8#include "../Foundation/Function.h"
9#include "../Foundation/OpaqueObject.h"
10#include "../Socket/Socket.h"
11#include "../Threading/Atomic.h"
12#include "../Threading/ThreadPool.h"
13
14namespace SC
15{
16struct ThreadPool;
17struct ThreadPoolTask;
18struct EventObject;
19} // namespace SC
44
47namespace SC
48{
49struct AsyncEventLoop;
50struct AsyncResult;
51struct AsyncSequence;
52struct AsyncTaskSequence;
53
54namespace detail
55{
56struct AsyncWinOverlapped;
57struct AsyncWinOverlappedDefinition
58{
59 static constexpr int Windows = sizeof(void*) * 4 + sizeof(uint64_t);
60 static constexpr size_t Alignment = alignof(void*);
61
62 using Object = AsyncWinOverlapped;
63};
64using WinOverlappedOpaque = OpaqueObject<AsyncWinOverlappedDefinition>;
65
66struct AsyncWinWaitDefinition
67{
68 using Handle = FileDescriptor::Handle; // fd
69 static constexpr Handle Invalid = FileDescriptor::Invalid; // invalid fd
70
71 static Result releaseHandle(Handle& waitHandle);
72};
73struct SC_COMPILER_EXPORT WinWaitHandle : public UniqueHandle<AsyncWinWaitDefinition>
74{
75};
76} // namespace detail
77
116struct SC_COMPILER_EXPORT AsyncRequest
117{
118 AsyncRequest* next = nullptr;
119 AsyncRequest* prev = nullptr;
120
121 void setDebugName(const char* newDebugName);
122
124 void executeOn(AsyncSequence& sequence);
125
130
133
135 enum class Type : uint8_t
136 {
137 LoopTimeout,
138 LoopWakeUp,
139 LoopWork,
140 ProcessExit,
141 Signal,
142 SocketAccept,
143 SocketConnect,
144 SocketSend,
145 SocketSendTo,
146 SocketReceive,
147 SocketReceiveFrom,
148 FileRead,
149 FileWrite,
150 FileSend,
151 FilePoll,
152 FileSystemOperation,
153 };
154
157 AsyncRequest(Type type) : state(State::Free), type(type), flags(0), unused(0), userFlags(0) {}
158
165 Result stop(AsyncEventLoop& eventLoop, Function<void(AsyncResult&)>* afterStopped = nullptr);
166
168 [[nodiscard]] bool isFree() const;
169
171 [[nodiscard]] bool isCancelling() const;
172
174 [[nodiscard]] bool isActive() const;
175
177 [[nodiscard]] Type getType() const { return type; }
178
181
183 void setUserFlags(uint16_t externalFlags) { userFlags = externalFlags; }
184
186 uint16_t getUserFlags() const { return userFlags; }
187
189 [[nodiscard]] Function<void(AsyncResult&)>* getCloseCallback() { return closeCallback; }
190
191 [[nodiscard]] const Function<void(AsyncResult&)>* getCloseCallback() const { return closeCallback; }
192
193 protected:
194 Result checkState();
195
196 void queueSubmission(AsyncEventLoop& eventLoop);
197
198 AsyncSequence* sequence = nullptr;
199
200 AsyncTaskSequence* getTask();
201
202 private:
203 Function<void(AsyncResult&)>* closeCallback = nullptr;
204
205 friend struct AsyncEventLoop;
206 friend struct AsyncResult;
207
208 void markAsFree();
209
210 [[nodiscard]] static const char* TypeToString(Type type);
211 enum class State : uint8_t
212 {
213 Free, // not in any queue, this can be started with an async.start(...)
214 Setup, // when in submission queue waiting to be setup (after an async.start(...))
215 Submitting, // when in submission queue waiting to be activated or re-activated
216 Active, // when monitored by OS syscall or in activeLoopWakeUps / activeTimeouts queues
217 Reactivate, // when flagged for reactivation inside the callback (after a result.reactivateRequest(true))
218 Cancelling, // when in cancellation queue waiting for a cancelAsync (on active async)
219 };
220
221#if SC_ASYNC_ENABLE_LOG
222 const char* debugName = "None";
223#endif
224 State state; // 1 byte
225 Type type; // 1 byte
226 int16_t flags; // 2 bytes
227
228 uint16_t unused; // 2 bytes
229 uint16_t userFlags; // 2 bytes
230};
231
236struct SC_COMPILER_EXPORT AsyncSequence
237{
238 AsyncSequence* next = nullptr;
239 AsyncSequence* prev = nullptr;
240
241 bool clearSequenceOnCancel = true;
242 bool clearSequenceOnError = true;
243 private:
244 friend struct AsyncEventLoop;
245 bool runningAsync = false; // true if an async from this sequence is being run
246 bool tracked = false;
247
248 IntrusiveDoubleLinkedList<AsyncRequest> submissions;
249};
250
252struct SC_COMPILER_EXPORT AsyncCompletionData{};
253
256struct SC_COMPILER_EXPORT AsyncResult
257{
259 AsyncResult(AsyncEventLoop& eventLoop, AsyncRequest& request, SC::Result& res, bool* hasBeenReactivated = nullptr)
260 : eventLoop(eventLoop), async(request), hasBeenReactivated(hasBeenReactivated), returnCode(res)
261 {}
262
265 void reactivateRequest(bool shouldBeReactivated);
266
268 [[nodiscard]] const SC::Result& isValid() const { return returnCode; }
269
270 AsyncEventLoop& eventLoop;
271 AsyncRequest& async;
272
273 protected:
274 friend struct AsyncEventLoop;
275
276 bool shouldCallCallback = true;
277 bool* hasBeenReactivated = nullptr;
278
279 SC::Result& returnCode;
280};
281
285template <typename T, typename C>
287{
288 T& getAsync() { return static_cast<T&>(AsyncResult::async); }
289 const T& getAsync() const { return static_cast<const T&>(AsyncResult::async); }
290
292
293 C completionData;
294 int32_t eventIndex = 0;
295};
296
301struct SC_COMPILER_EXPORT AsyncLoopTimeout : public AsyncRequest
302{
303 AsyncLoopTimeout() : AsyncRequest(Type::LoopTimeout) {}
304
307 using AsyncRequest::start;
308
310 SC::Result start(AsyncEventLoop& eventLoop, TimeMs relativeTimeout);
311
313
315
317 TimeMs getExpirationTime() const { return expirationTime; }
318
319 private:
320 SC::Result validate(AsyncEventLoop&);
321 friend struct AsyncEventLoop;
322 TimeMs expirationTime;
323};
324
337struct SC_COMPILER_EXPORT AsyncLoopWakeUp : public AsyncRequest
338{
339 AsyncLoopWakeUp() : AsyncRequest(Type::LoopWakeUp) {}
340
343 using AsyncRequest::start;
344
346 SC::Result start(AsyncEventLoop& eventLoop, EventObject& eventObject);
347
350
352 EventObject* eventObject = nullptr;
353
354 private:
355 friend struct AsyncEventLoop;
356 SC::Result validate(AsyncEventLoop&);
357
358 Atomic<bool> pending = false;
359};
360
365struct SC_COMPILER_EXPORT AsyncProcessExit : public AsyncRequest
366{
367 AsyncProcessExit() : AsyncRequest(Type::ProcessExit) {}
368
370 {
371 int exitStatus;
372 };
373
374 struct Result : public AsyncResultOf<AsyncProcessExit, CompletionData>
375 {
376 using AsyncResultOf<AsyncProcessExit, CompletionData>::AsyncResultOf;
377
378 SC::Result get(int& status)
379 {
380 status = completionData.exitStatus;
381 return returnCode;
382 }
383 };
384 using AsyncRequest::start;
385
389 SC::Result start(AsyncEventLoop& eventLoop, FileDescriptor::Handle process);
390
392
393 private:
394 friend struct AsyncEventLoop;
395 SC::Result validate(AsyncEventLoop&);
396
397 FileDescriptor::Handle handle = FileDescriptor::Invalid;
398#if SC_PLATFORM_WINDOWS
400 detail::WinWaitHandle waitHandle;
401 AsyncEventLoop* eventLoop = nullptr;
402#elif SC_PLATFORM_LINUX
403 FileDescriptor pidFd;
404#endif
405};
406
409{
411 enum class Mode : uint8_t
412 {
413 Persistent,
414 OneShot
415 };
417 bool coalesce = true;
418};
419
427struct SC_COMPILER_EXPORT AsyncSignal : public AsyncRequest
428{
429 AsyncSignal() : AsyncRequest(Type::Signal) {}
430
432 {
433 int signalNumber = 0;
434 uint32_t deliveryCount = 1;
435 };
436
437 struct Result : public AsyncResultOf<AsyncSignal, CompletionData>
438 {
439 using AsyncResultOf<AsyncSignal, CompletionData>::AsyncResultOf;
440 };
441 using AsyncRequest::start;
442
444 SC::Result start(AsyncEventLoop& eventLoop, int num, AsyncSignalOptions options = {});
445
447
448 private:
449 friend struct AsyncEventLoop;
450 SC::Result validate(AsyncEventLoop&);
451
452 int signalNumber = 0;
453 AsyncSignalOptions signalOptions;
454#if SC_PLATFORM_WINDOWS
456 AsyncEventLoop* eventLoop = nullptr;
457#elif SC_PLATFORM_LINUX
458 FileDescriptor signalFd;
459 FileDescriptor::Handle signalFdHandle = FileDescriptor::Invalid;
460#endif
461};
462
463struct AsyncSocketAccept;
464namespace detail
465{
468struct SC_COMPILER_EXPORT AsyncSocketAcceptData
469{
470#if SC_PLATFORM_WINDOWS
471 void (*pAcceptEx)() = nullptr;
473 SocketDescriptor clientSocket;
474 uint8_t acceptBuffer[288] = {0};
475#elif SC_PLATFORM_LINUX
476 AlignedStorage<28> sockAddrHandle;
477 uint32_t sockAddrLen;
478#endif
479};
480
482struct SC_COMPILER_EXPORT AsyncSocketAcceptBase : public AsyncRequest
483{
484 AsyncSocketAcceptBase() : AsyncRequest(Type::SocketAccept) {}
485
486 struct CompletionData : public AsyncCompletionData
487 {
488 SocketDescriptor acceptedClient;
489 };
490
491 struct Result : public AsyncResultOf<AsyncSocketAccept, CompletionData>
492 {
493 using AsyncResultOf<AsyncSocketAccept, CompletionData>::AsyncResultOf;
494
495 SC::Result moveTo(SocketDescriptor& client)
496 {
497 SC_TRY(returnCode);
498 return client.assign(move(completionData.acceptedClient));
499 }
500 };
501 using AsyncRequest::start;
502
504 SC::Result start(AsyncEventLoop& eventLoop, const SocketDescriptor& socketDescriptor, AsyncSocketAcceptData& data);
505 SC::Result validate(AsyncEventLoop&);
506
507 Function<void(Result&)> callback;
508 SocketDescriptor::Handle handle = SocketDescriptor::Invalid;
509 SocketFlags::AddressFamily addressFamily = SocketFlags::AddressFamilyIPV4;
510 AsyncSocketAcceptData* acceptData = nullptr;
511};
512
513} // namespace detail
514
524struct SC_COMPILER_EXPORT AsyncSocketAccept : public detail::AsyncSocketAcceptBase
525{
526 AsyncSocketAccept() { AsyncSocketAcceptBase::acceptData = &data; }
527 using AsyncSocketAcceptBase::start;
528
530 SC::Result start(AsyncEventLoop& eventLoop, const SocketDescriptor& socketDescriptor);
531
532 private:
533 detail::AsyncSocketAcceptData data;
534};
535
544struct SC_COMPILER_EXPORT AsyncSocketConnect : public AsyncRequest
545{
546 AsyncSocketConnect() : AsyncRequest(Type::SocketConnect) {}
547
550 using AsyncRequest::start;
551
553 SC::Result start(AsyncEventLoop& eventLoop, const SocketDescriptor& descriptor, SocketIPAddress address);
554
556
557 SocketDescriptor::Handle handle = SocketDescriptor::Invalid;
558 SocketIPAddress ipAddress;
559
560 private:
561 friend struct AsyncEventLoop;
562 SC::Result validate(AsyncEventLoop&);
563
564#if SC_PLATFORM_WINDOWS
565 void (*pConnectEx)() = nullptr;
567#endif
568};
569
578struct SC_COMPILER_EXPORT AsyncSocketSend : public AsyncRequest
579{
580 AsyncSocketSend() : AsyncRequest(Type::SocketSend) {}
582 {
583 size_t numBytes = 0;
584 };
586 using AsyncRequest::start;
587
590
593
595
596 SocketDescriptor::Handle handle = SocketDescriptor::Invalid;
597
600 bool singleBuffer = true;
601
602 protected:
603 AsyncSocketSend(Type type) : AsyncRequest(type) {}
604 friend struct AsyncEventLoop;
605 SC::Result validate(AsyncEventLoop&);
606
607 size_t totalBytesWritten = 0;
608#if SC_PLATFORM_WINDOWS
610#endif
611};
612
622struct SC_COMPILER_EXPORT AsyncSocketSendTo : public AsyncSocketSend
623{
624 AsyncSocketSendTo() : AsyncSocketSend(Type::SocketSendTo) {}
625
626 SocketIPAddress address;
627
628 SC::Result start(AsyncEventLoop& eventLoop, const SocketDescriptor& descriptor, SocketIPAddress ipAddress,
629 Span<const char> data);
630
631 SC::Result start(AsyncEventLoop& eventLoop, const SocketDescriptor& descriptor, SocketIPAddress ipAddress,
632 Span<Span<const char>> data);
633
634 private:
635 using AsyncSocketSend::start;
636 friend struct AsyncEventLoop;
637 SC::Result validate(AsyncEventLoop&);
638#if SC_PLATFORM_LINUX
639 AlignedStorage<56> typeErasedMsgHdr;
640#endif
641};
642
654struct SC_COMPILER_EXPORT AsyncSocketReceive : public AsyncRequest
655{
656 AsyncSocketReceive() : AsyncRequest(Type::SocketReceive) {}
657
659 {
660 size_t numBytes = 0;
661 bool disconnected = false;
662 };
663
664 struct Result : public AsyncResultOf<AsyncSocketReceive, CompletionData>
665 {
666 using AsyncResultOf<AsyncSocketReceive, CompletionData>::AsyncResultOf;
667
672 {
673 SC_TRY(getAsync().buffer.sliceStartLength(0, completionData.numBytes, outData));
674 return returnCode;
675 }
676
677 SocketIPAddress getSourceAddress() const;
678 };
679 using AsyncRequest::start;
680
682 SC::Result start(AsyncEventLoop& eventLoop, const SocketDescriptor& descriptor, Span<char> data);
683
685
687 SocketDescriptor::Handle handle = SocketDescriptor::Invalid;
688
689 protected:
691 friend struct AsyncEventLoop;
692 SC::Result validate(AsyncEventLoop&);
693#if SC_PLATFORM_WINDOWS
695#endif
696};
697
707struct SC_COMPILER_EXPORT AsyncSocketReceiveFrom : public AsyncSocketReceive
708{
709 AsyncSocketReceiveFrom() : AsyncSocketReceive(Type::SocketReceiveFrom) {}
710 using AsyncSocketReceive::start;
711
712 private:
713 SocketIPAddress address;
714 friend struct AsyncSocketReceive;
715 friend struct AsyncEventLoop;
716#if SC_PLATFORM_LINUX
717 AlignedStorage<56> typeErasedMsgHdr;
718#endif
719};
720
742struct SC_COMPILER_EXPORT AsyncFileRead : public AsyncRequest
743{
744 AsyncFileRead() : AsyncRequest(Type::FileRead) { handle = FileDescriptor::Invalid; }
745
747 {
748 size_t numBytes = 0;
749 bool endOfFile = false;
750 };
751
752 struct Result : public AsyncResultOf<AsyncFileRead, CompletionData>
753 {
754 using AsyncResultOf<AsyncFileRead, CompletionData>::AsyncResultOf;
755
756 SC::Result get(Span<char>& data)
757 {
758 SC_TRY(getAsync().buffer.sliceStartLength(0, completionData.numBytes, data));
759 return returnCode;
760 }
761 };
762 using AsyncRequest::start;
763
765 SC::Result start(AsyncEventLoop& eventLoop, const FileDescriptor& descriptor, Span<char> data);
766
767 Function<void(Result&)> callback;
769 FileDescriptor::Handle handle;
771
773 uint64_t getOffset() const { return offset; }
774
777 void setOffset(uint64_t fileOffset)
778 {
779 useOffset = true;
780 offset = fileOffset;
781 }
782
783 private:
784 friend struct AsyncEventLoop;
785 SC::Result validate(AsyncEventLoop&);
786
787 bool useOffset = false;
788 bool endedSync = false;
789
790 uint64_t offset = 0;
791#if SC_PLATFORM_WINDOWS
792 uint64_t readCursor = 0;
794#endif
795};
796
814struct SC_COMPILER_EXPORT AsyncFileWrite : public AsyncRequest
815{
816 AsyncFileWrite() : AsyncRequest(Type::FileWrite) { handle = FileDescriptor::Invalid; }
817
819 {
820 size_t numBytes = 0;
821 };
822
823 struct Result : public AsyncResultOf<AsyncFileWrite, CompletionData>
824 {
825 using AsyncResultOf<AsyncFileWrite, CompletionData>::AsyncResultOf;
826
827 SC::Result get(size_t& writtenSizeInBytes)
828 {
829 writtenSizeInBytes = completionData.numBytes;
830 return returnCode;
831 }
832 };
833
834 using AsyncRequest::start;
835
837 SC::Result start(AsyncEventLoop& eventLoop, const FileDescriptor& descriptor, Span<Span<const char>> data);
838
841
843 SC::Result start(AsyncEventLoop& eventLoop, const FileDescriptor& descriptor, Span<const char> data);
844
847
849
850 FileDescriptor::Handle handle;
852
855 bool singleBuffer = true;
856
858 uint64_t getOffset() const { return offset; }
859
862 void setOffset(uint64_t fileOffset)
863 {
864 useOffset = true;
865 offset = fileOffset;
866 }
867
868 private:
869 friend struct AsyncEventLoop;
870 SC::Result validate(AsyncEventLoop&);
871
872#if SC_PLATFORM_WINDOWS
873 bool endedSync = false;
874#else
875 bool isWatchable = false;
876#endif
877 bool useOffset = false;
878 uint64_t offset = 0xffffffffffffffff;
879
880 size_t totalBytesWritten = 0;
881#if SC_PLATFORM_WINDOWS
883#endif
884};
885
890struct SC_COMPILER_EXPORT AsyncFilePoll : public AsyncRequest
891{
892 AsyncFilePoll() : AsyncRequest(Type::FilePoll) {}
893
896
898 SC::Result start(AsyncEventLoop& eventLoop, FileDescriptor::Handle fileDescriptor);
899
900#if SC_PLATFORM_WINDOWS
901 [[nodiscard]] void* getOverlappedPtr();
902#endif
903
904 Function<void(Result&)> callback;
905
906 private:
907 friend struct AsyncEventLoop;
908 SC::Result validate(AsyncEventLoop&);
909
910 FileDescriptor::Handle handle = FileDescriptor::Invalid;
911#if SC_PLATFORM_WINDOWS
913#endif
914};
915
940struct SC_COMPILER_EXPORT AsyncFileSend : public AsyncRequest
941{
942 AsyncFileSend() : AsyncRequest(Type::FileSend) {}
943
945 {
946 size_t bytesTransferred = 0;
947 bool usedZeroCopy = false;
948 };
949
950 struct Result : public AsyncResultOf<AsyncFileSend, CompletionData>
951 {
952 using AsyncResultOf<AsyncFileSend, CompletionData>::AsyncResultOf;
953
955 [[nodiscard]] size_t getBytesTransferred() const { return completionData.bytesTransferred; }
956
958 [[nodiscard]] bool usedZeroCopy() const { return completionData.usedZeroCopy; }
959
961 [[nodiscard]] bool isComplete() const
962 {
963 return returnCode && completionData.bytesTransferred == getAsync().length;
964 }
965 };
966
967 using AsyncRequest::start;
968
978 SC::Result start(AsyncEventLoop& eventLoop, const FileDescriptor& file, const SocketDescriptor& socket,
979 int64_t offset = 0, size_t length = 0, size_t pipeSize = 0);
980
982
983 // Internal handles (set by start())
984 FileDescriptor::Handle fileHandle = FileDescriptor::Invalid;
985 SocketDescriptor::Handle socketHandle = SocketDescriptor::Invalid;
986
987 int64_t offset = 0;
988 size_t length = 0;
989 size_t bytesSent = 0;
990 private:
991 friend struct AsyncEventLoop;
992 SC::Result validate(AsyncEventLoop&);
993
994#if SC_PLATFORM_WINDOWS
996#elif SC_PLATFORM_LINUX
997 size_t pipeBufferSize = 0;
998 PipeDescriptor splicePipe;
999#endif
1000};
1001
1002// forward declared because it must be defined after AsyncTaskSequence
1003struct AsyncLoopWork;
1005
1007{
1008 FileDescriptor::Handle handle = FileDescriptor::Invalid; // for open
1009
1010 int code = 0; // for open/close
1011 size_t numBytes = 0; // for read
1012};
1013
1014namespace detail
1015{
1016// A simple hand-made variant of all completion types
1017struct SC_COMPILER_EXPORT AsyncCompletionVariant
1018{
1019 AsyncCompletionVariant() {}
1020 ~AsyncCompletionVariant() { destroy(); }
1021
1022 AsyncCompletionVariant(const AsyncCompletionVariant&) = delete;
1023 AsyncCompletionVariant(AsyncCompletionVariant&&) = delete;
1024 AsyncCompletionVariant& operator=(const AsyncCompletionVariant&) = delete;
1025 AsyncCompletionVariant& operator=(AsyncCompletionVariant&&) = delete;
1026
1027 bool inited = false;
1028
1029 AsyncRequest::Type type;
1030 union
1031 {
1032 AsyncCompletionData completionDataLoopWork; // Defined after AsyncCompletionVariant / AsyncTaskSequence
1033 AsyncLoopTimeout::CompletionData completionDataLoopTimeout;
1034 AsyncLoopWakeUp::CompletionData completionDataLoopWakeUp;
1035 AsyncProcessExit::CompletionData completionDataProcessExit;
1036 AsyncSignal::CompletionData completionDataSignal;
1037 AsyncSocketAccept::CompletionData completionDataSocketAccept;
1038 AsyncSocketConnect::CompletionData completionDataSocketConnect;
1039 AsyncSocketSend::CompletionData completionDataSocketSend;
1040 AsyncSocketSendTo::CompletionData completionDataSocketSendTo;
1041 AsyncSocketReceive::CompletionData completionDataSocketReceive;
1042 AsyncSocketReceiveFrom::CompletionData completionDataSocketReceiveFrom;
1043 AsyncFileRead::CompletionData completionDataFileRead;
1044 AsyncFileWrite::CompletionData completionDataFileWrite;
1045 AsyncFileSend::CompletionData completionDataFileSend;
1046 AsyncFilePoll::CompletionData completionDataFilePoll;
1047
1048 AsyncFileSystemOperationCompletionData completionDataFileSystemOperation;
1049 };
1050
1051 auto& getCompletion(AsyncLoopWork&) { return completionDataLoopWork; }
1052 auto& getCompletion(AsyncLoopTimeout&) { return completionDataLoopTimeout; }
1053 auto& getCompletion(AsyncLoopWakeUp&) { return completionDataLoopWakeUp; }
1054 auto& getCompletion(AsyncProcessExit&) { return completionDataProcessExit; }
1055 auto& getCompletion(AsyncSignal&) { return completionDataSignal; }
1056 auto& getCompletion(AsyncSocketAccept&) { return completionDataSocketAccept; }
1057 auto& getCompletion(AsyncSocketConnect&) { return completionDataSocketConnect; }
1058 auto& getCompletion(AsyncSocketSend&) { return completionDataSocketSend; }
1059 auto& getCompletion(AsyncSocketReceive&) { return completionDataSocketReceive; }
1060 auto& getCompletion(AsyncFileRead&) { return completionDataFileRead; }
1061 auto& getCompletion(AsyncFileWrite&) { return completionDataFileWrite; }
1062 auto& getCompletion(AsyncFileSend&) { return completionDataFileSend; }
1063 auto& getCompletion(AsyncFilePoll&) { return completionDataFilePoll; }
1064 auto& getCompletion(AsyncFileSystemOperation&) { return completionDataFileSystemOperation; }
1065
1066 template <typename T>
1067 auto& construct(T& t)
1068 {
1069 destroy();
1070 placementNew(getCompletion(t));
1071 inited = true;
1072 type = t.getType();
1073 return getCompletion(t);
1074 }
1075 void destroy();
1076};
1077} // namespace detail
1078
1082struct SC_COMPILER_EXPORT AsyncTaskSequence : public AsyncSequence
1083{
1084 protected:
1085 ThreadPoolTask task;
1086 ThreadPool* threadPool = nullptr;
1087
1088 friend struct AsyncEventLoop;
1089 friend struct AsyncRequest;
1090
1091 detail::AsyncCompletionVariant completion;
1092
1093 SC::Result returnCode = SC::Result(true);
1094};
1095
1101struct SC_COMPILER_EXPORT AsyncLoopWork : public AsyncRequest
1102{
1103 AsyncLoopWork() : AsyncRequest(Type::LoopWork) {}
1104
1107
1111
1112 Function<SC::Result()> work;
1114
1115 private:
1116 friend struct AsyncEventLoop;
1117 SC::Result validate(AsyncEventLoop&);
1118 AsyncTaskSequence task;
1119};
1120
1154struct SC_COMPILER_EXPORT AsyncFileSystemOperation : public AsyncRequest
1155{
1156 AsyncFileSystemOperation() : AsyncRequest(Type::FileSystemOperation) {}
1157 ~AsyncFileSystemOperation() { destroy(); }
1158#ifdef CopyFile
1159#undef CopyFile
1160#endif
1161#ifdef RemoveDirectory
1162#undef RemoveDirectory
1163#endif
1164 enum class Operation
1165 {
1166 None = 0,
1167 Open,
1168 Close,
1169 Read,
1170 Write,
1171 CopyFile,
1172 CopyDirectory,
1173 Rename,
1174 RemoveDirectory,
1175 RemoveFile,
1176 };
1177
1180
1183
1185
1192
1197 SC::Result close(AsyncEventLoop& eventLoop, FileDescriptor::Handle handle);
1198
1205 SC::Result read(AsyncEventLoop& eventLoop, FileDescriptor::Handle handle, Span<char> buffer, uint64_t offset);
1206
1213 SC::Result write(AsyncEventLoop& eventLoop, FileDescriptor::Handle handle, Span<const char> buffer,
1214 uint64_t offset);
1215
1222 SC::Result copyFile(AsyncEventLoop& eventLoop, StringSpan path, StringSpan destinationPath,
1224
1233
1240
1247
1253
1254 private:
1255 friend struct AsyncEventLoop;
1256 Operation operation = Operation::None;
1257 AsyncLoopWork loopWork;
1258 CompletionData completionData;
1259
1260 void onOperationCompleted(AsyncLoopWork::Result& res);
1261
1262 struct FileDescriptorData
1263 {
1264 FileDescriptor::Handle handle;
1265 };
1266
1267 struct OpenData
1268 {
1269 StringSpan path;
1270 FileOpen mode;
1271 };
1272
1273 struct ReadData
1274 {
1275 FileDescriptor::Handle handle;
1276 Span<char> buffer;
1277 uint64_t offset;
1278 };
1279
1280 struct WriteData
1281 {
1282 FileDescriptor::Handle handle;
1283 Span<const char> buffer;
1284 uint64_t offset;
1285 };
1286
1287 struct CopyFileData
1288 {
1289 StringSpan path;
1290 StringSpan destinationPath;
1291 FileSystemCopyFlags copyFlags;
1292 };
1293
1294 using CopyDirectoryData = CopyFileData;
1295
1296 using CloseData = FileDescriptorData;
1297
1298 struct RenameData
1299 {
1300 StringSpan path;
1301 StringSpan newPath;
1302 };
1303
1304 struct RemoveData
1305 {
1306 StringSpan path;
1307 };
1308
1309 union
1310 {
1311 OpenData openData;
1312 CloseData closeData;
1313 ReadData readData;
1314 WriteData writeData;
1315 CopyFileData copyFileData;
1316 CopyDirectoryData copyDirectoryData;
1317 RenameData renameData;
1318 RemoveData removeData;
1319 };
1320
1321 void destroy();
1322
1323 SC::Result start(AsyncEventLoop& eventLoop, FileDescriptor::Handle fileDescriptor);
1324 SC::Result validate(AsyncEventLoop&);
1325};
1326
1330struct SC_COMPILER_EXPORT AsyncKernelEvents
1331{
1333
1334 private:
1335 int numberOfEvents = 0;
1336 friend struct AsyncEventLoop;
1337};
1338
1340struct SC_COMPILER_EXPORT AsyncEventLoopListeners
1341{
1342 Function<void(AsyncEventLoop&)> beforeBlockingPoll;
1343 Function<void(AsyncEventLoop&)> afterBlockingPoll;
1344};
1345
1352struct SC_COMPILER_EXPORT AsyncEventLoop
1353{
1355 struct Options
1356 {
1357 enum class ApiType : uint8_t
1358 {
1359 Automatic = 0,
1360 ForceUseIOURing,
1361 ForceUseEpoll,
1362 };
1364
1365 Options() { apiType = ApiType::Automatic; }
1366 };
1367
1369
1370 AsyncEventLoop(const AsyncEventLoop&) = delete;
1371 AsyncEventLoop(AsyncEventLoop&&) = delete;
1372 AsyncEventLoop& operator=(AsyncEventLoop&&) = delete;
1373 AsyncEventLoop& operator=(const AsyncEventLoop&) = delete;
1374
1377
1380
1384
1387
1389 [[nodiscard]] bool isInitialized() const;
1390
1392 [[nodiscard]] bool needsThreadPoolForFileOperations() const;
1393
1400
1411
1418
1424
1444
1451
1455
1458
1461
1464
1467
1470
1473
1476
1479
1481 [[nodiscard]] TimeMs getLoopTime() const;
1482
1484 [[nodiscard]] int getNumberOfActiveRequests() const;
1485
1487 [[nodiscard]] int getNumberOfSubmittedRequests() const;
1488
1492
1495
1498
1500 void enumerateRequests(Function<void(AsyncRequest&)> enumerationCallback);
1501
1505
1507 [[nodiscard]] static bool isExcludedFromActiveCount(const AsyncRequest& async);
1508
1511 [[nodiscard]] static bool tryLoadingLiburing();
1512
1515
1516 struct Internal;
1517
1518 public:
1519 struct SC_COMPILER_EXPORT InternalDefinition
1520 {
1521 static constexpr int Windows = 552;
1522 static constexpr int Apple = 520;
1523 static constexpr int Linux = 736;
1524 static constexpr int Default = Linux;
1525
1526 static constexpr size_t Alignment = 8;
1527
1528 using Object = Internal;
1529 };
1530
1532
1533 private:
1534 InternalOpaque internalOpaque;
1535 Internal& internal;
1536
1537 friend struct AsyncRequest;
1538 friend struct AsyncFileWrite;
1539 friend struct AsyncFileRead;
1540 friend struct AsyncFileSystemOperation;
1541 friend struct AsyncResult;
1542};
1543
1547struct SC_COMPILER_EXPORT AsyncEventLoopMonitor
1548{
1550
1554
1557
1565
1571
1572 private:
1573#if SC_COMPILER_MSVC
1574#pragma warning(push)
1575#pragma warning(disable : 4324) // useless warning on 32 bit... (structure was padded due to __declspec(align()))
1576#endif
1577 alignas(uint64_t) uint8_t eventsMemory[8 * 1024]; // 8 Kb of kernel events
1578#if SC_COMPILER_MSVC
1579#pragma warning(pop)
1580#endif
1581
1582 AsyncKernelEvents asyncKernelEvents;
1583 AsyncEventLoop* eventLoop = nullptr;
1584 AsyncLoopWakeUp eventLoopWakeUp;
1585
1586 Thread eventLoopThread;
1587 EventObject eventObjectEnterBlockingMode;
1588 EventObject eventObjectExitBlockingMode;
1589
1590 Atomic<bool> finished = false;
1591 Atomic<bool> needsWakeUp = true;
1592
1593 bool wakeUpHasBeenCalled = false;
1594
1595 Result monitoringLoopThread(Thread& thread);
1596};
1597
1598} // namespace SC
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:264
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
struct SC_COMPILER_EXPORT Function
Wraps function pointers, member functions and lambdas without ever allocating.
Definition Function.h:19
A buffer of bytes with given alignment.
Definition AlignedStorage.h:29
Empty base struct for all AsyncRequest-derived CompletionData (internal) structs.
Definition Async.h:252
Allow library user to provide callbacks signaling different phases of async event loop cycle.
Definition Async.h:1341
Monitors Async I/O events from a background thread using a blocking kernel function (no CPU usage on ...
Definition Async.h:1548
Function< void(void)> onNewEventsAvailable
Informs to call dispatchCompletions on GUI Event Loop.
Definition Async.h:1549
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:1356
ApiType apiType
Criteria to choose Async IO API.
Definition Async.h:1363
ApiType
Definition Async.h:1358
Asynchronous I/O (files, sockets, timers, processes, fs events, threads wake-up) (see Async) AsyncEve...
Definition Async.h:1353
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 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 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)
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.
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:891
SC::Result start(AsyncEventLoop &eventLoop, FileDescriptor::Handle fileDescriptor)
Starts a file descriptor poll operation, monitoring its readiness with appropriate OS API.
Definition Async.h:747
Definition Async.h:753
Starts a file read operation, reading bytes from a file (or pipe).
Definition Async.h:743
FileDescriptor::Handle handle
The writeable span of memory where to data will be written.
Definition Async.h:769
Span< char > buffer
Callback called when some data has been read from the file into the buffer.
Definition Async.h:768
void setOffset(uint64_t fileOffset)
Sets the offset in bytes at which start reading.
Definition Async.h:777
SC::Result start(AsyncEventLoop &eventLoop, const FileDescriptor &descriptor, Span< char > data)
Sets async request members and calls AsyncEventLoop::start.
uint64_t getOffset() const
The file/pipe descriptor handle to read data from.
Definition Async.h:773
Definition Async.h:945
Definition Async.h:951
size_t getBytesTransferred() const
Get the number of bytes transferred.
Definition Async.h:955
bool usedZeroCopy() const
Check if zero-copy was used for this transfer.
Definition Async.h:958
bool isComplete() const
Check if the entire requested range was sent.
Definition Async.h:961
Sends file contents to a socket using zero-copy when available (sendfile, TransmitFile).
Definition Async.h:941
Function< void(Result &)> callback
Called when send completes or fails.
Definition Async.h:981
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:1155
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:1184
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:824
Starts a file write operation, writing bytes to a file (or pipe).
Definition Async.h:815
uint64_t getOffset() const
Returns the last offset set with AsyncFileWrite::setOffset.
Definition Async.h:858
FileDescriptor::Handle handle
The file/pipe descriptor to write data to.
Definition Async.h:850
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:862
Function< void(Result &)> callback
Callback called when descriptor is ready to be written with more data.
Definition Async.h:848
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:854
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:853
Allows user to supply a block of memory that will store kernel I/O events retrieved from AsyncEventLo...
Definition Async.h:1331
Span< uint8_t > eventsMemory
User supplied block of memory used to store kernel I/O events.
Definition Async.h:1332
Starts a Timeout that is invoked only once after expiration (relative) time has passed.
Definition Async.h:302
TimeMs getExpirationTime() const
Gets computed absolute expiration time that determines when this timeout get executed.
Definition Async.h:317
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:314
Function< void(Result &)> callback
Called after given expiration time since AsyncLoopTimeout::start has passed.
Definition Async.h:312
Starts a wake-up operation, allowing threads to execute callbacks on loop thread.
Definition Async.h:338
SC::Result start(AsyncEventLoop &eventLoop, EventObject &eventObject)
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:351
SC::Result wakeUp(AsyncEventLoop &eventLoop)
Wakes up event loop, scheduling AsyncLoopWakeUp::callback on next AsyncEventLoop::run (or its variati...
Executes work in a thread pool and then invokes a callback on the event loop thread.
Definition Async.h:1102
Function< void(Result &)> callback
Called to execute the work in a background threadpool thread.
Definition Async.h:1113
SC::Result setThreadPool(ThreadPool &threadPool)
Sets the ThreadPool that will supply the thread to run the async work on.
Definition Async.h:375
Starts monitoring a process, notifying about its termination.
Definition Async.h:366
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:391
Base class for all async requests, holding state and type.
Definition Async.h:117
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:157
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:186
Function< void(AsyncResult &)> * getCloseCallback()
Returns currently set close callback (if any) passed to AsyncRequest::stop.
Definition Async.h:189
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:177
void setUserFlags(uint16_t externalFlags)
Sets user flags, holding some meaningful data for the caller.
Definition Async.h:183
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:136
Helper holding CompletionData for a specific AsyncRequest-derived class.
Definition Async.h:287
Base class for all async results (argument of completion callbacks).
Definition Async.h:257
const SC::Result & isValid() const
Check if the returnCode of this result is valid.
Definition Async.h:268
AsyncResult(AsyncEventLoop &eventLoop, AsyncRequest &request, SC::Result &res, bool *hasBeenReactivated=nullptr)
Constructs an async result from a request and a result.
Definition Async.h:259
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:237
Options for AsyncSignal request configuration.
Definition Async.h:409
Mode
Mode of signal watching.
Definition Async.h:412
@ 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:416
bool coalesce
Merge repeated pending deliveries (default true)
Definition Async.h:417
Definition Async.h:432
Definition Async.h:438
Starts monitoring a signal, notifying about its reception.
Definition Async.h:428
Function< void(Result &)> callback
Called when the signal is raised.
Definition Async.h:446
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:525
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:545
Function< void(Result &)> callback
Called after socket is finally connected to endpoint.
Definition Async.h:555
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:708
Definition Async.h:665
SC::Result get(Span< char > &outData)
Get a Span of the actually read data.
Definition Async.h:671
Starts a socket receive operation, receiving bytes from a remote endpoint.
Definition Async.h:655
AsyncSocketReceive(Type type)
The Socket Descriptor handle to read data from.
Definition Async.h:690
SC::Result start(AsyncEventLoop &eventLoop, const SocketDescriptor &descriptor, Span< char > data)
Sets async request members and calls AsyncEventLoop::start.
Span< char > buffer
The writeable span of memory where to data will be written.
Definition Async.h:686
Function< void(Result &)> callback
Called after data has been received.
Definition Async.h:684
Starts an unconnected socket send to operation, sending bytes to a remote endpoint.
Definition Async.h:623
Starts a socket send operation, sending bytes to a remote endpoint.
Definition Async.h:579
Function< void(Result &)> callback
Called when socket is ready to send more data.
Definition Async.h:594
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:599
Span< const char > buffer
Span of bytes to send (singleBuffer == true)
Definition Async.h:598
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:1083
Atomic variables (only for int and bool for now).
Definition Atomic.h:41
An automatically reset event object to synchronize two threads.
Definition Threading.h:229
[UniqueHandleDeclaration2Snippet]
Definition File.h:79
Options used to open a file descriptor.
Definition File.h:50
A structure to describe copy flags.
Definition FileSystem.h:25
Hides implementation details from public headers (static PIMPL).
Definition OpaqueObject.h:31
Read / Write pipe (Process stdin/stdout and IPC communication)
Definition File.h:222
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:153
AddressFamily
Sets the address family of an IP Address (IPv4 or IPV6)
Definition Socket.h:60
Native representation of an IP Address.
Definition Socket.h:100
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:113
A vocabulary type representing a time interval in milliseconds since epoch.
Definition PrimitiveTypes.h:63