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 "../Common/CompilerMacrosExport.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 "../Common/Assert.h"
13#include "../Common/Function.h"
14#include "../Common/OpaqueObject.h"
15#include "../File/File.h"
16#include "../FileSystem/FileSystem.h"
17#include "../Socket/Socket.h"
18#include "../Threading/Atomic.h"
19#include "../Threading/ThreadPool.h"
20
21namespace SC
22{
23SC_DECLARE_ASSERT_PROVIDER(AsyncAssert, SC_ASYNC_EXPORT);
24
25#define SC_ASYNC_ASSERT_RELEASE(e) SC_ASSERT_PROVIDER_RELEASE(SC::AsyncAssert, e)
26#define SC_ASYNC_ASSERT_DEBUG(e) SC_ASSERT_PROVIDER_DEBUG(SC::AsyncAssert, e)
27#define SC_ASYNC_TRUST_RESULT(expression) SC_ASYNC_ASSERT_RELEASE(expression)
28
29struct ThreadPool;
30struct ThreadPoolTask;
31struct EventObject;
32} // namespace SC
57
60namespace SC
61{
62struct AsyncEventLoop;
63struct AsyncResult;
64struct AsyncSequence;
65struct AsyncTaskSequence;
66
67namespace detail
68{
69struct AsyncWinOverlapped;
70struct AsyncWinOverlappedDefinition
71{
72 static constexpr int Windows = sizeof(void*) * 4 + sizeof(uint64_t);
73 static constexpr size_t Alignment = alignof(void*);
74
75 using Object = AsyncWinOverlapped;
76};
77using WinOverlappedOpaque = OpaqueObject<AsyncWinOverlappedDefinition>;
78
79struct AsyncWinWaitDefinition
80{
81 using Handle = FileDescriptor::Handle; // fd
82 static constexpr Handle Invalid = FileDescriptor::Invalid; // invalid fd
83
84 static Result releaseHandle(Handle& waitHandle);
85};
86struct SC_ASYNC_EXPORT WinWaitHandle : public UniqueHandle<AsyncWinWaitDefinition>
87{
88};
89} // namespace detail
90
129struct SC_ASYNC_EXPORT AsyncRequest
130{
131 AsyncRequest* next = nullptr;
132 AsyncRequest* prev = nullptr;
133
134 void setDebugName(const char* newDebugName);
135
137 void executeOn(AsyncSequence& sequence);
138
143
146
148 enum class Type : uint8_t
149 {
150 LoopTimeout,
151 LoopWakeUp,
152 LoopWork,
153 ProcessExit,
154 Signal,
155 SocketAccept,
156 SocketConnect,
157 SocketSend,
158 SocketSendTo,
159 SocketReceive,
160 SocketReceiveFrom,
161 FileRead,
162 FileWrite,
163 FileSend,
164 FileReadiness,
165 ExternalCompletion,
166 FileSystemOperation,
167 };
168
171 AsyncRequest(Type type) : state(State::Free), type(type), flags(0), unused(0), userFlags(0) {}
172
179 Result stop(AsyncEventLoop& eventLoop, Function<void(AsyncResult&)>* afterStopped = nullptr);
180
182 [[nodiscard]] bool isFree() const;
183
185 [[nodiscard]] bool isCancelling() const;
186
188 [[nodiscard]] bool isActive() const;
189
191 [[nodiscard]] Type getType() const { return type; }
192
194 Result start(AsyncEventLoop& eventLoop);
195
197 void setUserFlags(uint16_t externalFlags) { userFlags = externalFlags; }
198
200 uint16_t getUserFlags() const { return userFlags; }
201
203 [[nodiscard]] Function<void(AsyncResult&)>* getCloseCallback() { return closeCallback; }
204
205 [[nodiscard]] const Function<void(AsyncResult&)>* getCloseCallback() const { return closeCallback; }
206
207 protected:
208 Result checkState();
209
210 void queueSubmission(AsyncEventLoop& eventLoop);
211
212 AsyncSequence* sequence = nullptr;
213
214 AsyncTaskSequence* getTask();
215
216 private:
217 Function<void(AsyncResult&)>* closeCallback = nullptr;
218
219 friend struct AsyncEventLoop;
220 friend struct AsyncResult;
221
222 void markAsFree();
223
224 [[nodiscard]] static const char* TypeToString(Type type);
225 enum class State : uint8_t
226 {
227 Free, // not in any queue, this can be started with an async.start(...)
228 Setup, // when in submission queue waiting to be setup (after an async.start(...))
229 Submitting, // when in submission queue waiting to be activated or re-activated
230 Active, // when monitored by OS syscall or in activeLoopWakeUps / activeTimeouts queues
231 Reactivate, // when flagged for reactivation inside the callback (after a result.reactivateRequest(true))
232 Cancelling, // when in cancellation queue waiting for a cancelAsync (on active async)
233 };
234
235#if SC_ASYNC_ENABLE_LOG
236 const char* debugName = "None";
237#endif
238 State state; // 1 byte
239 Type type; // 1 byte
240 int16_t flags; // 2 bytes
241
242 uint16_t unused; // 2 bytes
243 uint16_t userFlags; // 2 bytes
244};
245
250struct SC_ASYNC_EXPORT AsyncSequence
251{
252 AsyncSequence* next = nullptr;
253 AsyncSequence* prev = nullptr;
254
255 bool clearSequenceOnCancel = true;
256 bool clearSequenceOnError = true;
257 private:
258 friend struct AsyncEventLoop;
259 bool runningAsync = false; // true if an async from this sequence is being run
260 bool tracked = false;
261
262 IntrusiveDoubleLinkedList<AsyncRequest> submissions;
263};
264
266struct SC_ASYNC_EXPORT AsyncCompletionData
267{
268};
269
272struct SC_ASYNC_EXPORT AsyncResult
273{
275 AsyncResult(AsyncEventLoop& eventLoop, AsyncRequest& request, SC::Result& res, bool* hasBeenReactivated = nullptr)
276 : eventLoop(eventLoop), async(request), hasBeenReactivated(hasBeenReactivated), returnCode(res)
277 {}
278
281 void reactivateRequest(bool shouldBeReactivated);
282
284 [[nodiscard]] const SC::Result& isValid() const { return returnCode; }
285
286 AsyncEventLoop& eventLoop;
287 AsyncRequest& async;
288
289 protected:
290 friend struct AsyncEventLoop;
291
292 bool shouldCallCallback = true;
293 bool* hasBeenReactivated = nullptr;
294
295 SC::Result& returnCode;
296};
297
301template <typename T, typename C>
303{
304 T& getAsync() { return static_cast<T&>(AsyncResult::async); }
305 const T& getAsync() const { return static_cast<const T&>(AsyncResult::async); }
306
308
309 C completionData;
310 int32_t eventIndex = 0;
311};
312
317struct SC_ASYNC_EXPORT AsyncLoopTimeout : public AsyncRequest
318{
319 AsyncLoopTimeout() : AsyncRequest(Type::LoopTimeout) {}
320
323 using AsyncRequest::start;
324
326 SC::Result start(AsyncEventLoop& eventLoop, TimeMs relativeTimeout);
327
328 Function<void(Result&)> callback;
329
331
333 TimeMs getExpirationTime() const { return expirationTime; }
334
335 private:
336 SC::Result validate(AsyncEventLoop&);
337 friend struct AsyncEventLoop;
338 TimeMs expirationTime;
339};
340
343{
346 bool coalesce = true;
347};
348
365struct SC_ASYNC_EXPORT AsyncLoopWakeUp : public AsyncRequest
366{
367 AsyncLoopWakeUp() : AsyncRequest(Type::LoopWakeUp) {}
368
370 {
371 uint32_t deliveryCount = 1;
372 };
373
375
377 SC::Result start(AsyncEventLoop& eventLoop, AsyncLoopWakeUpOptions options = {});
378
380 SC::Result start(AsyncEventLoop& eventLoop, EventObject& eventObject, AsyncLoopWakeUpOptions options = {});
381
383 SC::Result wakeUp(AsyncEventLoop& eventLoop);
384
385 Function<void(Result&)> callback;
386 EventObject* eventObject = nullptr;
387
388 private:
389 friend struct AsyncEventLoop;
390 SC::Result validate(AsyncEventLoop&);
391 int32_t consumePendingWakeUps();
392 int32_t getPendingWakeUps() const;
393
394 AsyncLoopWakeUpOptions wakeUpOptions;
395 Atomic<int32_t> pendingWakeUps = 0;
396};
397
402struct SC_ASYNC_EXPORT AsyncProcessExit : public AsyncRequest
403{
404 AsyncProcessExit() : AsyncRequest(Type::ProcessExit) {}
405
407 {
408 int exitStatus;
409 };
410
411 struct Result : public AsyncResultOf<AsyncProcessExit, CompletionData>
412 {
413 using AsyncResultOf<AsyncProcessExit, CompletionData>::AsyncResultOf;
414
415 SC::Result get(int& status)
416 {
417 status = completionData.exitStatus;
418 return returnCode;
419 }
420 };
421 using AsyncRequest::start;
422
426 SC::Result start(AsyncEventLoop& eventLoop, FileDescriptor::Handle process);
427
428 Function<void(Result&)> callback;
429
430 private:
431 friend struct AsyncEventLoop;
432 SC::Result validate(AsyncEventLoop&);
433
434 FileDescriptor::Handle handle = FileDescriptor::Invalid;
435#if SC_PLATFORM_WINDOWS
436 detail::WinOverlappedOpaque overlapped;
437 detail::WinWaitHandle waitHandle;
438 AsyncEventLoop* eventLoop = nullptr;
439#elif SC_PLATFORM_LINUX
440 FileDescriptor pidFd;
441#endif
442};
443
446{
448 enum class Mode : uint8_t
449 {
450 Persistent,
451 OneShot
452 };
454 bool coalesce = true;
455};
456
464struct SC_ASYNC_EXPORT AsyncSignal : public AsyncRequest
465{
466 AsyncSignal() : AsyncRequest(Type::Signal) {}
467
469 {
470 int signalNumber = 0;
471 uint32_t deliveryCount = 1;
472 };
473
474 struct Result : public AsyncResultOf<AsyncSignal, CompletionData>
475 {
476 using AsyncResultOf<AsyncSignal, CompletionData>::AsyncResultOf;
477 };
478 using AsyncRequest::start;
479
481 SC::Result start(AsyncEventLoop& eventLoop, int num, AsyncSignalOptions options = {});
482
483 Function<void(Result&)> callback;
484
485 private:
486 friend struct AsyncEventLoop;
487 SC::Result validate(AsyncEventLoop&);
488
489 int signalNumber = 0;
490 AsyncSignalOptions signalOptions;
491#if SC_PLATFORM_WINDOWS
492 detail::WinOverlappedOpaque overlapped;
493 AsyncEventLoop* eventLoop = nullptr;
494#elif SC_PLATFORM_LINUX
495 FileDescriptor signalFd;
496 FileDescriptor::Handle signalFdHandle = FileDescriptor::Invalid;
497#endif
498};
499
500struct AsyncSocketAccept;
501namespace detail
502{
505struct SC_ASYNC_EXPORT AsyncSocketAcceptData
506{
507#if SC_PLATFORM_WINDOWS
508 void (*pAcceptEx)() = nullptr;
509 detail::WinOverlappedOpaque overlapped;
510 SocketDescriptor clientSocket;
511 uint8_t acceptBuffer[288] = {0};
512#elif SC_PLATFORM_LINUX
513 AlignedStorage<28> sockAddrHandle;
514 uint32_t sockAddrLen;
515#endif
516};
517
519struct SC_ASYNC_EXPORT AsyncSocketAcceptBase : public AsyncRequest
520{
521 AsyncSocketAcceptBase() : AsyncRequest(Type::SocketAccept) {}
522
523 struct CompletionData : public AsyncCompletionData
524 {
525 SocketDescriptor acceptedClient;
526 };
527
528 struct Result : public AsyncResultOf<AsyncSocketAccept, CompletionData>
529 {
530 using AsyncResultOf<AsyncSocketAccept, CompletionData>::AsyncResultOf;
531
532 SC::Result moveTo(SocketDescriptor& client)
533 {
534 SC_TRY(returnCode);
535 return SC::Result(client.assign(move(completionData.acceptedClient)));
536 }
537 };
538 using AsyncRequest::start;
539
541 SC::Result start(AsyncEventLoop& eventLoop, const SocketDescriptor& socketDescriptor, AsyncSocketAcceptData& data);
542 SC::Result validate(AsyncEventLoop&);
543
544 Function<void(Result&)> callback;
545 SocketDescriptor::Handle handle = SocketDescriptor::Invalid;
546 SocketFlags::AddressFamily addressFamily = SocketFlags::AddressFamilyIPV4;
547 AsyncSocketAcceptData* acceptData = nullptr;
548};
549
550} // namespace detail
551
561struct SC_ASYNC_EXPORT AsyncSocketAccept : public detail::AsyncSocketAcceptBase
562{
563 AsyncSocketAccept() { AsyncSocketAcceptBase::acceptData = &data; }
564 using AsyncSocketAcceptBase::start;
565
567 SC::Result start(AsyncEventLoop& eventLoop, const SocketDescriptor& socketDescriptor);
568
569 private:
570 detail::AsyncSocketAcceptData data;
571};
572
581struct SC_ASYNC_EXPORT AsyncSocketConnect : public AsyncRequest
582{
583 AsyncSocketConnect() : AsyncRequest(Type::SocketConnect) {}
584
587 using AsyncRequest::start;
588
590 SC::Result start(AsyncEventLoop& eventLoop, const SocketDescriptor& descriptor, SocketIPAddress address);
591
592 Function<void(Result&)> callback;
593
594 SocketDescriptor::Handle handle = SocketDescriptor::Invalid;
595 SocketIPAddress ipAddress;
596
597 private:
598 friend struct AsyncEventLoop;
599 SC::Result validate(AsyncEventLoop&);
600
601#if SC_PLATFORM_WINDOWS
602 void (*pConnectEx)() = nullptr;
603 detail::WinOverlappedOpaque overlapped;
604#endif
605};
606
615struct SC_ASYNC_EXPORT AsyncSocketSend : public AsyncRequest
616{
617 AsyncSocketSend() : AsyncRequest(Type::SocketSend) {}
619 {
620 size_t numBytes = 0;
621 };
623 using AsyncRequest::start;
624
626 SC::Result start(AsyncEventLoop& eventLoop, const SocketDescriptor& descriptor, Span<const char> data);
627
629 SC::Result start(AsyncEventLoop& eventLoop, const SocketDescriptor& descriptor, Span<Span<const char>> data);
630
631 Function<void(Result&)> callback;
632
633 SocketDescriptor::Handle handle = SocketDescriptor::Invalid;
634
635 SC::Result closeHandle() { return detail::SocketDescriptorDefinition::releaseHandle(handle); }
636
637 Span<const char> buffer;
638 Span<Span<const char>> buffers;
639 bool singleBuffer = true;
640
641 protected:
642 AsyncSocketSend(Type type) : AsyncRequest(type) {}
643 friend struct AsyncEventLoop;
644 SC::Result validate(AsyncEventLoop&);
645
646 size_t totalBytesWritten = 0;
647#if SC_PLATFORM_WINDOWS
648 detail::WinOverlappedOpaque overlapped;
649#endif
650};
651
661struct SC_ASYNC_EXPORT AsyncSocketSendTo : public AsyncSocketSend
662{
663 AsyncSocketSendTo() : AsyncSocketSend(Type::SocketSendTo) {}
664
665 SocketIPAddress address;
666
667 SC::Result start(AsyncEventLoop& eventLoop, const SocketDescriptor& descriptor, SocketIPAddress ipAddress,
668 Span<const char> data);
669
670 SC::Result start(AsyncEventLoop& eventLoop, const SocketDescriptor& descriptor, SocketIPAddress ipAddress,
671 Span<Span<const char>> data);
672
673 private:
674 using AsyncSocketSend::start;
675 friend struct AsyncEventLoop;
676 SC::Result validate(AsyncEventLoop&);
677#if SC_PLATFORM_LINUX
678 AlignedStorage<56> typeErasedMsgHdr;
679#endif
680};
681
693struct SC_ASYNC_EXPORT AsyncSocketReceive : public AsyncRequest
694{
695 AsyncSocketReceive() : AsyncRequest(Type::SocketReceive) {}
696
698 {
699 size_t numBytes = 0;
700 bool disconnected = false;
701 };
702
703 struct Result : public AsyncResultOf<AsyncSocketReceive, CompletionData>
704 {
705 using AsyncResultOf<AsyncSocketReceive, CompletionData>::AsyncResultOf;
706
707 bool isEnded() const { return completionData.disconnected; }
708
712 SC::Result get(Span<char>& outData)
713 {
714 SC_TRY(getAsync().buffer.sliceStartLength(0, completionData.numBytes, outData));
715 return returnCode;
716 }
717
718 SocketIPAddress getSourceAddress() const;
719 };
720 using AsyncRequest::start;
721
723 SC::Result start(AsyncEventLoop& eventLoop, const SocketDescriptor& descriptor, Span<char> data);
724
725 Function<void(Result&)> callback;
726
727 Span<char> buffer;
728 SocketDescriptor::Handle handle = SocketDescriptor::Invalid;
729
730 SC::Result closeHandle() { return detail::SocketDescriptorDefinition::releaseHandle(handle); }
731
732 protected:
733 AsyncSocketReceive(Type type) : AsyncRequest(type) {}
734 friend struct AsyncEventLoop;
735 SC::Result validate(AsyncEventLoop&);
736#if SC_PLATFORM_WINDOWS
737 detail::WinOverlappedOpaque overlapped;
738#endif
739};
740
750struct SC_ASYNC_EXPORT AsyncSocketReceiveFrom : public AsyncSocketReceive
751{
752 AsyncSocketReceiveFrom() : AsyncSocketReceive(Type::SocketReceiveFrom) {}
753 using AsyncSocketReceive::start;
754
755 private:
756 SocketIPAddress address;
757 friend struct AsyncSocketReceive;
758 friend struct AsyncEventLoop;
759#if SC_PLATFORM_LINUX
760 AlignedStorage<56> typeErasedMsgHdr;
761#endif
762};
763
785struct SC_ASYNC_EXPORT AsyncFileRead : public AsyncRequest
786{
787 AsyncFileRead() : AsyncRequest(Type::FileRead) { handle = FileDescriptor::Invalid; }
788
790 {
791 size_t numBytes = 0;
792 bool endOfFile = false;
793 };
794
795 struct Result : public AsyncResultOf<AsyncFileRead, CompletionData>
796 {
797 using AsyncResultOf<AsyncFileRead, CompletionData>::AsyncResultOf;
798
799 bool isEnded() const { return completionData.endOfFile; }
800
801 SC::Result get(Span<char>& data)
802 {
803 SC_TRY(getAsync().buffer.sliceStartLength(0, completionData.numBytes, data));
804 return returnCode;
805 }
806 };
807 using AsyncRequest::start;
808
810 SC::Result start(AsyncEventLoop& eventLoop, const FileDescriptor& descriptor, Span<char> data);
811
812 Function<void(Result&)> callback;
813 Span<char> buffer;
814 FileDescriptor::Handle handle;
816
817 SC::Result closeHandle() { return detail::FileDescriptorDefinition::releaseHandle(handle); }
818
820 uint64_t getOffset() const { return offset; }
821
824 void setOffset(uint64_t fileOffset)
825 {
826 useOffset = true;
827 offset = fileOffset;
828 }
829
830 private:
831 friend struct AsyncEventLoop;
832 SC::Result validate(AsyncEventLoop&);
833
834 bool useOffset = false;
835 bool endedSync = false;
836
837 uint64_t offset = 0;
838#if SC_PLATFORM_WINDOWS
839 uint64_t readCursor = 0;
840 detail::WinOverlappedOpaque overlapped;
841#endif
842};
843
861struct SC_ASYNC_EXPORT AsyncFileWrite : public AsyncRequest
862{
863 AsyncFileWrite() : AsyncRequest(Type::FileWrite) { handle = FileDescriptor::Invalid; }
864
866 {
867 size_t numBytes = 0;
868 };
869
870 struct Result : public AsyncResultOf<AsyncFileWrite, CompletionData>
871 {
872 using AsyncResultOf<AsyncFileWrite, CompletionData>::AsyncResultOf;
873
874 SC::Result get(size_t& writtenSizeInBytes)
875 {
876 writtenSizeInBytes = completionData.numBytes;
877 return returnCode;
878 }
879 };
880
881 using AsyncRequest::start;
882
884 SC::Result start(AsyncEventLoop& eventLoop, const FileDescriptor& descriptor, Span<Span<const char>> data);
885
887 SC::Result start(AsyncEventLoop& eventLoop, Span<Span<const char>> data);
888
890 SC::Result start(AsyncEventLoop& eventLoop, const FileDescriptor& descriptor, Span<const char> data);
891
893 SC::Result start(AsyncEventLoop& eventLoop, Span<const char> data);
894
895 Function<void(Result&)> callback;
896
897 FileDescriptor::Handle handle;
899
900 SC::Result closeHandle() { return detail::FileDescriptorDefinition::releaseHandle(handle); }
901
902 Span<const char> buffer;
903 Span<Span<const char>> buffers;
904 bool singleBuffer = true;
905
907 uint64_t getOffset() const { return offset; }
908
911 void setOffset(uint64_t fileOffset)
912 {
913 useOffset = true;
914 offset = fileOffset;
915 }
916
917 private:
918 friend struct AsyncEventLoop;
919 SC::Result validate(AsyncEventLoop&);
920
921#if SC_PLATFORM_WINDOWS
922 bool endedSync = false;
923#else
924 bool isWatchable = false;
925#endif
926 bool useOffset = false;
927 uint64_t offset = 0xffffffffffffffff;
928
929 size_t totalBytesWritten = 0;
930#if SC_PLATFORM_WINDOWS
931 detail::WinOverlappedOpaque overlapped;
932#endif
933};
934
938struct SC_ASYNC_EXPORT AsyncFileReadiness : public AsyncRequest
939{
940 AsyncFileReadiness() : AsyncRequest(Type::FileReadiness) {}
941
944
946 SC::Result start(AsyncEventLoop& eventLoop, FileDescriptor::Handle fileDescriptor);
947
948 Function<void(Result&)> callback;
949
950 private:
951 friend struct AsyncEventLoop;
952 SC::Result validate(AsyncEventLoop&);
953
954 FileDescriptor::Handle handle = FileDescriptor::Invalid;
955};
956
960struct SC_ASYNC_EXPORT AsyncExternalCompletion : public AsyncRequest
961{
963 {
964 size_t bytesTransferred = 0;
965 };
967
968 AsyncExternalCompletion() : AsyncRequest(Type::ExternalCompletion) {}
969
971 SC::Result start(AsyncEventLoop& eventLoop);
972
973#if SC_PLATFORM_WINDOWS
975 SC::Result start(AsyncEventLoop& eventLoop, FileDescriptor::Handle fileDescriptor);
976
978 [[nodiscard]] void* getWindowsOverlapped();
979#endif
980
983
986
987 [[nodiscard]] bool hasSubmissionPending() const { return submissionPending; }
988
989 Function<void(Result&)> callback;
990
991 private:
992 friend struct AsyncEventLoop;
993 SC::Result validate(AsyncEventLoop&);
994
995 FileDescriptor::Handle handle = FileDescriptor::Invalid;
996 size_t bytesTransferred = 0;
997 bool manualMode = true;
998 bool submissionPending = false;
999 bool completionPosted = false;
1000#if SC_PLATFORM_WINDOWS
1001 detail::WinOverlappedOpaque overlapped;
1002#endif
1003};
1004
1029struct SC_ASYNC_EXPORT AsyncFileSend : public AsyncRequest
1030{
1031 AsyncFileSend() : AsyncRequest(Type::FileSend) {}
1032
1034 {
1035 size_t bytesTransferred = 0;
1036 bool usedZeroCopy = false;
1037 };
1038
1039 struct Result : public AsyncResultOf<AsyncFileSend, CompletionData>
1040 {
1041 using AsyncResultOf<AsyncFileSend, CompletionData>::AsyncResultOf;
1042
1044 [[nodiscard]] size_t getBytesTransferred() const { return completionData.bytesTransferred; }
1045
1047 [[nodiscard]] bool usedZeroCopy() const { return completionData.usedZeroCopy; }
1048
1050 [[nodiscard]] bool isComplete() const
1051 {
1052 return returnCode && completionData.bytesTransferred == getAsync().length;
1053 }
1054 };
1055
1056 using AsyncRequest::start;
1057
1067 SC::Result start(AsyncEventLoop& eventLoop, const FileDescriptor& file, const SocketDescriptor& socket,
1068 int64_t offset = 0, size_t length = 0, size_t pipeSize = 0);
1069
1070 Function<void(Result&)> callback;
1071
1072 // Internal handles (set by start())
1073 FileDescriptor::Handle fileHandle = FileDescriptor::Invalid;
1074 SocketDescriptor::Handle socketHandle = SocketDescriptor::Invalid;
1075
1076 int64_t offset = 0;
1077 size_t length = 0;
1078 size_t bytesSent = 0;
1079 private:
1080 friend struct AsyncEventLoop;
1081 SC::Result validate(AsyncEventLoop&);
1082
1083#if SC_PLATFORM_WINDOWS
1084 detail::WinOverlappedOpaque overlapped;
1085#elif SC_PLATFORM_LINUX
1086 size_t pipeBufferSize = 0;
1087 PipeDescriptor splicePipe;
1088#endif
1089};
1090
1091// forward declared because it must be defined after AsyncTaskSequence
1092struct AsyncLoopWork;
1094
1096{
1097 FileDescriptor::Handle handle = FileDescriptor::Invalid; // for open
1098
1099 int code = 0; // for open/close
1100 size_t numBytes = 0; // for read
1101};
1102
1103namespace detail
1104{
1105// A simple hand-made variant of all completion types
1106struct SC_ASYNC_EXPORT AsyncCompletionVariant
1107{
1108 AsyncCompletionVariant() {}
1109 ~AsyncCompletionVariant() { destroy(); }
1110
1111 AsyncCompletionVariant(const AsyncCompletionVariant&) = delete;
1112 AsyncCompletionVariant(AsyncCompletionVariant&&) = delete;
1113 AsyncCompletionVariant& operator=(const AsyncCompletionVariant&) = delete;
1114 AsyncCompletionVariant& operator=(AsyncCompletionVariant&&) = delete;
1115
1116 bool inited = false;
1117
1118 AsyncRequest::Type type;
1119 union
1120 {
1121 AsyncCompletionData completionDataLoopWork; // Defined after AsyncCompletionVariant / AsyncTaskSequence
1122 AsyncLoopTimeout::CompletionData completionDataLoopTimeout;
1123 AsyncLoopWakeUp::CompletionData completionDataLoopWakeUp;
1124 AsyncProcessExit::CompletionData completionDataProcessExit;
1125 AsyncSignal::CompletionData completionDataSignal;
1126 AsyncSocketAccept::CompletionData completionDataSocketAccept;
1127 AsyncSocketConnect::CompletionData completionDataSocketConnect;
1128 AsyncSocketSend::CompletionData completionDataSocketSend;
1129 AsyncSocketSendTo::CompletionData completionDataSocketSendTo;
1130 AsyncSocketReceive::CompletionData completionDataSocketReceive;
1131 AsyncSocketReceiveFrom::CompletionData completionDataSocketReceiveFrom;
1132 AsyncFileRead::CompletionData completionDataFileRead;
1133 AsyncFileWrite::CompletionData completionDataFileWrite;
1134 AsyncFileSend::CompletionData completionDataFileSend;
1135 AsyncFileReadiness::CompletionData completionDataFileReadiness;
1136 AsyncExternalCompletion::CompletionData completionDataExternalCompletion;
1137
1138 AsyncFileSystemOperationCompletionData completionDataFileSystemOperation;
1139 };
1140
1141 auto& getCompletion(AsyncLoopWork&) { return completionDataLoopWork; }
1142 auto& getCompletion(AsyncLoopTimeout&) { return completionDataLoopTimeout; }
1143 auto& getCompletion(AsyncLoopWakeUp&) { return completionDataLoopWakeUp; }
1144 auto& getCompletion(AsyncProcessExit&) { return completionDataProcessExit; }
1145 auto& getCompletion(AsyncSignal&) { return completionDataSignal; }
1146 auto& getCompletion(AsyncSocketAccept&) { return completionDataSocketAccept; }
1147 auto& getCompletion(AsyncSocketConnect&) { return completionDataSocketConnect; }
1148 auto& getCompletion(AsyncSocketSend&) { return completionDataSocketSend; }
1149 auto& getCompletion(AsyncSocketReceive&) { return completionDataSocketReceive; }
1150 auto& getCompletion(AsyncFileRead&) { return completionDataFileRead; }
1151 auto& getCompletion(AsyncFileWrite&) { return completionDataFileWrite; }
1152 auto& getCompletion(AsyncFileSend&) { return completionDataFileSend; }
1153 auto& getCompletion(AsyncFileReadiness&) { return completionDataFileReadiness; }
1154 auto& getCompletion(AsyncExternalCompletion&) { return completionDataExternalCompletion; }
1155 auto& getCompletion(AsyncFileSystemOperation&) { return completionDataFileSystemOperation; }
1156
1157 template <typename T>
1158 auto& construct(T& t)
1159 {
1160 destroy();
1161 placementNew(getCompletion(t));
1162 inited = true;
1163 type = t.getType();
1164 return getCompletion(t);
1165 }
1166 void destroy();
1167};
1168} // namespace detail
1169
1173struct SC_ASYNC_EXPORT AsyncTaskSequence : public AsyncSequence
1174{
1175 protected:
1176 ThreadPoolTask task;
1177 ThreadPool* threadPool = nullptr;
1178
1179 friend struct AsyncEventLoop;
1180 friend struct AsyncRequest;
1181
1182 detail::AsyncCompletionVariant completion;
1183
1184 SC::Result returnCode = SC::Result(true);
1185};
1186
1192struct SC_ASYNC_EXPORT AsyncLoopWork : public AsyncRequest
1193{
1194 AsyncLoopWork() : AsyncRequest(Type::LoopWork) {}
1195
1198
1201 SC::Result setThreadPool(ThreadPool& threadPool);
1202
1203 Function<SC::Result()> work;
1204 Function<void(Result&)> callback;
1205
1206 private:
1207 friend struct AsyncEventLoop;
1208 SC::Result validate(AsyncEventLoop&);
1209 AsyncTaskSequence task;
1210};
1211
1245struct SC_ASYNC_EXPORT AsyncFileSystemOperation : public AsyncRequest
1246{
1247 AsyncFileSystemOperation() : AsyncRequest(Type::FileSystemOperation) {}
1248 ~AsyncFileSystemOperation() { destroy(); }
1249#ifdef CopyFile
1250#undef CopyFile
1251#endif
1252#ifdef RemoveDirectory
1253#undef RemoveDirectory
1254#endif
1255 enum class Operation
1256 {
1257 None = 0,
1258 Open,
1259 Close,
1260 Read,
1261 Write,
1262 CopyFile,
1263 CopyDirectory,
1264 Rename,
1265 RemoveDirectory,
1266 RemoveFile,
1267 };
1268
1271
1273 SC::Result setThreadPool(ThreadPool& threadPool);
1274
1276 SC::Result stop(AsyncEventLoop& eventLoop, Function<void(AsyncResult&)>* afterStopped = nullptr);
1277
1278 Function<void(Result&)> callback;
1279
1285 SC::Result open(AsyncEventLoop& eventLoop, StringSpan path, FileOpen mode);
1286
1291 SC::Result close(AsyncEventLoop& eventLoop, FileDescriptor::Handle handle);
1292
1299 SC::Result read(AsyncEventLoop& eventLoop, FileDescriptor::Handle handle, Span<char> buffer, uint64_t offset);
1300
1307 SC::Result write(AsyncEventLoop& eventLoop, FileDescriptor::Handle handle, Span<const char> buffer,
1308 uint64_t offset);
1309
1316 SC::Result copyFile(AsyncEventLoop& eventLoop, StringSpan path, StringSpan destinationPath,
1318
1325 SC::Result copyDirectory(AsyncEventLoop& eventLoop, StringSpan path, StringSpan destinationPath,
1327
1333 SC::Result rename(AsyncEventLoop& eventLoop, StringSpan path, StringSpan newPath);
1334
1340 SC::Result removeEmptyDirectory(AsyncEventLoop& eventLoop, StringSpan path);
1341
1346 SC::Result removeFile(AsyncEventLoop& eventLoop, StringSpan path);
1347
1348 private:
1349 friend struct AsyncEventLoop;
1350 Operation operation = Operation::None;
1351 AsyncLoopWork loopWork;
1352 CompletionData completionData;
1353
1354 void onOperationCompleted(AsyncLoopWork::Result& res);
1355
1356 struct FileDescriptorData
1357 {
1358 FileDescriptor::Handle handle;
1359 };
1360
1361 struct OpenData
1362 {
1363 StringSpan path;
1364 FileOpen mode;
1365 };
1366
1367 struct ReadData
1368 {
1369 FileDescriptor::Handle handle;
1370 Span<char> buffer;
1371 uint64_t offset;
1372 };
1373
1374 struct WriteData
1375 {
1376 FileDescriptor::Handle handle;
1377 Span<const char> buffer;
1378 uint64_t offset;
1379 };
1380
1381 struct CopyFileData
1382 {
1383 StringSpan path;
1384 StringSpan destinationPath;
1385 FileSystemCopyFlags copyFlags;
1386 };
1387
1388 using CopyDirectoryData = CopyFileData;
1389
1390 using CloseData = FileDescriptorData;
1391
1392 struct RenameData
1393 {
1394 StringSpan path;
1395 StringSpan newPath;
1396 };
1397
1398 struct RemoveData
1399 {
1400 StringSpan path;
1401 };
1402
1403 union
1404 {
1405 OpenData openData;
1406 CloseData closeData;
1407 ReadData readData;
1408 WriteData writeData;
1409 CopyFileData copyFileData;
1410 CopyDirectoryData copyDirectoryData;
1411 RenameData renameData;
1412 RemoveData removeData;
1413 };
1414
1415 void destroy();
1416
1417 SC::Result start(AsyncEventLoop& eventLoop, FileDescriptor::Handle fileDescriptor);
1418 SC::Result validate(AsyncEventLoop&);
1419};
1420
1424struct SC_ASYNC_EXPORT AsyncKernelEvents
1425{
1426 Span<uint8_t> eventsMemory;
1427
1428 private:
1429 int numberOfEvents = 0;
1430 friend struct AsyncEventLoop;
1431};
1432
1434struct SC_ASYNC_EXPORT AsyncEventLoopListeners
1435{
1436 Function<void(AsyncEventLoop&)> beforeBlockingPoll;
1437 Function<void(AsyncEventLoop&)> afterBlockingPoll;
1438};
1439
1446struct SC_ASYNC_EXPORT AsyncEventLoop
1447{
1449 struct Options
1450 {
1451 enum class ApiType : uint8_t
1452 {
1453 Automatic = 0,
1454 ForceUseIoUring,
1455 ForceUseEpoll,
1456 };
1458
1459 Options() { apiType = ApiType::Automatic; }
1460 };
1461
1463
1464 AsyncEventLoop(const AsyncEventLoop&) = delete;
1465 AsyncEventLoop(AsyncEventLoop&&) = delete;
1466 AsyncEventLoop& operator=(AsyncEventLoop&&) = delete;
1467 AsyncEventLoop& operator=(const AsyncEventLoop&) = delete;
1468
1470 Result create(Options options = Options());
1471
1473 Result close();
1474
1477 Result start(AsyncRequest& async);
1478
1480 Result postExternalCompletion(AsyncExternalCompletion& async, size_t bytesTransferred = 0);
1481
1484
1486 [[nodiscard]] bool isInitialized() const;
1487
1489 [[nodiscard]] bool needsThreadPoolForFileOperations() const;
1490
1496 Result run();
1497
1507 Result runOnce();
1508
1514 Result runNoWait();
1515
1520 Result submitRequests(AsyncKernelEvents& kernelEvents);
1521
1540 Result blockingPoll(AsyncKernelEvents& kernelEvents);
1541
1548
1552
1555
1558
1561
1564
1566 Result associateExternallyCreatedSocketHandle(SocketDescriptor::Handle handle);
1567
1570
1572 Result associateExternallyCreatedFileDescriptorHandle(FileDescriptor::Handle handle);
1573
1575 static Result removeAllAssociationsFor(SocketDescriptor& outDescriptor);
1576
1578 static Result removeAllAssociationsForSocketHandle(SocketDescriptor::Handle handle);
1579
1581 static Result removeAllAssociationsFor(FileDescriptor& outDescriptor);
1582
1584 static Result removeAllAssociationsForFileDescriptorHandle(FileDescriptor::Handle handle);
1585
1588
1590 [[nodiscard]] TimeMs getLoopTime() const;
1591
1593 [[nodiscard]] int getNumberOfActiveRequests() const;
1594
1596 [[nodiscard]] int getNumberOfSubmittedRequests() const;
1597
1601
1604
1607
1609 void enumerateRequests(Function<void(AsyncRequest&)> enumerationCallback);
1610
1614
1616 [[nodiscard]] static bool isExcludedFromActiveCount(const AsyncRequest& async);
1617
1620 [[nodiscard]] static bool tryProbingIOUring();
1621
1624
1625 struct Internal;
1626
1628 using LoopWork = AsyncLoopWork;
1631 using Signal = AsyncSignal;
1638 using FileRead = AsyncFileRead;
1639 using FileWrite = AsyncFileWrite;
1640 using FileSend = AsyncFileSend;
1645 using ResultType = AsyncResult;
1646
1647 public:
1648 struct SC_ASYNC_EXPORT InternalDefinition
1649 {
1650 static constexpr int Windows = 576;
1651 static constexpr int Apple = 552;
1652 static constexpr int Linux = 816;
1653 static constexpr int Default = Linux;
1654
1655 static constexpr size_t Alignment = 8;
1656
1657 using Object = Internal;
1658 };
1659
1660 using InternalOpaque = OpaqueObject<InternalDefinition>;
1661
1662 private:
1663 InternalOpaque internalOpaque;
1664 Internal& internal;
1665
1666 friend struct AsyncRequest;
1667 friend struct AsyncFileWrite;
1668 friend struct AsyncFileRead;
1669 friend struct AsyncFileSystemOperation;
1670 friend struct AsyncResult;
1671};
1672
1676struct SC_ASYNC_EXPORT AsyncEventLoopMonitor
1677{
1678 Function<void(void)> onNewEventsAvailable;
1679
1682 Result create(AsyncEventLoop& eventLoop);
1683
1685 Result close();
1686
1694
1700
1701 private:
1702#if SC_COMPILER_MSVC
1703#pragma warning(push)
1704#pragma warning(disable : 4324) // useless warning on 32 bit... (structure was padded due to __declspec(align()))
1705#endif
1706 alignas(uint64_t) uint8_t eventsMemory[8 * 1024]; // 8 Kb of kernel events
1707#if SC_COMPILER_MSVC
1708#pragma warning(pop)
1709#endif
1710
1711 AsyncKernelEvents asyncKernelEvents;
1712 AsyncEventLoop* eventLoop = nullptr;
1713 AsyncLoopWakeUp eventLoopWakeUp;
1714
1715 Thread eventLoopThread;
1716 EventObject eventObjectEnterBlockingMode;
1717 EventObject eventObjectExitBlockingMode;
1718
1719 Atomic<bool> finished = false;
1720 Atomic<bool> needsWakeUp = true;
1721
1722 bool wakeUpHasBeenCalled = false;
1723
1724 Result monitoringLoopThread(Thread& thread);
1725};
1726
1727} // namespace SC
Empty base struct for all AsyncRequest-derived CompletionData (internal) structs.
Definition Async.h:267
Allow library user to provide callbacks signaling different phases of async event loop cycle.
Definition Async.h:1435
Monitors Async I/O events from a background thread using a blocking kernel function (no CPU usage on ...
Definition Async.h:1677
Function< void(void)> onNewEventsAvailable
Informs to call dispatchCompletions on GUI Event Loop.
Definition Async.h:1678
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:1450
ApiType apiType
Criteria to choose Async IO API.
Definition Async.h:1457
ApiType
Definition Async.h:1452
Asynchronous I/O (files, sockets, timers, processes, fs events, threads wake-up) (see Async) AsyncEve...
Definition Async.h:1447
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 tryProbingIOUring()
Check if io_uring can be created directly (only on Linux)
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.
Result postExternalCompletion(AsyncExternalCompletion &async, size_t bytesTransferred=0)
Posts completion for an AsyncExternalCompletion started in manual mode.
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.
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.
Integrates externally-submitted completion based operations with AsyncEventLoop.
Definition Async.h:961
SC::Result clearSubmissionPending()
Clears a pending submission after an external submission failed synchronously.
SC::Result start(AsyncEventLoop &eventLoop)
Starts a manual external completion. The request remains active until postExternalCompletion() or sto...
SC::Result markSubmissionPending()
Marks that a native/manual external operation has been submitted and must complete before reuse.
Definition Async.h:790
Definition Async.h:796
Starts a file read operation, reading bytes from a file (or pipe).
Definition Async.h:786
FileDescriptor::Handle handle
The writeable span of memory where to data will be written.
Definition Async.h:814
Span< char > buffer
Callback called when some data has been read from the file into the buffer.
Definition Async.h:813
SC::Result closeHandle()
The file/pipe descriptor handle to read data from.
Definition Async.h:817
void setOffset(uint64_t fileOffset)
Sets the offset in bytes at which start reading.
Definition Async.h:824
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:820
Starts a file descriptor readiness operation.
Definition Async.h:939
SC::Result start(AsyncEventLoop &eventLoop, FileDescriptor::Handle fileDescriptor)
Starts a file descriptor poll operation, monitoring its readiness with appropriate OS API.
Definition Async.h:1034
Definition Async.h:1040
size_t getBytesTransferred() const
Get the number of bytes transferred.
Definition Async.h:1044
bool usedZeroCopy() const
Check if zero-copy was used for this transfer.
Definition Async.h:1047
bool isComplete() const
Check if the entire requested range was sent.
Definition Async.h:1050
Sends file contents to a socket using zero-copy when available (sendfile, TransmitFile).
Definition Async.h:1030
Function< void(Result &)> callback
Called when send completes or fails.
Definition Async.h:1070
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:1246
SC::Result stop(AsyncEventLoop &eventLoop, Function< void(AsyncResult &)> *afterStopped=nullptr)
Stops the operation, including the internal thread-pool work item when used.
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:1278
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:871
Starts a file write operation, writing bytes to a file (or pipe).
Definition Async.h:862
uint64_t getOffset() const
Returns the last offset set with AsyncFileWrite::setOffset.
Definition Async.h:907
FileDescriptor::Handle handle
The file/pipe descriptor to write data to.
Definition Async.h:897
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:911
Function< void(Result &)> callback
Callback called when descriptor is ready to be written with more data.
Definition Async.h:895
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:903
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:902
Allows user to supply a block of memory that will store kernel I/O events retrieved from AsyncEventLo...
Definition Async.h:1425
Span< uint8_t > eventsMemory
User supplied block of memory used to store kernel I/O events.
Definition Async.h:1426
Starts a Timeout that is invoked only once after expiration (relative) time has passed.
Definition Async.h:318
TimeMs getExpirationTime() const
Gets computed absolute expiration time that determines when this timeout get executed.
Definition Async.h:333
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:330
Function< void(Result &)> callback
Called after given expiration time since AsyncLoopTimeout::start has passed.
Definition Async.h:328
Options for AsyncLoopWakeUp configuration.
Definition Async.h:343
bool coalesce
Merge repeated pending wakeUp() calls into a single callback (default true, matching libuv uv_async_t...
Definition Async.h:346
Starts a wake-up operation, allowing threads to execute callbacks on loop thread.
Definition Async.h:366
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:385
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:1193
Function< void(Result &)> callback
Called to execute the work in a background threadpool thread.
Definition Async.h:1204
SC::Result setThreadPool(ThreadPool &threadPool)
Sets the ThreadPool that will supply the thread to run the async work on.
Definition Async.h:412
Starts monitoring a process, notifying about its termination.
Definition Async.h:403
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:428
Base class for all async requests, holding state and type.
Definition Async.h:130
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:171
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:200
Function< void(AsyncResult &)> * getCloseCallback()
Returns currently set close callback (if any) passed to AsyncRequest::stop.
Definition Async.h:203
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:191
void setUserFlags(uint16_t externalFlags)
Sets user flags, holding some meaningful data for the caller.
Definition Async.h:197
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:149
Helper holding CompletionData for a specific AsyncRequest-derived class.
Definition Async.h:303
Base class for all async results (argument of completion callbacks).
Definition Async.h:273
const SC::Result & isValid() const
Check if the returnCode of this result is valid.
Definition Async.h:284
AsyncResult(AsyncEventLoop &eventLoop, AsyncRequest &request, SC::Result &res, bool *hasBeenReactivated=nullptr)
Constructs an async result from a request and a result.
Definition Async.h:275
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:251
Options for AsyncSignal request configuration.
Definition Async.h:446
Mode
Mode of signal watching.
Definition Async.h:449
@ 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:453
bool coalesce
Merge repeated pending deliveries (default true)
Definition Async.h:454
Definition Async.h:469
Definition Async.h:475
Starts monitoring a signal, notifying about its reception.
Definition Async.h:465
Function< void(Result &)> callback
Called when the signal is raised.
Definition Async.h:483
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:562
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:582
Function< void(Result &)> callback
Called after socket is finally connected to endpoint.
Definition Async.h:592
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:751
Definition Async.h:704
SC::Result get(Span< char > &outData)
Get a Span of the actually read data.
Definition Async.h:712
Starts a socket receive operation, receiving bytes from a remote endpoint.
Definition Async.h:694
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:730
Span< char > buffer
The writeable span of memory where to data will be written.
Definition Async.h:727
Function< void(Result &)> callback
Called after data has been received.
Definition Async.h:725
Starts an unconnected socket send to operation, sending bytes to a remote endpoint.
Definition Async.h:662
Starts a socket send operation, sending bytes to a remote endpoint.
Definition Async.h:616
Function< void(Result &)> callback
Called when socket is ready to send more data.
Definition Async.h:631
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:638
Span< const char > buffer
Span of bytes to send (singleBuffer == true)
Definition Async.h:637
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:1174
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:243
[UniqueHandleDeclaration2Snippet]
Definition File.h:130
Options used to open a file descriptor.
Definition File.h:101
A structure to describe copy flags.
Definition FileSystem.h:76
Read / Write pipe (Process stdin/stdout and IPC communication)
Definition File.h:302
Low-level OS socket handle.
Definition Socket.h:167
AddressFamily
Sets the address family of an IP Address (IPv4 or IPV6)
Definition Socket.h:74
Native representation of an IP Address.
Definition Socket.h:114
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:127