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 FilePoll,
165 FileSystemOperation,
166 };
167
170 AsyncRequest(Type type) : state(State::Free), type(type), flags(0), unused(0), userFlags(0) {}
171
178 Result stop(AsyncEventLoop& eventLoop, Function<void(AsyncResult&)>* afterStopped = nullptr);
179
181 [[nodiscard]] bool isFree() const;
182
184 [[nodiscard]] bool isCancelling() const;
185
187 [[nodiscard]] bool isActive() const;
188
190 [[nodiscard]] Type getType() const { return type; }
191
193 Result start(AsyncEventLoop& eventLoop);
194
196 void setUserFlags(uint16_t externalFlags) { userFlags = externalFlags; }
197
199 uint16_t getUserFlags() const { return userFlags; }
200
202 [[nodiscard]] Function<void(AsyncResult&)>* getCloseCallback() { return closeCallback; }
203
204 [[nodiscard]] const Function<void(AsyncResult&)>* getCloseCallback() const { return closeCallback; }
205
206 protected:
207 Result checkState();
208
209 void queueSubmission(AsyncEventLoop& eventLoop);
210
211 AsyncSequence* sequence = nullptr;
212
213 AsyncTaskSequence* getTask();
214
215 private:
216 Function<void(AsyncResult&)>* closeCallback = nullptr;
217
218 friend struct AsyncEventLoop;
219 friend struct AsyncResult;
220
221 void markAsFree();
222
223 [[nodiscard]] static const char* TypeToString(Type type);
224 enum class State : uint8_t
225 {
226 Free, // not in any queue, this can be started with an async.start(...)
227 Setup, // when in submission queue waiting to be setup (after an async.start(...))
228 Submitting, // when in submission queue waiting to be activated or re-activated
229 Active, // when monitored by OS syscall or in activeLoopWakeUps / activeTimeouts queues
230 Reactivate, // when flagged for reactivation inside the callback (after a result.reactivateRequest(true))
231 Cancelling, // when in cancellation queue waiting for a cancelAsync (on active async)
232 };
233
234#if SC_ASYNC_ENABLE_LOG
235 const char* debugName = "None";
236#endif
237 State state; // 1 byte
238 Type type; // 1 byte
239 int16_t flags; // 2 bytes
240
241 uint16_t unused; // 2 bytes
242 uint16_t userFlags; // 2 bytes
243};
244
249struct SC_ASYNC_EXPORT AsyncSequence
250{
251 AsyncSequence* next = nullptr;
252 AsyncSequence* prev = nullptr;
253
254 bool clearSequenceOnCancel = true;
255 bool clearSequenceOnError = true;
256 private:
257 friend struct AsyncEventLoop;
258 bool runningAsync = false; // true if an async from this sequence is being run
259 bool tracked = false;
260
261 IntrusiveDoubleLinkedList<AsyncRequest> submissions;
262};
263
265struct SC_ASYNC_EXPORT AsyncCompletionData
266{
267};
268
271struct SC_ASYNC_EXPORT AsyncResult
272{
274 AsyncResult(AsyncEventLoop& eventLoop, AsyncRequest& request, SC::Result& res, bool* hasBeenReactivated = nullptr)
275 : eventLoop(eventLoop), async(request), hasBeenReactivated(hasBeenReactivated), returnCode(res)
276 {}
277
280 void reactivateRequest(bool shouldBeReactivated);
281
283 [[nodiscard]] const SC::Result& isValid() const { return returnCode; }
284
285 AsyncEventLoop& eventLoop;
286 AsyncRequest& async;
287
288 protected:
289 friend struct AsyncEventLoop;
290
291 bool shouldCallCallback = true;
292 bool* hasBeenReactivated = nullptr;
293
294 SC::Result& returnCode;
295};
296
300template <typename T, typename C>
302{
303 T& getAsync() { return static_cast<T&>(AsyncResult::async); }
304 const T& getAsync() const { return static_cast<const T&>(AsyncResult::async); }
305
307
308 C completionData;
309 int32_t eventIndex = 0;
310};
311
316struct SC_ASYNC_EXPORT AsyncLoopTimeout : public AsyncRequest
317{
318 AsyncLoopTimeout() : AsyncRequest(Type::LoopTimeout) {}
319
322 using AsyncRequest::start;
323
325 SC::Result start(AsyncEventLoop& eventLoop, TimeMs relativeTimeout);
326
327 Function<void(Result&)> callback;
328
330
332 TimeMs getExpirationTime() const { return expirationTime; }
333
334 private:
335 SC::Result validate(AsyncEventLoop&);
336 friend struct AsyncEventLoop;
337 TimeMs expirationTime;
338};
339
342{
345 bool coalesce = true;
346};
347
364struct SC_ASYNC_EXPORT AsyncLoopWakeUp : public AsyncRequest
365{
366 AsyncLoopWakeUp() : AsyncRequest(Type::LoopWakeUp) {}
367
369 {
370 uint32_t deliveryCount = 1;
371 };
372
374
376 SC::Result start(AsyncEventLoop& eventLoop, AsyncLoopWakeUpOptions options = {});
377
379 SC::Result start(AsyncEventLoop& eventLoop, EventObject& eventObject, AsyncLoopWakeUpOptions options = {});
380
382 SC::Result wakeUp(AsyncEventLoop& eventLoop);
383
384 Function<void(Result&)> callback;
385 EventObject* eventObject = nullptr;
386
387 private:
388 friend struct AsyncEventLoop;
389 SC::Result validate(AsyncEventLoop&);
390 int32_t consumePendingWakeUps();
391 int32_t getPendingWakeUps() const;
392
393 AsyncLoopWakeUpOptions wakeUpOptions;
394 Atomic<int32_t> pendingWakeUps = 0;
395};
396
401struct SC_ASYNC_EXPORT AsyncProcessExit : public AsyncRequest
402{
403 AsyncProcessExit() : AsyncRequest(Type::ProcessExit) {}
404
406 {
407 int exitStatus;
408 };
409
410 struct Result : public AsyncResultOf<AsyncProcessExit, CompletionData>
411 {
412 using AsyncResultOf<AsyncProcessExit, CompletionData>::AsyncResultOf;
413
414 SC::Result get(int& status)
415 {
416 status = completionData.exitStatus;
417 return returnCode;
418 }
419 };
420 using AsyncRequest::start;
421
425 SC::Result start(AsyncEventLoop& eventLoop, FileDescriptor::Handle process);
426
427 Function<void(Result&)> callback;
428
429 private:
430 friend struct AsyncEventLoop;
431 SC::Result validate(AsyncEventLoop&);
432
433 FileDescriptor::Handle handle = FileDescriptor::Invalid;
434#if SC_PLATFORM_WINDOWS
435 detail::WinOverlappedOpaque overlapped;
436 detail::WinWaitHandle waitHandle;
437 AsyncEventLoop* eventLoop = nullptr;
438#elif SC_PLATFORM_LINUX
439 FileDescriptor pidFd;
440#endif
441};
442
445{
447 enum class Mode : uint8_t
448 {
449 Persistent,
450 OneShot
451 };
453 bool coalesce = true;
454};
455
463struct SC_ASYNC_EXPORT AsyncSignal : public AsyncRequest
464{
465 AsyncSignal() : AsyncRequest(Type::Signal) {}
466
468 {
469 int signalNumber = 0;
470 uint32_t deliveryCount = 1;
471 };
472
473 struct Result : public AsyncResultOf<AsyncSignal, CompletionData>
474 {
475 using AsyncResultOf<AsyncSignal, CompletionData>::AsyncResultOf;
476 };
477 using AsyncRequest::start;
478
480 SC::Result start(AsyncEventLoop& eventLoop, int num, AsyncSignalOptions options = {});
481
482 Function<void(Result&)> callback;
483
484 private:
485 friend struct AsyncEventLoop;
486 SC::Result validate(AsyncEventLoop&);
487
488 int signalNumber = 0;
489 AsyncSignalOptions signalOptions;
490#if SC_PLATFORM_WINDOWS
491 detail::WinOverlappedOpaque overlapped;
492 AsyncEventLoop* eventLoop = nullptr;
493#elif SC_PLATFORM_LINUX
494 FileDescriptor signalFd;
495 FileDescriptor::Handle signalFdHandle = FileDescriptor::Invalid;
496#endif
497};
498
499struct AsyncSocketAccept;
500namespace detail
501{
504struct SC_ASYNC_EXPORT AsyncSocketAcceptData
505{
506#if SC_PLATFORM_WINDOWS
507 void (*pAcceptEx)() = nullptr;
508 detail::WinOverlappedOpaque overlapped;
509 SocketDescriptor clientSocket;
510 uint8_t acceptBuffer[288] = {0};
511#elif SC_PLATFORM_LINUX
512 AlignedStorage<28> sockAddrHandle;
513 uint32_t sockAddrLen;
514#endif
515};
516
518struct SC_ASYNC_EXPORT AsyncSocketAcceptBase : public AsyncRequest
519{
520 AsyncSocketAcceptBase() : AsyncRequest(Type::SocketAccept) {}
521
522 struct CompletionData : public AsyncCompletionData
523 {
524 SocketDescriptor acceptedClient;
525 };
526
527 struct Result : public AsyncResultOf<AsyncSocketAccept, CompletionData>
528 {
529 using AsyncResultOf<AsyncSocketAccept, CompletionData>::AsyncResultOf;
530
531 SC::Result moveTo(SocketDescriptor& client)
532 {
533 SC_TRY(returnCode);
534 return SC::Result(client.assign(move(completionData.acceptedClient)));
535 }
536 };
537 using AsyncRequest::start;
538
540 SC::Result start(AsyncEventLoop& eventLoop, const SocketDescriptor& socketDescriptor, AsyncSocketAcceptData& data);
541 SC::Result validate(AsyncEventLoop&);
542
543 Function<void(Result&)> callback;
544 SocketDescriptor::Handle handle = SocketDescriptor::Invalid;
545 SocketFlags::AddressFamily addressFamily = SocketFlags::AddressFamilyIPV4;
546 AsyncSocketAcceptData* acceptData = nullptr;
547};
548
549} // namespace detail
550
560struct SC_ASYNC_EXPORT AsyncSocketAccept : public detail::AsyncSocketAcceptBase
561{
562 AsyncSocketAccept() { AsyncSocketAcceptBase::acceptData = &data; }
563 using AsyncSocketAcceptBase::start;
564
566 SC::Result start(AsyncEventLoop& eventLoop, const SocketDescriptor& socketDescriptor);
567
568 private:
569 detail::AsyncSocketAcceptData data;
570};
571
580struct SC_ASYNC_EXPORT AsyncSocketConnect : public AsyncRequest
581{
582 AsyncSocketConnect() : AsyncRequest(Type::SocketConnect) {}
583
586 using AsyncRequest::start;
587
589 SC::Result start(AsyncEventLoop& eventLoop, const SocketDescriptor& descriptor, SocketIPAddress address);
590
591 Function<void(Result&)> callback;
592
593 SocketDescriptor::Handle handle = SocketDescriptor::Invalid;
594 SocketIPAddress ipAddress;
595
596 private:
597 friend struct AsyncEventLoop;
598 SC::Result validate(AsyncEventLoop&);
599
600#if SC_PLATFORM_WINDOWS
601 void (*pConnectEx)() = nullptr;
602 detail::WinOverlappedOpaque overlapped;
603#endif
604};
605
614struct SC_ASYNC_EXPORT AsyncSocketSend : public AsyncRequest
615{
616 AsyncSocketSend() : AsyncRequest(Type::SocketSend) {}
618 {
619 size_t numBytes = 0;
620 };
622 using AsyncRequest::start;
623
625 SC::Result start(AsyncEventLoop& eventLoop, const SocketDescriptor& descriptor, Span<const char> data);
626
628 SC::Result start(AsyncEventLoop& eventLoop, const SocketDescriptor& descriptor, Span<Span<const char>> data);
629
630 Function<void(Result&)> callback;
631
632 SocketDescriptor::Handle handle = SocketDescriptor::Invalid;
633
634 SC::Result closeHandle() { return detail::SocketDescriptorDefinition::releaseHandle(handle); }
635
636 Span<const char> buffer;
637 Span<Span<const char>> buffers;
638 bool singleBuffer = true;
639
640 protected:
641 AsyncSocketSend(Type type) : AsyncRequest(type) {}
642 friend struct AsyncEventLoop;
643 SC::Result validate(AsyncEventLoop&);
644
645 size_t totalBytesWritten = 0;
646#if SC_PLATFORM_WINDOWS
647 detail::WinOverlappedOpaque overlapped;
648#endif
649};
650
660struct SC_ASYNC_EXPORT AsyncSocketSendTo : public AsyncSocketSend
661{
662 AsyncSocketSendTo() : AsyncSocketSend(Type::SocketSendTo) {}
663
664 SocketIPAddress address;
665
666 SC::Result start(AsyncEventLoop& eventLoop, const SocketDescriptor& descriptor, SocketIPAddress ipAddress,
667 Span<const char> data);
668
669 SC::Result start(AsyncEventLoop& eventLoop, const SocketDescriptor& descriptor, SocketIPAddress ipAddress,
670 Span<Span<const char>> data);
671
672 private:
673 using AsyncSocketSend::start;
674 friend struct AsyncEventLoop;
675 SC::Result validate(AsyncEventLoop&);
676#if SC_PLATFORM_LINUX
677 AlignedStorage<56> typeErasedMsgHdr;
678#endif
679};
680
692struct SC_ASYNC_EXPORT AsyncSocketReceive : public AsyncRequest
693{
694 AsyncSocketReceive() : AsyncRequest(Type::SocketReceive) {}
695
697 {
698 size_t numBytes = 0;
699 bool disconnected = false;
700 };
701
702 struct Result : public AsyncResultOf<AsyncSocketReceive, CompletionData>
703 {
704 using AsyncResultOf<AsyncSocketReceive, CompletionData>::AsyncResultOf;
705
706 bool isEnded() const { return completionData.disconnected; }
707
711 SC::Result get(Span<char>& outData)
712 {
713 SC_TRY(getAsync().buffer.sliceStartLength(0, completionData.numBytes, outData));
714 return returnCode;
715 }
716
717 SocketIPAddress getSourceAddress() const;
718 };
719 using AsyncRequest::start;
720
722 SC::Result start(AsyncEventLoop& eventLoop, const SocketDescriptor& descriptor, Span<char> data);
723
724 Function<void(Result&)> callback;
725
726 Span<char> buffer;
727 SocketDescriptor::Handle handle = SocketDescriptor::Invalid;
728
729 SC::Result closeHandle() { return detail::SocketDescriptorDefinition::releaseHandle(handle); }
730
731 protected:
732 AsyncSocketReceive(Type type) : AsyncRequest(type) {}
733 friend struct AsyncEventLoop;
734 SC::Result validate(AsyncEventLoop&);
735#if SC_PLATFORM_WINDOWS
736 detail::WinOverlappedOpaque overlapped;
737#endif
738};
739
749struct SC_ASYNC_EXPORT AsyncSocketReceiveFrom : public AsyncSocketReceive
750{
751 AsyncSocketReceiveFrom() : AsyncSocketReceive(Type::SocketReceiveFrom) {}
752 using AsyncSocketReceive::start;
753
754 private:
755 SocketIPAddress address;
756 friend struct AsyncSocketReceive;
757 friend struct AsyncEventLoop;
758#if SC_PLATFORM_LINUX
759 AlignedStorage<56> typeErasedMsgHdr;
760#endif
761};
762
784struct SC_ASYNC_EXPORT AsyncFileRead : public AsyncRequest
785{
786 AsyncFileRead() : AsyncRequest(Type::FileRead) { handle = FileDescriptor::Invalid; }
787
789 {
790 size_t numBytes = 0;
791 bool endOfFile = false;
792 };
793
794 struct Result : public AsyncResultOf<AsyncFileRead, CompletionData>
795 {
796 using AsyncResultOf<AsyncFileRead, CompletionData>::AsyncResultOf;
797
798 bool isEnded() const { return completionData.endOfFile; }
799
800 SC::Result get(Span<char>& data)
801 {
802 SC_TRY(getAsync().buffer.sliceStartLength(0, completionData.numBytes, data));
803 return returnCode;
804 }
805 };
806 using AsyncRequest::start;
807
809 SC::Result start(AsyncEventLoop& eventLoop, const FileDescriptor& descriptor, Span<char> data);
810
811 Function<void(Result&)> callback;
812 Span<char> buffer;
813 FileDescriptor::Handle handle;
815
816 SC::Result closeHandle() { return detail::FileDescriptorDefinition::releaseHandle(handle); }
817
819 uint64_t getOffset() const { return offset; }
820
823 void setOffset(uint64_t fileOffset)
824 {
825 useOffset = true;
826 offset = fileOffset;
827 }
828
829 private:
830 friend struct AsyncEventLoop;
831 SC::Result validate(AsyncEventLoop&);
832
833 bool useOffset = false;
834 bool endedSync = false;
835
836 uint64_t offset = 0;
837#if SC_PLATFORM_WINDOWS
838 uint64_t readCursor = 0;
839 detail::WinOverlappedOpaque overlapped;
840#endif
841};
842
860struct SC_ASYNC_EXPORT AsyncFileWrite : public AsyncRequest
861{
862 AsyncFileWrite() : AsyncRequest(Type::FileWrite) { handle = FileDescriptor::Invalid; }
863
865 {
866 size_t numBytes = 0;
867 };
868
869 struct Result : public AsyncResultOf<AsyncFileWrite, CompletionData>
870 {
871 using AsyncResultOf<AsyncFileWrite, CompletionData>::AsyncResultOf;
872
873 SC::Result get(size_t& writtenSizeInBytes)
874 {
875 writtenSizeInBytes = completionData.numBytes;
876 return returnCode;
877 }
878 };
879
880 using AsyncRequest::start;
881
883 SC::Result start(AsyncEventLoop& eventLoop, const FileDescriptor& descriptor, Span<Span<const char>> data);
884
886 SC::Result start(AsyncEventLoop& eventLoop, Span<Span<const char>> data);
887
889 SC::Result start(AsyncEventLoop& eventLoop, const FileDescriptor& descriptor, Span<const char> data);
890
892 SC::Result start(AsyncEventLoop& eventLoop, Span<const char> data);
893
894 Function<void(Result&)> callback;
895
896 FileDescriptor::Handle handle;
898
899 SC::Result closeHandle() { return detail::FileDescriptorDefinition::releaseHandle(handle); }
900
901 Span<const char> buffer;
902 Span<Span<const char>> buffers;
903 bool singleBuffer = true;
904
906 uint64_t getOffset() const { return offset; }
907
910 void setOffset(uint64_t fileOffset)
911 {
912 useOffset = true;
913 offset = fileOffset;
914 }
915
916 private:
917 friend struct AsyncEventLoop;
918 SC::Result validate(AsyncEventLoop&);
919
920#if SC_PLATFORM_WINDOWS
921 bool endedSync = false;
922#else
923 bool isWatchable = false;
924#endif
925 bool useOffset = false;
926 uint64_t offset = 0xffffffffffffffff;
927
928 size_t totalBytesWritten = 0;
929#if SC_PLATFORM_WINDOWS
930 detail::WinOverlappedOpaque overlapped;
931#endif
932};
933
938struct SC_ASYNC_EXPORT AsyncFilePoll : public AsyncRequest
939{
940 AsyncFilePoll() : AsyncRequest(Type::FilePoll) {}
941
944
946 SC::Result start(AsyncEventLoop& eventLoop, FileDescriptor::Handle fileDescriptor);
947
948#if SC_PLATFORM_WINDOWS
949 [[nodiscard]] void* getOverlappedPtr();
950#endif
951
952 Function<void(Result&)> callback;
953
954 private:
955 friend struct AsyncEventLoop;
956 SC::Result validate(AsyncEventLoop&);
957
958 FileDescriptor::Handle handle = FileDescriptor::Invalid;
959#if SC_PLATFORM_WINDOWS
960 detail::WinOverlappedOpaque overlapped;
961#endif
962};
963
988struct SC_ASYNC_EXPORT AsyncFileSend : public AsyncRequest
989{
990 AsyncFileSend() : AsyncRequest(Type::FileSend) {}
991
993 {
994 size_t bytesTransferred = 0;
995 bool usedZeroCopy = false;
996 };
997
998 struct Result : public AsyncResultOf<AsyncFileSend, CompletionData>
999 {
1000 using AsyncResultOf<AsyncFileSend, CompletionData>::AsyncResultOf;
1001
1003 [[nodiscard]] size_t getBytesTransferred() const { return completionData.bytesTransferred; }
1004
1006 [[nodiscard]] bool usedZeroCopy() const { return completionData.usedZeroCopy; }
1007
1009 [[nodiscard]] bool isComplete() const
1010 {
1011 return returnCode && completionData.bytesTransferred == getAsync().length;
1012 }
1013 };
1014
1015 using AsyncRequest::start;
1016
1026 SC::Result start(AsyncEventLoop& eventLoop, const FileDescriptor& file, const SocketDescriptor& socket,
1027 int64_t offset = 0, size_t length = 0, size_t pipeSize = 0);
1028
1029 Function<void(Result&)> callback;
1030
1031 // Internal handles (set by start())
1032 FileDescriptor::Handle fileHandle = FileDescriptor::Invalid;
1033 SocketDescriptor::Handle socketHandle = SocketDescriptor::Invalid;
1034
1035 int64_t offset = 0;
1036 size_t length = 0;
1037 size_t bytesSent = 0;
1038 private:
1039 friend struct AsyncEventLoop;
1040 SC::Result validate(AsyncEventLoop&);
1041
1042#if SC_PLATFORM_WINDOWS
1043 detail::WinOverlappedOpaque overlapped;
1044#elif SC_PLATFORM_LINUX
1045 size_t pipeBufferSize = 0;
1046 PipeDescriptor splicePipe;
1047#endif
1048};
1049
1050// forward declared because it must be defined after AsyncTaskSequence
1051struct AsyncLoopWork;
1053
1055{
1056 FileDescriptor::Handle handle = FileDescriptor::Invalid; // for open
1057
1058 int code = 0; // for open/close
1059 size_t numBytes = 0; // for read
1060};
1061
1062namespace detail
1063{
1064// A simple hand-made variant of all completion types
1065struct SC_ASYNC_EXPORT AsyncCompletionVariant
1066{
1067 AsyncCompletionVariant() {}
1068 ~AsyncCompletionVariant() { destroy(); }
1069
1070 AsyncCompletionVariant(const AsyncCompletionVariant&) = delete;
1071 AsyncCompletionVariant(AsyncCompletionVariant&&) = delete;
1072 AsyncCompletionVariant& operator=(const AsyncCompletionVariant&) = delete;
1073 AsyncCompletionVariant& operator=(AsyncCompletionVariant&&) = delete;
1074
1075 bool inited = false;
1076
1077 AsyncRequest::Type type;
1078 union
1079 {
1080 AsyncCompletionData completionDataLoopWork; // Defined after AsyncCompletionVariant / AsyncTaskSequence
1081 AsyncLoopTimeout::CompletionData completionDataLoopTimeout;
1082 AsyncLoopWakeUp::CompletionData completionDataLoopWakeUp;
1083 AsyncProcessExit::CompletionData completionDataProcessExit;
1084 AsyncSignal::CompletionData completionDataSignal;
1085 AsyncSocketAccept::CompletionData completionDataSocketAccept;
1086 AsyncSocketConnect::CompletionData completionDataSocketConnect;
1087 AsyncSocketSend::CompletionData completionDataSocketSend;
1088 AsyncSocketSendTo::CompletionData completionDataSocketSendTo;
1089 AsyncSocketReceive::CompletionData completionDataSocketReceive;
1090 AsyncSocketReceiveFrom::CompletionData completionDataSocketReceiveFrom;
1091 AsyncFileRead::CompletionData completionDataFileRead;
1092 AsyncFileWrite::CompletionData completionDataFileWrite;
1093 AsyncFileSend::CompletionData completionDataFileSend;
1094 AsyncFilePoll::CompletionData completionDataFilePoll;
1095
1096 AsyncFileSystemOperationCompletionData completionDataFileSystemOperation;
1097 };
1098
1099 auto& getCompletion(AsyncLoopWork&) { return completionDataLoopWork; }
1100 auto& getCompletion(AsyncLoopTimeout&) { return completionDataLoopTimeout; }
1101 auto& getCompletion(AsyncLoopWakeUp&) { return completionDataLoopWakeUp; }
1102 auto& getCompletion(AsyncProcessExit&) { return completionDataProcessExit; }
1103 auto& getCompletion(AsyncSignal&) { return completionDataSignal; }
1104 auto& getCompletion(AsyncSocketAccept&) { return completionDataSocketAccept; }
1105 auto& getCompletion(AsyncSocketConnect&) { return completionDataSocketConnect; }
1106 auto& getCompletion(AsyncSocketSend&) { return completionDataSocketSend; }
1107 auto& getCompletion(AsyncSocketReceive&) { return completionDataSocketReceive; }
1108 auto& getCompletion(AsyncFileRead&) { return completionDataFileRead; }
1109 auto& getCompletion(AsyncFileWrite&) { return completionDataFileWrite; }
1110 auto& getCompletion(AsyncFileSend&) { return completionDataFileSend; }
1111 auto& getCompletion(AsyncFilePoll&) { return completionDataFilePoll; }
1112 auto& getCompletion(AsyncFileSystemOperation&) { return completionDataFileSystemOperation; }
1113
1114 template <typename T>
1115 auto& construct(T& t)
1116 {
1117 destroy();
1118 placementNew(getCompletion(t));
1119 inited = true;
1120 type = t.getType();
1121 return getCompletion(t);
1122 }
1123 void destroy();
1124};
1125} // namespace detail
1126
1130struct SC_ASYNC_EXPORT AsyncTaskSequence : public AsyncSequence
1131{
1132 protected:
1133 ThreadPoolTask task;
1134 ThreadPool* threadPool = nullptr;
1135
1136 friend struct AsyncEventLoop;
1137 friend struct AsyncRequest;
1138
1139 detail::AsyncCompletionVariant completion;
1140
1141 SC::Result returnCode = SC::Result(true);
1142};
1143
1149struct SC_ASYNC_EXPORT AsyncLoopWork : public AsyncRequest
1150{
1151 AsyncLoopWork() : AsyncRequest(Type::LoopWork) {}
1152
1155
1158 SC::Result setThreadPool(ThreadPool& threadPool);
1159
1160 Function<SC::Result()> work;
1161 Function<void(Result&)> callback;
1162
1163 private:
1164 friend struct AsyncEventLoop;
1165 SC::Result validate(AsyncEventLoop&);
1166 AsyncTaskSequence task;
1167};
1168
1202struct SC_ASYNC_EXPORT AsyncFileSystemOperation : public AsyncRequest
1203{
1204 AsyncFileSystemOperation() : AsyncRequest(Type::FileSystemOperation) {}
1205 ~AsyncFileSystemOperation() { destroy(); }
1206#ifdef CopyFile
1207#undef CopyFile
1208#endif
1209#ifdef RemoveDirectory
1210#undef RemoveDirectory
1211#endif
1212 enum class Operation
1213 {
1214 None = 0,
1215 Open,
1216 Close,
1217 Read,
1218 Write,
1219 CopyFile,
1220 CopyDirectory,
1221 Rename,
1222 RemoveDirectory,
1223 RemoveFile,
1224 };
1225
1228
1230 SC::Result setThreadPool(ThreadPool& threadPool);
1231
1233 SC::Result stop(AsyncEventLoop& eventLoop, Function<void(AsyncResult&)>* afterStopped = nullptr);
1234
1235 Function<void(Result&)> callback;
1236
1242 SC::Result open(AsyncEventLoop& eventLoop, StringSpan path, FileOpen mode);
1243
1248 SC::Result close(AsyncEventLoop& eventLoop, FileDescriptor::Handle handle);
1249
1256 SC::Result read(AsyncEventLoop& eventLoop, FileDescriptor::Handle handle, Span<char> buffer, uint64_t offset);
1257
1264 SC::Result write(AsyncEventLoop& eventLoop, FileDescriptor::Handle handle, Span<const char> buffer,
1265 uint64_t offset);
1266
1273 SC::Result copyFile(AsyncEventLoop& eventLoop, StringSpan path, StringSpan destinationPath,
1275
1282 SC::Result copyDirectory(AsyncEventLoop& eventLoop, StringSpan path, StringSpan destinationPath,
1284
1290 SC::Result rename(AsyncEventLoop& eventLoop, StringSpan path, StringSpan newPath);
1291
1297 SC::Result removeEmptyDirectory(AsyncEventLoop& eventLoop, StringSpan path);
1298
1303 SC::Result removeFile(AsyncEventLoop& eventLoop, StringSpan path);
1304
1305 private:
1306 friend struct AsyncEventLoop;
1307 Operation operation = Operation::None;
1308 AsyncLoopWork loopWork;
1309 CompletionData completionData;
1310
1311 void onOperationCompleted(AsyncLoopWork::Result& res);
1312
1313 struct FileDescriptorData
1314 {
1315 FileDescriptor::Handle handle;
1316 };
1317
1318 struct OpenData
1319 {
1320 StringSpan path;
1321 FileOpen mode;
1322 };
1323
1324 struct ReadData
1325 {
1326 FileDescriptor::Handle handle;
1327 Span<char> buffer;
1328 uint64_t offset;
1329 };
1330
1331 struct WriteData
1332 {
1333 FileDescriptor::Handle handle;
1334 Span<const char> buffer;
1335 uint64_t offset;
1336 };
1337
1338 struct CopyFileData
1339 {
1340 StringSpan path;
1341 StringSpan destinationPath;
1342 FileSystemCopyFlags copyFlags;
1343 };
1344
1345 using CopyDirectoryData = CopyFileData;
1346
1347 using CloseData = FileDescriptorData;
1348
1349 struct RenameData
1350 {
1351 StringSpan path;
1352 StringSpan newPath;
1353 };
1354
1355 struct RemoveData
1356 {
1357 StringSpan path;
1358 };
1359
1360 union
1361 {
1362 OpenData openData;
1363 CloseData closeData;
1364 ReadData readData;
1365 WriteData writeData;
1366 CopyFileData copyFileData;
1367 CopyDirectoryData copyDirectoryData;
1368 RenameData renameData;
1369 RemoveData removeData;
1370 };
1371
1372 void destroy();
1373
1374 SC::Result start(AsyncEventLoop& eventLoop, FileDescriptor::Handle fileDescriptor);
1375 SC::Result validate(AsyncEventLoop&);
1376};
1377
1381struct SC_ASYNC_EXPORT AsyncKernelEvents
1382{
1383 Span<uint8_t> eventsMemory;
1384
1385 private:
1386 int numberOfEvents = 0;
1387 friend struct AsyncEventLoop;
1388};
1389
1391struct SC_ASYNC_EXPORT AsyncEventLoopListeners
1392{
1393 Function<void(AsyncEventLoop&)> beforeBlockingPoll;
1394 Function<void(AsyncEventLoop&)> afterBlockingPoll;
1395};
1396
1403struct SC_ASYNC_EXPORT AsyncEventLoop
1404{
1406 struct Options
1407 {
1408 enum class ApiType : uint8_t
1409 {
1410 Automatic = 0,
1411 ForceUseIoUring,
1412 ForceUseEpoll,
1413 };
1415
1416 Options() { apiType = ApiType::Automatic; }
1417 };
1418
1420
1421 AsyncEventLoop(const AsyncEventLoop&) = delete;
1422 AsyncEventLoop(AsyncEventLoop&&) = delete;
1423 AsyncEventLoop& operator=(AsyncEventLoop&&) = delete;
1424 AsyncEventLoop& operator=(const AsyncEventLoop&) = delete;
1425
1427 Result create(Options options = Options());
1428
1430 Result close();
1431
1434 Result start(AsyncRequest& async);
1435
1438
1440 [[nodiscard]] bool isInitialized() const;
1441
1443 [[nodiscard]] bool needsThreadPoolForFileOperations() const;
1444
1450 Result run();
1451
1461 Result runOnce();
1462
1468 Result runNoWait();
1469
1474 Result submitRequests(AsyncKernelEvents& kernelEvents);
1475
1494 Result blockingPoll(AsyncKernelEvents& kernelEvents);
1495
1502
1506
1509
1512
1515
1518
1520 Result associateExternallyCreatedSocketHandle(SocketDescriptor::Handle handle);
1521
1524
1526 Result associateExternallyCreatedFileDescriptorHandle(FileDescriptor::Handle handle);
1527
1529 static Result removeAllAssociationsFor(SocketDescriptor& outDescriptor);
1530
1532 static Result removeAllAssociationsForSocketHandle(SocketDescriptor::Handle handle);
1533
1535 static Result removeAllAssociationsFor(FileDescriptor& outDescriptor);
1536
1538 static Result removeAllAssociationsForFileDescriptorHandle(FileDescriptor::Handle handle);
1539
1542
1544 [[nodiscard]] TimeMs getLoopTime() const;
1545
1547 [[nodiscard]] int getNumberOfActiveRequests() const;
1548
1550 [[nodiscard]] int getNumberOfSubmittedRequests() const;
1551
1555
1558
1561
1563 void enumerateRequests(Function<void(AsyncRequest&)> enumerationCallback);
1564
1568
1570 [[nodiscard]] static bool isExcludedFromActiveCount(const AsyncRequest& async);
1571
1574 [[nodiscard]] static bool tryProbingIOUring();
1575
1578
1579 struct Internal;
1580
1582 using LoopWork = AsyncLoopWork;
1585 using Signal = AsyncSignal;
1592 using FileRead = AsyncFileRead;
1593 using FileWrite = AsyncFileWrite;
1594 using FileSend = AsyncFileSend;
1595 using FilePoll = AsyncFilePoll;
1598 using ResultType = AsyncResult;
1599
1600 public:
1601 struct SC_ASYNC_EXPORT InternalDefinition
1602 {
1603 static constexpr int Windows = 552;
1604 static constexpr int Apple = 520;
1605 static constexpr int Linux = 784;
1606 static constexpr int Default = Linux;
1607
1608 static constexpr size_t Alignment = 8;
1609
1610 using Object = Internal;
1611 };
1612
1613 using InternalOpaque = OpaqueObject<InternalDefinition>;
1614
1615 private:
1616 InternalOpaque internalOpaque;
1617 Internal& internal;
1618
1619 friend struct AsyncRequest;
1620 friend struct AsyncFileWrite;
1621 friend struct AsyncFileRead;
1622 friend struct AsyncFileSystemOperation;
1623 friend struct AsyncResult;
1624};
1625
1629struct SC_ASYNC_EXPORT AsyncEventLoopMonitor
1630{
1631 Function<void(void)> onNewEventsAvailable;
1632
1635 Result create(AsyncEventLoop& eventLoop);
1636
1638 Result close();
1639
1647
1653
1654 private:
1655#if SC_COMPILER_MSVC
1656#pragma warning(push)
1657#pragma warning(disable : 4324) // useless warning on 32 bit... (structure was padded due to __declspec(align()))
1658#endif
1659 alignas(uint64_t) uint8_t eventsMemory[8 * 1024]; // 8 Kb of kernel events
1660#if SC_COMPILER_MSVC
1661#pragma warning(pop)
1662#endif
1663
1664 AsyncKernelEvents asyncKernelEvents;
1665 AsyncEventLoop* eventLoop = nullptr;
1666 AsyncLoopWakeUp eventLoopWakeUp;
1667
1668 Thread eventLoopThread;
1669 EventObject eventObjectEnterBlockingMode;
1670 EventObject eventObjectExitBlockingMode;
1671
1672 Atomic<bool> finished = false;
1673 Atomic<bool> needsWakeUp = true;
1674
1675 bool wakeUpHasBeenCalled = false;
1676
1677 Result monitoringLoopThread(Thread& thread);
1678};
1679
1680} // namespace SC
Empty base struct for all AsyncRequest-derived CompletionData (internal) structs.
Definition Async.h:266
Allow library user to provide callbacks signaling different phases of async event loop cycle.
Definition Async.h:1392
Monitors Async I/O events from a background thread using a blocking kernel function (no CPU usage on ...
Definition Async.h:1630
Function< void(void)> onNewEventsAvailable
Informs to call dispatchCompletions on GUI Event Loop.
Definition Async.h:1631
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:1407
ApiType apiType
Criteria to choose Async IO API.
Definition Async.h:1414
ApiType
Definition Async.h:1409
Asynchronous I/O (files, sockets, timers, processes, fs events, threads wake-up) (see Async) AsyncEve...
Definition Async.h:1404
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.
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.
Starts an handle polling 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:789
Definition Async.h:795
Starts a file read operation, reading bytes from a file (or pipe).
Definition Async.h:785
FileDescriptor::Handle handle
The writeable span of memory where to data will be written.
Definition Async.h:813
Span< char > buffer
Callback called when some data has been read from the file into the buffer.
Definition Async.h:812
SC::Result closeHandle()
The file/pipe descriptor handle to read data from.
Definition Async.h:816
void setOffset(uint64_t fileOffset)
Sets the offset in bytes at which start reading.
Definition Async.h:823
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:819
Definition Async.h:993
Definition Async.h:999
size_t getBytesTransferred() const
Get the number of bytes transferred.
Definition Async.h:1003
bool usedZeroCopy() const
Check if zero-copy was used for this transfer.
Definition Async.h:1006
bool isComplete() const
Check if the entire requested range was sent.
Definition Async.h:1009
Sends file contents to a socket using zero-copy when available (sendfile, TransmitFile).
Definition Async.h:989
Function< void(Result &)> callback
Called when send completes or fails.
Definition Async.h:1029
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:1203
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:1235
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:870
Starts a file write operation, writing bytes to a file (or pipe).
Definition Async.h:861
uint64_t getOffset() const
Returns the last offset set with AsyncFileWrite::setOffset.
Definition Async.h:906
FileDescriptor::Handle handle
The file/pipe descriptor to write data to.
Definition Async.h:896
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:910
Function< void(Result &)> callback
Callback called when descriptor is ready to be written with more data.
Definition Async.h:894
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:902
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:901
Allows user to supply a block of memory that will store kernel I/O events retrieved from AsyncEventLo...
Definition Async.h:1382
Span< uint8_t > eventsMemory
User supplied block of memory used to store kernel I/O events.
Definition Async.h:1383
Starts a Timeout that is invoked only once after expiration (relative) time has passed.
Definition Async.h:317
TimeMs getExpirationTime() const
Gets computed absolute expiration time that determines when this timeout get executed.
Definition Async.h:332
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:329
Function< void(Result &)> callback
Called after given expiration time since AsyncLoopTimeout::start has passed.
Definition Async.h:327
Options for AsyncLoopWakeUp configuration.
Definition Async.h:342
bool coalesce
Merge repeated pending wakeUp() calls into a single callback (default true, matching libuv uv_async_t...
Definition Async.h:345
Starts a wake-up operation, allowing threads to execute callbacks on loop thread.
Definition Async.h:365
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:384
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:1150
Function< void(Result &)> callback
Called to execute the work in a background threadpool thread.
Definition Async.h:1161
SC::Result setThreadPool(ThreadPool &threadPool)
Sets the ThreadPool that will supply the thread to run the async work on.
Definition Async.h:411
Starts monitoring a process, notifying about its termination.
Definition Async.h:402
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:427
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:170
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:199
Function< void(AsyncResult &)> * getCloseCallback()
Returns currently set close callback (if any) passed to AsyncRequest::stop.
Definition Async.h:202
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:190
void setUserFlags(uint16_t externalFlags)
Sets user flags, holding some meaningful data for the caller.
Definition Async.h:196
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:302
Base class for all async results (argument of completion callbacks).
Definition Async.h:272
const SC::Result & isValid() const
Check if the returnCode of this result is valid.
Definition Async.h:283
AsyncResult(AsyncEventLoop &eventLoop, AsyncRequest &request, SC::Result &res, bool *hasBeenReactivated=nullptr)
Constructs an async result from a request and a result.
Definition Async.h:274
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:250
Options for AsyncSignal request configuration.
Definition Async.h:445
Mode
Mode of signal watching.
Definition Async.h:448
@ 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:452
bool coalesce
Merge repeated pending deliveries (default true)
Definition Async.h:453
Definition Async.h:468
Definition Async.h:474
Starts monitoring a signal, notifying about its reception.
Definition Async.h:464
Function< void(Result &)> callback
Called when the signal is raised.
Definition Async.h:482
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:561
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:581
Function< void(Result &)> callback
Called after socket is finally connected to endpoint.
Definition Async.h:591
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:750
Definition Async.h:703
SC::Result get(Span< char > &outData)
Get a Span of the actually read data.
Definition Async.h:711
Starts a socket receive operation, receiving bytes from a remote endpoint.
Definition Async.h:693
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:729
Span< char > buffer
The writeable span of memory where to data will be written.
Definition Async.h:726
Function< void(Result &)> callback
Called after data has been received.
Definition Async.h:724
Starts an unconnected socket send to operation, sending bytes to a remote endpoint.
Definition Async.h:661
Starts a socket send operation, sending bytes to a remote endpoint.
Definition Async.h:615
Function< void(Result &)> callback
Called when socket is ready to send more data.
Definition Async.h:630
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:637
Span< const char > buffer
Span of bytes to send (singleBuffer == true)
Definition Async.h:636
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:1131
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