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 "../Containers/IntrusiveDoubleLinkedList.h"
6#include "../FileSystem/FileSystemOperations.h" // FileSystemCopyFlags
7#include "../Foundation/Function.h"
8#include "../Foundation/OpaqueObject.h"
9#include "../Foundation/Span.h"
10#include "../Threading/Atomic.h"
11#include "../Threading/ThreadPool.h"
12#include "../Time/Time.h"
13
14// Descriptors
15#include "../File/FileDescriptor.h"
16#include "../Process/ProcessDescriptor.h"
17#include "../Socket/SocketDescriptor.h"
18
19namespace SC
20{
21struct ThreadPool;
22struct ThreadPoolTask;
23struct EventObject;
24} // namespace SC
49
52namespace SC
53{
54struct AsyncEventLoop;
55struct AsyncResult;
56struct AsyncSequence;
57struct AsyncTaskSequence;
58
59namespace detail
60{
61struct AsyncWinOverlapped;
62struct AsyncWinOverlappedDefinition
63{
64 static constexpr int Windows = sizeof(void*) * 4 + sizeof(uint64_t);
65 static constexpr size_t Alignment = alignof(void*);
66
67 using Object = AsyncWinOverlapped;
68};
69using WinOverlappedOpaque = OpaqueObject<AsyncWinOverlappedDefinition>;
70
71struct AsyncWinWaitDefinition
72{
73 using Handle = FileDescriptor::Handle; // fd
74 static constexpr Handle Invalid = FileDescriptor::Invalid; // invalid fd
75
76 static Result releaseHandle(Handle& waitHandle);
77};
78struct WinWaitHandle : public UniqueHandle<AsyncWinWaitDefinition>
79{
80};
81} // namespace detail
82
122{
123 AsyncRequest* next = nullptr;
124 AsyncRequest* prev = nullptr;
125
126 void setDebugName(const char* newDebugName);
127
129 void executeOn(AsyncSequence& sequence);
130
135
138
157
160 AsyncRequest(Type type) : state(State::Free), type(type), flags(0), userFlags(0), unused(0) {}
161
168 Result stop(AsyncEventLoop& eventLoop, Function<void(AsyncResult&)>* afterStopped = nullptr);
169
171 [[nodiscard]] bool isFree() const;
172
174 [[nodiscard]] bool isCancelling() const;
175
177 [[nodiscard]] bool isActive() const;
178
180 [[nodiscard]] Type getType() const { return type; }
181
184
186 void setUserFlags(uint16_t externalFlags) { userFlags = externalFlags; }
187
189 uint16_t getUserFlags() const { return userFlags; }
190
192 [[nodiscard]] Function<void(AsyncResult&)>* getCloseCallback() { return closeCallback; }
193
194 [[nodiscard]] const Function<void(AsyncResult&)>* getCloseCallback() const { return closeCallback; }
195
196 protected:
197 Result checkState();
198
199 void queueSubmission(AsyncEventLoop& eventLoop);
200
201 AsyncSequence* sequence = nullptr;
202
203 AsyncTaskSequence* getTask();
204
205 private:
206 Function<void(AsyncResult&)>* closeCallback = nullptr;
207
208 friend struct AsyncEventLoop;
209 friend struct AsyncResult;
210
211 void markAsFree();
212
213 [[nodiscard]] static const char* TypeToString(Type type);
214 enum class State : uint8_t
215 {
216 Free, // not in any queue, this can be started with an async.start(...)
217 Setup, // when in submission queue waiting to be setup (after an async.start(...))
218 Submitting, // when in submission queue waiting to be activated or re-activated
219 Active, // when monitored by OS syscall or in activeLoopWakeUps / activeTimeouts queues
220 Reactivate, // when flagged for reactivation inside the callback (after a result.reactivateRequest(true))
221 Cancelling, // when in cancellation queue waiting for a cancelAsync (on active async)
222 };
223
224#if SC_ASYNC_ENABLE_LOG
225 const char* debugName = "None";
226#endif
227 State state; // 1 byte
228 Type type; // 1 byte
229 int16_t flags; // 2 bytes
230
231 uint16_t unused; // 2 bytes
232 uint16_t userFlags; // 2 bytes
233};
234
240{
241 AsyncSequence* next = nullptr;
242 AsyncSequence* prev = nullptr;
243
246 private:
247 friend struct AsyncEventLoop;
248 bool runningAsync = false; // true if an async from this sequence is being run
249 bool tracked = false;
250
252};
253
256{
257};
258
262{
264 AsyncResult(AsyncEventLoop& eventLoop, AsyncRequest& request, SC::Result& res, bool* hasBeenReactivated = nullptr)
265 : eventLoop(eventLoop), async(request), returnCode(res), hasBeenReactivated(hasBeenReactivated)
266 {}
267
270 void reactivateRequest(bool shouldBeReactivated);
271
273 [[nodiscard]] const SC::Result& isValid() const { return returnCode; }
274
275 AsyncEventLoop& eventLoop;
276 AsyncRequest& async;
277
278 protected:
279 friend struct AsyncEventLoop;
280
281 bool shouldCallCallback = true;
282 bool* hasBeenReactivated = nullptr;
283
284 SC::Result& returnCode;
285};
286
290template <typename T, typename C>
292{
293 T& getAsync() { return static_cast<T&>(AsyncResult::async); }
294 const T& getAsync() const { return static_cast<const T&>(AsyncResult::async); }
295
297
298 C completionData;
299 int32_t eventIndex = 0;
300};
301
329
365
371{
373
375 {
377 };
378
379 struct Result : public AsyncResultOf<AsyncProcessExit, CompletionData>
380 {
381 using AsyncResultOf<AsyncProcessExit, CompletionData>::AsyncResultOf;
382
384 {
385 status = completionData.exitStatus;
386 return returnCode;
387 }
388 };
390
392 SC::Result start(AsyncEventLoop& eventLoop, ProcessDescriptor::Handle process);
393
395
396 private:
397 friend struct AsyncEventLoop;
398 SC::Result validate(AsyncEventLoop&);
399
400 ProcessDescriptor::Handle handle = ProcessDescriptor::Invalid;
401#if SC_PLATFORM_WINDOWS
403 detail::WinWaitHandle waitHandle;
404 AsyncEventLoop* eventLoop = nullptr;
405#elif SC_PLATFORM_LINUX
406 FileDescriptor pidFd;
407#endif
408};
409
410struct AsyncSocketAccept;
411namespace detail
412{
415struct AsyncSocketAcceptData
416{
417#if SC_PLATFORM_WINDOWS
418 void (*pAcceptEx)() = nullptr;
420 SocketDescriptor clientSocket;
421 uint8_t acceptBuffer[288] = {0};
422#elif SC_PLATFORM_LINUX
423 AlignedStorage<28> sockAddrHandle;
424 uint32_t sockAddrLen;
425#endif
426};
427
429struct AsyncSocketAcceptBase : public AsyncRequest
430{
431 AsyncSocketAcceptBase() : AsyncRequest(Type::SocketAccept) {}
432
433 struct CompletionData : public AsyncCompletionData
434 {
435 SocketDescriptor acceptedClient;
436 };
437
438 struct Result : public AsyncResultOf<AsyncSocketAccept, CompletionData>
439 {
440 using AsyncResultOf<AsyncSocketAccept, CompletionData>::AsyncResultOf;
441
442 SC::Result moveTo(SocketDescriptor& client)
443 {
444 SC_TRY(returnCode);
445 return client.assign(move(completionData.acceptedClient));
446 }
447 };
449
451 SC::Result start(AsyncEventLoop& eventLoop, const SocketDescriptor& socketDescriptor, AsyncSocketAcceptData& data);
452 SC::Result validate(AsyncEventLoop&);
453
454 Function<void(Result&)> callback;
455 SocketDescriptor::Handle handle = SocketDescriptor::Invalid;
457 AsyncSocketAcceptData* acceptData = nullptr;
458};
459
460} // namespace detail
461
471struct AsyncSocketAccept : public detail::AsyncSocketAcceptBase
472{
473 AsyncSocketAccept() { AsyncSocketAcceptBase::acceptData = &data; }
474 using AsyncSocketAcceptBase::start;
475
477 SC::Result start(AsyncEventLoop& eventLoop, const SocketDescriptor& socketDescriptor);
478
479 private:
480 detail::AsyncSocketAcceptData data;
481};
482
492{
494
498
500 SC::Result start(AsyncEventLoop& eventLoop, const SocketDescriptor& descriptor, SocketIPAddress address);
501
503
504 SocketDescriptor::Handle handle = SocketDescriptor::Invalid;
505 SocketIPAddress ipAddress;
506
507 private:
508 friend struct AsyncEventLoop;
509 SC::Result validate(AsyncEventLoop&);
510
511#if SC_PLATFORM_WINDOWS
512 void (*pConnectEx)() = nullptr;
514#endif
515};
516
526{
529 {
530 size_t numBytes = 0;
531 };
534
537
540
542
543 SocketDescriptor::Handle handle = SocketDescriptor::Invalid;
544
547 bool singleBuffer = true;
548
549 protected:
550 AsyncSocketSend(Type type) : AsyncRequest(type) {}
551 friend struct AsyncEventLoop;
552 SC::Result validate(AsyncEventLoop&);
553
554 size_t totalBytesWritten = 0;
555#if SC_PLATFORM_WINDOWS
557#endif
558};
559
570{
572
573 SocketIPAddress address;
574
575 SC::Result start(AsyncEventLoop& eventLoop, const SocketDescriptor& descriptor, SocketIPAddress ipAddress,
576 Span<const char> data);
577
578 SC::Result start(AsyncEventLoop& eventLoop, const SocketDescriptor& descriptor, SocketIPAddress ipAddress,
579 Span<Span<const char>> data);
580
581 private:
583 friend struct AsyncEventLoop;
584 SC::Result validate(AsyncEventLoop&);
585#if SC_PLATFORM_LINUX
586 AlignedStorage<56> typeErasedMsgHdr;
587#endif
588};
589
602{
604
606 {
607 size_t numBytes = 0;
608 bool disconnected = false;
609 };
610
611 struct Result : public AsyncResultOf<AsyncSocketReceive, CompletionData>
612 {
613 using AsyncResultOf<AsyncSocketReceive, CompletionData>::AsyncResultOf;
614
619 {
620 SC_TRY(getAsync().buffer.sliceStartLength(0, completionData.numBytes, outData));
621 return returnCode;
622 }
623
624 SocketIPAddress getSourceAddress() const;
625 };
627
629 SC::Result start(AsyncEventLoop& eventLoop, const SocketDescriptor& descriptor, Span<char> data);
630
632
634 SocketDescriptor::Handle handle = SocketDescriptor::Invalid;
635
636 protected:
638 friend struct AsyncEventLoop;
639 SC::Result validate(AsyncEventLoop&);
640#if SC_PLATFORM_WINDOWS
642#endif
643};
644
655{
658
659 private:
660 SocketIPAddress address;
661 friend struct AsyncSocketReceive;
662 friend struct AsyncEventLoop;
663#if SC_PLATFORM_LINUX
664 AlignedStorage<56> typeErasedMsgHdr;
665#endif
666};
667
690{
691 AsyncFileRead() : AsyncRequest(Type::FileRead) { handle = FileDescriptor::Invalid; }
692
694 {
695 size_t numBytes = 0;
696 bool endOfFile = false;
697 };
698
699 struct Result : public AsyncResultOf<AsyncFileRead, CompletionData>
700 {
701 using AsyncResultOf<AsyncFileRead, CompletionData>::AsyncResultOf;
702
703 SC::Result get(Span<char>& data)
704 {
705 SC_TRY(getAsync().buffer.sliceStartLength(0, completionData.numBytes, data));
706 return returnCode;
707 }
708 };
710
711 Function<void(Result&)> callback;
713 FileDescriptor::Handle handle;
715
717 uint64_t getOffset() const { return offset; }
718
721 void setOffset(uint64_t fileOffset)
722 {
723 useOffset = true;
724 offset = fileOffset;
725 }
726
727 private:
728 friend struct AsyncEventLoop;
729 SC::Result validate(AsyncEventLoop&);
730 bool useOffset = false;
731 uint64_t offset = 0;
732#if SC_PLATFORM_WINDOWS
733 uint64_t readCursor = 0;
735#endif
736};
737
756{
757 AsyncFileWrite() : AsyncRequest(Type::FileWrite) { handle = FileDescriptor::Invalid; }
758
760 {
761 size_t numBytes = 0;
762 };
763
764 struct Result : public AsyncResultOf<AsyncFileWrite, CompletionData>
765 {
766 using AsyncResultOf<AsyncFileWrite, CompletionData>::AsyncResultOf;
767
768 SC::Result get(size_t& writtenSizeInBytes)
769 {
770 writtenSizeInBytes = completionData.numBytes;
771 return returnCode;
772 }
773 };
774
776
779
782
784
785 FileDescriptor::Handle handle;
787
790 bool singleBuffer = true;
791
793 uint64_t getOffset() const { return offset; }
794
797 void setOffset(uint64_t fileOffset)
798 {
799 useOffset = true;
800 offset = fileOffset;
801 }
802
803 private:
804 friend struct AsyncEventLoop;
805 SC::Result validate(AsyncEventLoop&);
806
807 bool isWatchable = false;
808 bool useOffset = false;
809 uint64_t offset = 0xffffffffffffffff;
810
811 size_t totalBytesWritten = 0;
812#if SC_PLATFORM_WINDOWS
814#endif
815};
816
822{
824
827
829 SC::Result start(AsyncEventLoop& eventLoop, FileDescriptor::Handle fileDescriptor);
830
831#if SC_PLATFORM_WINDOWS
832 [[nodiscard]] auto& getOverlappedOpaque() { return overlapped; }
833#endif
834
835 Function<void(Result&)> callback;
836
837 private:
838 friend struct AsyncEventLoop;
839 SC::Result validate(AsyncEventLoop&);
840
841 FileDescriptor::Handle handle = FileDescriptor::Invalid;
842#if SC_PLATFORM_WINDOWS
844#endif
845};
846
847// forward declared because it must be defined after AsyncTaskSequence
848struct AsyncLoopWork;
849struct AsyncFileSystemOperation;
850
852{
853 FileDescriptor::Handle handle = FileDescriptor::Invalid; // for open
854
855 int code = 0; // for open/close
856 size_t numBytes = 0; // for read
857};
858
859namespace detail
860{
861// A simple hand-made variant of all completion types
862struct AsyncCompletionVariant
863{
864 AsyncCompletionVariant() {}
865 ~AsyncCompletionVariant() { destroy(); }
866
867 AsyncCompletionVariant(const AsyncCompletionVariant&) = delete;
868 AsyncCompletionVariant(AsyncCompletionVariant&&) = delete;
869 AsyncCompletionVariant& operator=(const AsyncCompletionVariant&) = delete;
870 AsyncCompletionVariant& operator=(AsyncCompletionVariant&&) = delete;
871
872 bool inited = false;
873
875 union
876 {
877 AsyncCompletionData completionDataLoopWork; // Defined after AsyncCompletionVariant / AsyncTaskSequence
878 AsyncLoopTimeout::CompletionData completionDataLoopTimeout;
879 AsyncLoopWakeUp::CompletionData completionDataLoopWakeUp;
880 AsyncProcessExit::CompletionData completionDataProcessExit;
881 AsyncSocketAccept::CompletionData completionDataSocketAccept;
882 AsyncSocketConnect::CompletionData completionDataSocketConnect;
883 AsyncSocketSend::CompletionData completionDataSocketSend;
884 AsyncSocketSendTo::CompletionData completionDataSocketSendTo;
885 AsyncSocketReceive::CompletionData completionDataSocketReceive;
886 AsyncSocketReceiveFrom::CompletionData completionDataSocketReceiveFrom;
887 AsyncFileRead::CompletionData completionDataFileRead;
888 AsyncFileWrite::CompletionData completionDataFileWrite;
889 AsyncFilePoll::CompletionData completionDataFilePoll;
890
891 AsyncFileSystemOperationCompletionData completionDataFileSystemOperation;
892 };
893
894 auto& getCompletion(AsyncLoopWork&) { return completionDataLoopWork; }
895 auto& getCompletion(AsyncLoopTimeout&) { return completionDataLoopTimeout; }
896 auto& getCompletion(AsyncLoopWakeUp&) { return completionDataLoopWakeUp; }
897 auto& getCompletion(AsyncProcessExit&) { return completionDataProcessExit; }
898 auto& getCompletion(AsyncSocketAccept&) { return completionDataSocketAccept; }
899 auto& getCompletion(AsyncSocketConnect&) { return completionDataSocketConnect; }
900 auto& getCompletion(AsyncSocketSend&) { return completionDataSocketSend; }
901 auto& getCompletion(AsyncSocketReceive&) { return completionDataSocketReceive; }
902 auto& getCompletion(AsyncFileRead&) { return completionDataFileRead; }
903 auto& getCompletion(AsyncFileWrite&) { return completionDataFileWrite; }
904 auto& getCompletion(AsyncFilePoll&) { return completionDataFilePoll; }
905 auto& getCompletion(AsyncFileSystemOperation&) { return completionDataFileSystemOperation; }
906
907 template <typename T>
908 auto& construct(T& t)
909 {
910 destroy();
911 placementNew(getCompletion(t));
912 inited = true;
913 type = t.getType();
914 return getCompletion(t);
915 }
916 void destroy();
917};
918} // namespace detail
919
924{
925 protected:
926 ThreadPoolTask task;
927 ThreadPool* threadPool = nullptr;
928
929 friend struct AsyncEventLoop;
930 friend struct AsyncRequest;
931
932 detail::AsyncCompletionVariant completion;
933
934 SC::Result returnCode = SC::Result(true);
935};
936
961
978{
980 ~AsyncFileSystemOperation() { destroy(); }
981
982 enum class Operation
983 {
984 None = 0,
985 Open,
986 Close,
987 Read,
988 Write,
989 CopyFile,
990 };
991
994
997
999
1005
1009 SC::Result close(AsyncEventLoop& eventLoop, FileDescriptor::Handle handle);
1010
1016 SC::Result read(AsyncEventLoop& eventLoop, FileDescriptor::Handle handle, Span<char> buffer, uint64_t offset);
1017
1023 SC::Result write(AsyncEventLoop& eventLoop, FileDescriptor::Handle handle, Span<const char> buffer,
1024 uint64_t offset);
1025
1033
1034 private:
1035 friend struct AsyncEventLoop;
1036 Operation operation = Operation::None;
1037 AsyncLoopWork loopWork;
1038 CompletionData completionData;
1039
1040 void onOperationCompleted(AsyncLoopWork::Result& res);
1041
1042 struct FileDescriptorData
1043 {
1044 FileDescriptor::Handle handle;
1045 };
1046
1047 struct OpenData
1048 {
1049 StringViewData path;
1050 FileOpen mode;
1051 };
1052
1053 struct ReadData
1054 {
1055 FileDescriptor::Handle handle;
1056 Span<char> buffer;
1057 uint64_t offset;
1058 };
1059
1060 struct WriteData
1061 {
1062 FileDescriptor::Handle handle;
1063 Span<const char> buffer;
1064 uint64_t offset;
1065 };
1066
1067 struct CopyFileData
1068 {
1069 StringViewData path;
1070 StringViewData destinationPath;
1071 FileSystemCopyFlags copyFlags;
1072 };
1073
1074 using CloseData = FileDescriptorData;
1075
1076 union
1077 {
1078 OpenData openData;
1079 CloseData closeData;
1080 ReadData readData;
1081 WriteData writeData;
1082 CopyFileData copyFileData;
1083 };
1084
1085 void destroy();
1086
1087 SC::Result start(AsyncEventLoop& eventLoop, FileDescriptor::Handle fileDescriptor);
1088 SC::Result validate(AsyncEventLoop&);
1089};
1090
1095{
1097
1098 private:
1099 int numberOfEvents = 0;
1100 friend struct AsyncEventLoop;
1101};
1102
1105{
1106 Function<void(AsyncEventLoop&)> beforeBlockingPoll;
1107 Function<void(AsyncEventLoop&)> afterBlockingPoll;
1108};
1109
1117{
1119 struct Options
1120 {
1121 enum class ApiType : uint8_t
1122 {
1123 Automatic = 0,
1126 };
1128
1130 };
1131
1133
1136
1139
1143
1146
1148 [[nodiscard]] bool isInitialized() const;
1149
1156
1167
1174
1180
1200
1207
1211
1214
1217
1220
1223
1226
1229
1232
1235
1237 [[nodiscard]] Time::Monotonic getLoopTime() const;
1238
1240 [[nodiscard]] int getNumberOfActiveRequests() const;
1241
1243 [[nodiscard]] int getNumberOfSubmittedRequests() const;
1244
1248
1251
1254
1256 void enumerateRequests(Function<void(AsyncRequest&)> enumerationCallback);
1257
1261
1263 [[nodiscard]] static bool isExcludedFromActiveCount(const AsyncRequest& async);
1264
1267 [[nodiscard]] static bool tryLoadingLiburing();
1268
1271
1272 struct Internal;
1273
1274 private:
1275 struct InternalDefinition
1276 {
1277 static constexpr int Windows = 520;
1278 static constexpr int Apple = 512;
1279 static constexpr int Linux = 720;
1280 static constexpr int Default = Linux;
1281
1282 static constexpr size_t Alignment = 8;
1283
1284 using Object = Internal;
1285 };
1286
1287 public:
1288 using InternalOpaque = OpaqueObject<InternalDefinition>;
1289
1290 private:
1291 InternalOpaque internalOpaque;
1292 Internal& internal;
1293
1294 friend struct AsyncRequest;
1295 friend struct AsyncFileWrite;
1296 friend struct AsyncFileRead;
1297 friend struct AsyncFileSystemOperation;
1298 friend struct AsyncResult;
1299};
1300
1305{
1307
1311
1314
1322
1328
1329 private:
1330#if SC_COMPILER_MSVC
1331#pragma warning(push)
1332#pragma warning(disable : 4324) // useless warning on 32 bit... (structure was padded due to __declspec(align()))
1333#endif
1334 alignas(uint64_t) uint8_t eventsMemory[8 * 1024]; // 8 Kb of kernel events
1335#if SC_COMPILER_MSVC
1336#pragma warning(pop)
1337#endif
1338
1339 AsyncKernelEvents asyncKernelEvents;
1340 AsyncEventLoop* eventLoop = nullptr;
1341 AsyncLoopWakeUp eventLoopWakeUp;
1342
1343 Thread eventLoopThread;
1344 EventObject eventObjectEnterBlockingMode;
1345 EventObject eventObjectExitBlockingMode;
1346
1347 Atomic<bool> finished = false;
1348 Atomic<bool> needsWakeUp = true;
1349
1350 bool wakeUpHasBeenCalled = false;
1351
1352 Result monitoringLoopThread(Thread& thread);
1353};
1354
1355} // 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:269
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
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:48
A buffer of bytes with given alignment.
Definition AlignedStorage.h:29
Empty base struct for all AsyncRequest-derived CompletionData (internal) structs.
Definition Async.h:256
Allow library user to provide callbacks signaling different phases of async event loop cycle.
Definition Async.h:1105
Monitors Async I/O events from a background thread using a blocking kernel function (no CPU usage on ...
Definition Async.h:1305
Function< void(void)> onNewEventsAvailable
Informs to call dispatchCompletions on GUI Event Loop.
Definition Async.h:1306
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:1120
ApiType apiType
Criteria to choose Async IO API.
Definition Async.h:1127
ApiType
Definition Async.h:1122
@ Automatic
Platform specific backend chooses the best API.
@ ForceUseEpoll
(Linux only) Tries to use epoll
@ ForceUseIOURing
(Linux only) Tries to use io_uring (failing if it's not found on the system)
Asynchronous I/O (files, sockets, timers, processes, fs events, threads wake-up) (see Async) AsyncEve...
Definition Async.h:1117
Time::Monotonic getLoopTime() const
Get Loop time.
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.
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:822
SC::Result start(AsyncEventLoop &eventLoop, FileDescriptor::Handle fileDescriptor)
Starts a file descriptor poll operation, monitoring its readiness with appropriate OS API.
Definition Async.h:694
Definition Async.h:700
Starts a file read operation, reading bytes from a file (or pipe).
Definition Async.h:690
FileDescriptor::Handle handle
The writeable span of memory where to data will be written.
Definition Async.h:713
Span< char > buffer
Callback called when some data has been read from the file into the buffer.
Definition Async.h:712
void setOffset(uint64_t fileOffset)
Sets the offset in bytes at which start reading.
Definition Async.h:721
uint64_t getOffset() const
The file/pipe descriptor handle to read data from.
Definition Async.h:717
Starts an asynchronous file system operation (open, close, read, write, sendFile, stat,...
Definition Async.h:978
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 open(AsyncEventLoop &eventLoop, StringViewData path, FileOpen mode)
Opens a file asynchronously and returns its corresponding file descriptor.
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:998
SC::Result copyFile(AsyncEventLoop &eventLoop, StringViewData path, StringViewData destinationPath, FileSystemCopyFlags copyFlags=FileSystemCopyFlags())
Copies a file from one location to another.
Definition Async.h:765
Starts a file write operation, writing bytes to a file (or pipe).
Definition Async.h:756
uint64_t getOffset() const
Returns the last offset set with AsyncFileWrite::setOffset.
Definition Async.h:793
FileDescriptor::Handle handle
The file/pipe descriptor to write data to.
Definition Async.h:785
SC::Result start(AsyncEventLoop &eventLoop, 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:797
Function< void(Result &)> callback
Callback called when descriptor is ready to be written with more data.
Definition Async.h:783
Span< Span< const char > > buffers
The read-only spans of memory where to read the data from.
Definition Async.h:789
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:788
bool singleBuffer
Controls if buffer or buffers will be used.
Definition Async.h:790
Allows user to supply a block of memory that will store kernel I/O events retrieved from AsyncEventLo...
Definition Async.h:1095
Span< uint8_t > eventsMemory
User supplied block of memory used to store kernel I/O events.
Definition Async.h:1096
Starts a Timeout that is invoked only once after expiration (relative) time has passed.
Definition Async.h:307
SC::Result start(AsyncEventLoop &eventLoop, Time::Milliseconds relativeTimeout)
Sets async request members and calls AsyncEventLoop::start.
Time::Absolute getExpirationTime() const
Gets computed absolute expiration time that determines when this timeout get executed.
Definition Async.h:322
Function< void(Result &)> callback
Called after given expiration time since AsyncLoopTimeout::start has passed.
Definition Async.h:317
Time::Milliseconds relativeTimeout
First timer expiration (relative) time in milliseconds.
Definition Async.h:319
Starts a wake-up operation, allowing threads to execute callbacks on loop thread.
Definition Async.h:343
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:356
SC::Result wakeUp(AsyncEventLoop &eventLoop)
Wakes up event loop, scheduling AsyncLoopWakeUp::callback on next AsyncEventLoop::run (or its variati...
EventObject * eventObject
Optional EventObject to let external threads wait for the callback to end.
Definition Async.h:357
Executes work in a thread pool and then invokes a callback on the event loop thread.
Definition Async.h:943
Function< void(Result &)> callback
Called to execute the work in a background threadpool thread.
Definition Async.h:954
SC::Result setThreadPool(ThreadPool &threadPool)
Sets the ThreadPool that will supply the thread to run the async work on.
Definition Async.h:380
Starts monitoring a process, notifying about its termination.
Definition Async.h:371
SC::Result start(AsyncEventLoop &eventLoop, ProcessDescriptor::Handle process)
Sets async request members and calls AsyncEventLoop::start.
Function< void(Result &)> callback
Called when process has exited.
Definition Async.h:394
Base class for all async requests, holding state and type.
Definition Async.h:122
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:160
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:189
Function< void(AsyncResult &)> * getCloseCallback()
Returns currently set close callback (if any) passed to AsyncRequest::stop.
Definition Async.h:192
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:180
void setUserFlags(uint16_t externalFlags)
Sets user flags, holding some meaningful data for the caller.
Definition Async.h:186
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:141
@ SocketSend
Request is an AsyncSocketSend object.
@ SocketReceive
Request is an AsyncSocketReceive object.
@ SocketAccept
Request is an AsyncSocketAccept object.
@ FileWrite
Request is an AsyncFileWrite object.
@ SocketSendTo
Request is an SocketSendTo object.
@ FileSystemOperation
Request is an AsyncFileSystemOperation object.
@ LoopTimeout
Request is an AsyncLoopTimeout object.
@ ProcessExit
Request is an AsyncProcessExit object.
@ FileRead
Request is an AsyncFileRead object.
@ SocketReceiveFrom
Request is an SocketReceiveFrom object.
@ FilePoll
Request is an AsyncFilePoll object.
@ LoopWakeUp
Request is an AsyncLoopWakeUp object.
@ SocketConnect
Request is an AsyncSocketConnect object.
@ LoopWork
Request is an AsyncLoopWork object.
Helper holding CompletionData for a specific AsyncRequest-derived class.
Definition Async.h:292
Base class for all async results (argument of completion callbacks).
Definition Async.h:262
const SC::Result & isValid() const
Check if the returnCode of this result is valid.
Definition Async.h:273
AsyncResult(AsyncEventLoop &eventLoop, AsyncRequest &request, SC::Result &res, bool *hasBeenReactivated=nullptr)
Constructs an async result from a request and a result.
Definition Async.h:264
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:240
bool clearSequenceOnError
Do not queue next requests in the sequence when current one returns error.
Definition Async.h:245
bool clearSequenceOnCancel
Do not queue next requests in the sequence when current one is cancelled.
Definition Async.h:244
Starts a socket accept operation, obtaining a new socket from a listening socket.
Definition Async.h:472
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:492
Function< void(Result &)> callback
Called after socket is finally connected to endpoint.
Definition Async.h:502
SC::Result start(AsyncEventLoop &eventLoop, const SocketDescriptor &descriptor, SocketIPAddress address)
Sets async request members and calls AsyncEventLoop::start.
Starts a unconnectedsocket receive from operation, receiving bytes from a remote endpoint.
Definition Async.h:655
Definition Async.h:612
SC::Result get(Span< char > &outData)
Get a Span of the actually read data.
Definition Async.h:618
Starts a socket receive operation, receiving bytes from a remote endpoint.
Definition Async.h:602
AsyncSocketReceive(Type type)
The Socket Descriptor handle to read data from.
Definition Async.h:637
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:633
Function< void(Result &)> callback
Called after data has been received.
Definition Async.h:631
Starts an unconnected socket send to operation, sending bytes to a remote endpoint.
Definition Async.h:570
Starts a socket send operation, sending bytes to a remote endpoint.
Definition Async.h:526
Function< void(Result &)> callback
Called when socket is ready to send more data.
Definition Async.h:541
bool singleBuffer
Controls if buffer or buffers will be used.
Definition Async.h:547
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:546
Span< const char > buffer
Span of bytes to send (singleBuffer == true)
Definition Async.h:545
SC::Result start(AsyncEventLoop &eventLoop, const SocketDescriptor &descriptor, Span< Span< const char > > data)
Sets async request members and calls AsyncEventLoop::start.
SocketDescriptor::Handle handle
The socket to send data to.
Definition Async.h:543
An AsyncSequence using a SC::ThreadPool to execute one or more SC::AsyncRequest in a background threa...
Definition Async.h:924
Atomic variables (only for int and bool for now).
Definition Atomic.h:97
An automatically reset event object to synchronize two threads.
Definition Threading.h:174
File Descriptor (use File to open and use it with strings and buffers).
Definition FileDescriptor.h:75
Options used to open a file descriptor.
Definition FileDescriptor.h:47
A structure to describe copy flags.
Definition FileSystemOperations.h:19
Wraps function pointers, member functions and lambdas without ever allocating.
Definition Function.h:19
An Intrusive Double Linked List.
Definition IntrusiveDoubleLinkedList.h:18
Hides implementation details from public headers (static PIMPL).
Definition OpaqueObject.h:77
Definition ProcessDescriptor.h:44
An ascii string used as boolean result. SC_TRY macro forwards errors to caller.
Definition Result.h:12
Low-level OS socket handle.
Definition SocketDescriptor.h:178
AddressFamily
Sets the address family of an IP Address (IPv4 or IPV6)
Definition SocketDescriptor.h:74
@ AddressFamilyIPV4
IP Address is IPV4.
Definition SocketDescriptor.h:75
Native representation of an IP Address.
Definition SocketDescriptor.h:119
View over a contiguous sequence of items (pointer + size in elements).
Definition Span.h:29
constexpr bool sliceStartLength(SizeType offsetInElements, SizeType lengthInElements, Span &destination) const
Creates another Span, starting at an offset in elements from current Span of specified length.
Definition Span.h:159
An read-only view over a string (to avoid including Strings library)
Definition StringViewData.h:31
A small task containing a function to execute that can be queued in the thread pool.
Definition ThreadPool.h:19
Simple thread pool that executes tasks in a fixed number of worker threads.
Definition ThreadPool.h:41
A native OS thread.
Definition Threading.h:118
Absolute time as realtime or monotonically increasing clock.
Definition Time.h:114
Type-safe wrapper of uint64 used to represent milliseconds.
Definition Time.h:44
Represent monotonically increasing time (use Monotonic::now for current time)
Definition Time.h:180