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
58
61namespace SC
62{
63struct AsyncEventLoop;
64struct AsyncResult;
65struct AsyncSequence;
66struct AsyncTaskSequence;
67
69enum class AsyncThreadPoolMode : uint8_t
70{
71 NativePreferred,
72 ForceThreadPool,
73};
74
75namespace detail
76{
77struct AsyncWinOverlapped;
78struct AsyncWinOverlappedDefinition
79{
80 static constexpr int Windows = sizeof(void*) * 4 + sizeof(uint64_t);
81 static constexpr size_t Alignment = alignof(void*);
82
83 using Object = AsyncWinOverlapped;
84};
85using WinOverlappedOpaque = OpaqueObject<AsyncWinOverlappedDefinition>;
86
87struct AsyncWinWaitDefinition
88{
89 using Handle = FileDescriptor::Handle; // fd
90 static constexpr Handle Invalid = FileDescriptor::Invalid; // invalid fd
91
92 static Result releaseHandle(Handle& waitHandle);
93};
94struct SC_ASYNC_EXPORT WinWaitHandle : public UniqueHandle<AsyncWinWaitDefinition>
95{
96};
97} // namespace detail
98
137struct SC_ASYNC_EXPORT AsyncRequest
138{
139 AsyncRequest* next = nullptr;
140 AsyncRequest* prev = nullptr;
141
142 void setDebugName(const char* newDebugName);
143
145 void executeOn(AsyncSequence& sequence);
146
151 AsyncThreadPoolMode mode = AsyncThreadPoolMode::NativePreferred);
152
155
157 enum class Type : uint8_t
158 {
159 LoopTimeout,
160 LoopWakeUp,
161 LoopWork,
162 ProcessExit,
163 Signal,
164 SocketAccept,
165 SocketConnect,
166 SocketSend,
167 SocketSendTo,
168 SocketReceive,
169 SocketReceiveFrom,
170 FileRead,
171 FileWrite,
172 FileSend,
173 FileReadiness,
174 ExternalCompletion,
175 FileSystemOperation,
176 };
177
180 AsyncRequest(Type type) : state(State::Free), type(type), flags(0), unused(0), userFlags(0) {}
181
189 Result stop(AsyncEventLoop& eventLoop, Function<void(AsyncResult&)>* afterStopped = nullptr);
190
192 [[nodiscard]] bool isFree() const;
193
195 [[nodiscard]] bool isCancelling() const;
196
198 [[nodiscard]] bool isActive() const;
199
201 [[nodiscard]] Type getType() const { return type; }
202
204 Result start(AsyncEventLoop& eventLoop);
205
207 void setUserFlags(uint16_t externalFlags) { userFlags = externalFlags; }
208
210 uint16_t getUserFlags() const { return userFlags; }
211
213 [[nodiscard]] Function<void(AsyncResult&)>* getCloseCallback() { return closeCallback; }
214
215 [[nodiscard]] const Function<void(AsyncResult&)>* getCloseCallback() const { return closeCallback; }
216
217 protected:
218 Result checkState();
219
220 void queueSubmission(AsyncEventLoop& eventLoop);
221
222 AsyncSequence* sequence = nullptr;
223
224 AsyncTaskSequence* getTask();
225
226 [[nodiscard]] bool isThreadPoolForced() const;
227
228 private:
229 Function<void(AsyncResult&)>* closeCallback = nullptr;
230
231 friend struct AsyncEventLoop;
232 friend struct AsyncResult;
233
234 void markAsFree();
235
236 [[nodiscard]] static const char* TypeToString(Type type);
237 enum class State : uint8_t
238 {
239 Free, // not in any queue, this can be started with an async.start(...)
240 Setup, // when in submission queue waiting to be setup (after an async.start(...))
241 Submitting, // when in submission queue waiting to be activated or re-activated
242 Active, // when monitored by OS syscall or in activeLoopWakeUps / activeTimeouts queues
243 Reactivate, // when flagged for reactivation inside the callback (after a result.reactivateRequest(true))
244 Cancelling, // when in cancellation queue waiting for a cancelAsync (on active async)
245 };
246
247#if SC_ASYNC_ENABLE_LOG
248 const char* debugName = "None";
249#endif
250 State state; // 1 byte
251 Type type; // 1 byte
252 int16_t flags; // 2 bytes
253
254 uint16_t unused; // 2 bytes
255 uint16_t userFlags; // 2 bytes
256};
257
262struct SC_ASYNC_EXPORT AsyncSequence
263{
264 AsyncSequence* next = nullptr;
265 AsyncSequence* prev = nullptr;
266
267 bool clearSequenceOnCancel = true;
268 bool clearSequenceOnError = true;
269 private:
270 friend struct AsyncEventLoop;
271 bool runningAsync = false; // true if an async from this sequence is being run
272 bool tracked = false;
273
274 AsyncRequest* runningRequest = nullptr;
275
276 IntrusiveDoubleLinkedList<AsyncRequest> submissions;
277};
278
280struct SC_ASYNC_EXPORT AsyncCompletionData
281{
282};
283
286struct SC_ASYNC_EXPORT AsyncResult
287{
289 AsyncResult(AsyncEventLoop& eventLoop, AsyncRequest& request, SC::Result& res, bool* hasBeenReactivated = nullptr)
290 : eventLoop(eventLoop), async(request), hasBeenReactivated(hasBeenReactivated), returnCode(res)
291 {}
292
295 void reactivateRequest(bool shouldBeReactivated);
296
298 [[nodiscard]] const SC::Result& isValid() const { return returnCode; }
299
300 AsyncEventLoop& eventLoop;
301 AsyncRequest& async;
302
303 protected:
304 friend struct AsyncEventLoop;
305
306 bool shouldCallCallback = true;
307 bool* hasBeenReactivated = nullptr;
308
309 SC::Result& returnCode;
310};
311
315template <typename T, typename C>
317{
318 T& getAsync() { return static_cast<T&>(AsyncResult::async); }
319 const T& getAsync() const { return static_cast<const T&>(AsyncResult::async); }
320
322
323 C completionData;
324 int32_t eventIndex = 0;
325};
326
331struct SC_ASYNC_EXPORT AsyncLoopTimeout : public AsyncRequest
332{
333 AsyncLoopTimeout() : AsyncRequest(Type::LoopTimeout) {}
334
337 using AsyncRequest::start;
338
340 SC::Result start(AsyncEventLoop& eventLoop, TimeMs relativeTimeout);
341
345 SC::Result unschedule(AsyncEventLoop& eventLoop);
346
347 Function<void(Result&)> callback;
348
350
352 TimeMs getExpirationTime() const { return expirationTime; }
353
354 private:
355 SC::Result validate(AsyncEventLoop&);
356 friend struct AsyncEventLoop;
357 TimeMs expirationTime;
358};
359
362{
365 bool coalesce = true;
366};
367
387struct SC_ASYNC_EXPORT AsyncLoopWakeUp : public AsyncRequest
388{
389 AsyncLoopWakeUp() : AsyncRequest(Type::LoopWakeUp) {}
390
392 {
393 uint32_t deliveryCount = 1;
394 };
395
397
399 SC::Result start(AsyncEventLoop& eventLoop, AsyncLoopWakeUpOptions options = {});
400
402 SC::Result start(AsyncEventLoop& eventLoop, EventObject& eventObject, AsyncLoopWakeUpOptions options = {});
403
405 SC::Result wakeUp(AsyncEventLoop& eventLoop);
406
407 Function<void(Result&)> callback;
408 EventObject* eventObject = nullptr;
409
410 private:
411 friend struct AsyncEventLoop;
412 SC::Result validate(AsyncEventLoop&);
413 int32_t consumePendingWakeUps();
414 int32_t getPendingWakeUps() const;
415
416 AsyncLoopWakeUpOptions wakeUpOptions;
417 Atomic<int32_t> pendingWakeUps = 0;
418};
419
424struct SC_ASYNC_EXPORT AsyncProcessExit : public AsyncRequest
425{
426 AsyncProcessExit() : AsyncRequest(Type::ProcessExit) {}
427
429 {
430 int exitStatus;
431 };
432
433 struct Result : public AsyncResultOf<AsyncProcessExit, CompletionData>
434 {
435 using AsyncResultOf<AsyncProcessExit, CompletionData>::AsyncResultOf;
436
437 SC::Result get(int& status)
438 {
439 status = completionData.exitStatus;
440 return returnCode;
441 }
442 };
443 using AsyncRequest::start;
444
448 SC::Result start(AsyncEventLoop& eventLoop, FileDescriptor::Handle process);
449
450 Function<void(Result&)> callback;
451
452 private:
453 friend struct AsyncEventLoop;
454 SC::Result validate(AsyncEventLoop&);
455
456 FileDescriptor::Handle handle = FileDescriptor::Invalid;
457#if SC_PLATFORM_WINDOWS
458 detail::WinOverlappedOpaque overlapped;
459 detail::WinWaitHandle waitHandle;
460 AsyncEventLoop* eventLoop = nullptr;
461#elif SC_PLATFORM_LINUX
462 FileDescriptor pidFd;
463#endif
464};
465
468{
473 enum class Mode : uint8_t
474 {
475 Persistent,
476 OneShot
477 };
479 bool coalesce = true;
480};
481
501struct SC_ASYNC_EXPORT AsyncSignal : public AsyncRequest
502{
503 AsyncSignal() : AsyncRequest(Type::Signal) {}
504
506 {
507 int signalNumber = 0;
508 uint32_t deliveryCount = 1;
509 };
510
511 struct Result : public AsyncResultOf<AsyncSignal, CompletionData>
512 {
513 using AsyncResultOf<AsyncSignal, CompletionData>::AsyncResultOf;
514 };
515 using AsyncRequest::start;
516
518 SC::Result start(AsyncEventLoop& eventLoop, int num, AsyncSignalOptions options = {});
519
520 Function<void(Result&)> callback;
521
522 private:
523 friend struct AsyncEventLoop;
524 SC::Result validate(AsyncEventLoop&);
525
526 int signalNumber = 0;
527 AsyncSignalOptions signalOptions;
528#if SC_PLATFORM_WINDOWS
529 detail::WinOverlappedOpaque overlapped;
530 AsyncEventLoop* eventLoop = nullptr;
531#elif SC_PLATFORM_LINUX
532 FileDescriptor signalFd;
533 FileDescriptor::Handle signalFdHandle = FileDescriptor::Invalid;
534#endif
535};
536
537struct AsyncSocketAccept;
538namespace detail
539{
542struct SC_ASYNC_EXPORT AsyncSocketAcceptData
543{
544#if SC_PLATFORM_WINDOWS
545 void (*pAcceptEx)() = nullptr;
546 detail::WinOverlappedOpaque overlapped;
547 SocketDescriptor clientSocket;
548 uint8_t acceptBuffer[288] = {0};
549#elif SC_PLATFORM_LINUX
550 AlignedStorage<128> sockAddrHandle;
551 uint32_t sockAddrLen;
552#endif
553};
554
556struct SC_ASYNC_EXPORT AsyncSocketAcceptBase : public AsyncRequest
557{
558 AsyncSocketAcceptBase() : AsyncRequest(Type::SocketAccept) {}
559
560 struct CompletionData : public AsyncCompletionData
561 {
562 SocketDescriptor acceptedClient;
563 };
564
565 struct Result : public AsyncResultOf<AsyncSocketAccept, CompletionData>
566 {
567 using AsyncResultOf<AsyncSocketAccept, CompletionData>::AsyncResultOf;
568
569 SC::Result moveTo(SocketDescriptor& client)
570 {
571 SC_TRY(returnCode);
572 return SC::Result(client.assign(move(completionData.acceptedClient)));
573 }
574 };
575 using AsyncRequest::start;
576
578 SC::Result start(AsyncEventLoop& eventLoop, const SocketDescriptor& socketDescriptor, AsyncSocketAcceptData& data);
579 SC::Result validate(AsyncEventLoop&);
580
581 Function<void(Result&)> callback;
582 SocketDescriptor::Handle handle = SocketDescriptor::Invalid;
583 SocketFlags::AddressFamily addressFamily = SocketFlags::AddressFamilyIPV4;
584 AsyncSocketAcceptData* acceptData = nullptr;
585};
586
587} // namespace detail
588
598struct SC_ASYNC_EXPORT AsyncSocketAccept : public detail::AsyncSocketAcceptBase
599{
600 AsyncSocketAccept() { AsyncSocketAcceptBase::acceptData = &data; }
601 using AsyncSocketAcceptBase::start;
602
604 SC::Result start(AsyncEventLoop& eventLoop, const SocketDescriptor& socketDescriptor);
605
606 private:
607 detail::AsyncSocketAcceptData data;
608};
609
618struct SC_ASYNC_EXPORT AsyncSocketConnect : public AsyncRequest
619{
620 AsyncSocketConnect() : AsyncRequest(Type::SocketConnect) {}
621
624 using AsyncRequest::start;
625
627 SC::Result start(AsyncEventLoop& eventLoop, const SocketDescriptor& descriptor, SocketIPAddress address);
628 SC::Result start(AsyncEventLoop& eventLoop, const SocketDescriptor& descriptor, SocketAddress address);
629
630 Function<void(Result&)> callback;
631
632 SocketDescriptor::Handle handle = SocketDescriptor::Invalid;
633 SocketAddress address;
634
635 private:
636 friend struct AsyncEventLoop;
637 SC::Result validate(AsyncEventLoop&);
638
639#if SC_PLATFORM_WINDOWS
640 void (*pConnectEx)() = nullptr;
641 detail::WinOverlappedOpaque overlapped;
642#endif
643};
644
653struct SC_ASYNC_EXPORT AsyncSocketSend : public AsyncRequest
654{
655 AsyncSocketSend() : AsyncRequest(Type::SocketSend) {}
657 {
658 size_t numBytes = 0;
659 };
661 using AsyncRequest::start;
662
664 SC::Result start(AsyncEventLoop& eventLoop, const SocketDescriptor& descriptor, Span<const char> data);
665
667 SC::Result start(AsyncEventLoop& eventLoop, const SocketDescriptor& descriptor, Span<Span<const char>> data);
668
669 Function<void(Result&)> callback;
670
671 SocketDescriptor::Handle handle = SocketDescriptor::Invalid;
672
673 SC::Result closeHandle() { return detail::SocketDescriptorDefinition::releaseHandle(handle); }
674
675 Span<const char> buffer;
676 Span<Span<const char>> buffers;
677 bool singleBuffer = true;
678
679 protected:
680 AsyncSocketSend(Type type) : AsyncRequest(type) {}
681 friend struct AsyncEventLoop;
682 SC::Result validate(AsyncEventLoop&);
683
684 size_t totalBytesWritten = 0;
685#if SC_PLATFORM_WINDOWS
686 detail::WinOverlappedOpaque overlapped;
687#endif
688};
689
699struct SC_ASYNC_EXPORT AsyncSocketSendTo : public AsyncSocketSend
700{
701 AsyncSocketSendTo() : AsyncSocketSend(Type::SocketSendTo) {}
702
703 SocketAddress address;
704
705 SC::Result start(AsyncEventLoop& eventLoop, const SocketDescriptor& descriptor, SocketIPAddress ipAddress,
706 Span<const char> data);
707
708 SC::Result start(AsyncEventLoop& eventLoop, const SocketDescriptor& descriptor, SocketIPAddress ipAddress,
709 Span<Span<const char>> data);
710
711 SC::Result start(AsyncEventLoop& eventLoop, const SocketDescriptor& descriptor, SocketAddress socketAddress,
712 Span<const char> data);
713
714 SC::Result start(AsyncEventLoop& eventLoop, const SocketDescriptor& descriptor, SocketAddress socketAddress,
715 Span<Span<const char>> data);
716
717 private:
718 using AsyncSocketSend::start;
719 friend struct AsyncEventLoop;
720 SC::Result validate(AsyncEventLoop&);
721#if SC_PLATFORM_LINUX
722 AlignedStorage<56> typeErasedMsgHdr;
723#endif
724};
725
737struct SC_ASYNC_EXPORT AsyncSocketReceive : public AsyncRequest
738{
739 AsyncSocketReceive() : AsyncRequest(Type::SocketReceive) {}
740
742 {
743 size_t numBytes = 0;
744 bool disconnected = false;
745 };
746
747 struct Result : public AsyncResultOf<AsyncSocketReceive, CompletionData>
748 {
749 using AsyncResultOf<AsyncSocketReceive, CompletionData>::AsyncResultOf;
750
751 bool isEnded() const { return completionData.disconnected; }
752
756 SC::Result get(Span<char>& outData)
757 {
758 SC_TRY(getAsync().buffer.sliceStartLength(0, completionData.numBytes, outData));
759 return returnCode;
760 }
761
765
768 };
769 using AsyncRequest::start;
770
772 SC::Result start(AsyncEventLoop& eventLoop, const SocketDescriptor& descriptor, Span<char> data);
773
774 Function<void(Result&)> callback;
775
776 Span<char> buffer;
777 SocketDescriptor::Handle handle = SocketDescriptor::Invalid;
778
779 SC::Result closeHandle() { return detail::SocketDescriptorDefinition::releaseHandle(handle); }
780
781 protected:
782 AsyncSocketReceive(Type type) : AsyncRequest(type) {}
783 friend struct AsyncEventLoop;
784 SC::Result validate(AsyncEventLoop&);
785#if SC_PLATFORM_WINDOWS
786 detail::WinOverlappedOpaque overlapped;
787#endif
788};
789
799struct SC_ASYNC_EXPORT AsyncSocketReceiveFrom : public AsyncSocketReceive
800{
801 AsyncSocketReceiveFrom() : AsyncSocketReceive(Type::SocketReceiveFrom) {}
802 using AsyncSocketReceive::start;
803
804 private:
805 SocketAddress address;
806 friend struct AsyncSocketReceive;
807 friend struct AsyncEventLoop;
808#if SC_PLATFORM_LINUX
809 AlignedStorage<56> typeErasedMsgHdr;
810#elif SC_PLATFORM_WINDOWS
811 unsigned long receiveFlags = 0;
812 int addressSize = 0;
813#endif
814};
815
838struct SC_ASYNC_EXPORT AsyncFileRead : public AsyncRequest
839{
840 AsyncFileRead() : AsyncRequest(Type::FileRead) { handle = FileDescriptor::Invalid; }
841
843 {
844 size_t numBytes = 0;
845 bool endOfFile = false;
846 };
847
848 struct Result : public AsyncResultOf<AsyncFileRead, CompletionData>
849 {
850 using AsyncResultOf<AsyncFileRead, CompletionData>::AsyncResultOf;
851
852 bool isEnded() const { return completionData.endOfFile; }
853
854 SC::Result get(Span<char>& data)
855 {
856 SC_TRY(getAsync().buffer.sliceStartLength(0, completionData.numBytes, data));
857 return returnCode;
858 }
859 };
860 using AsyncRequest::start;
861
863 SC::Result start(AsyncEventLoop& eventLoop, const FileDescriptor& descriptor, Span<char> data);
864
865 Function<void(Result&)> callback;
866 Span<char> buffer;
867 FileDescriptor::Handle handle;
869
870 SC::Result closeHandle() { return detail::FileDescriptorDefinition::releaseHandle(handle); }
871
873 uint64_t getOffset() const { return offset; }
874
877 void setOffset(uint64_t fileOffset)
878 {
879 useOffset = true;
880 offset = fileOffset;
881 }
882
883 private:
884 friend struct AsyncEventLoop;
885 SC::Result validate(AsyncEventLoop&);
886
887 bool useOffset = false;
888 bool endedSync = false;
889
890 uint64_t offset = 0;
891#if SC_PLATFORM_WINDOWS
892 uint64_t readCursor = 0;
893 detail::WinOverlappedOpaque overlapped;
894#endif
895};
896
918struct SC_ASYNC_EXPORT AsyncFileWrite : public AsyncRequest
919{
920 AsyncFileWrite() : AsyncRequest(Type::FileWrite) { handle = FileDescriptor::Invalid; }
921
923 {
924 size_t numBytes = 0;
925 };
926
927 struct Result : public AsyncResultOf<AsyncFileWrite, CompletionData>
928 {
929 using AsyncResultOf<AsyncFileWrite, CompletionData>::AsyncResultOf;
930
931 SC::Result get(size_t& writtenSizeInBytes)
932 {
933 writtenSizeInBytes = completionData.numBytes;
934 return returnCode;
935 }
936 };
937
938 using AsyncRequest::start;
939
941 SC::Result start(AsyncEventLoop& eventLoop, const FileDescriptor& descriptor, Span<Span<const char>> data);
942
944 SC::Result start(AsyncEventLoop& eventLoop, Span<Span<const char>> data);
945
947 SC::Result start(AsyncEventLoop& eventLoop, const FileDescriptor& descriptor, Span<const char> data);
948
950 SC::Result start(AsyncEventLoop& eventLoop, Span<const char> data);
951
952 Function<void(Result&)> callback;
953
954 FileDescriptor::Handle handle;
956
957 SC::Result closeHandle() { return detail::FileDescriptorDefinition::releaseHandle(handle); }
958
959 Span<const char> buffer;
960 Span<Span<const char>> buffers;
961 bool singleBuffer = true;
962
964 uint64_t getOffset() const { return offset; }
965
968 void setOffset(uint64_t fileOffset)
969 {
970 useOffset = true;
971 offset = fileOffset;
972 }
973
974 private:
975 friend struct AsyncEventLoop;
976 SC::Result validate(AsyncEventLoop&);
977
978#if SC_PLATFORM_WINDOWS
979 bool endedSync = false;
980#else
981 bool isWatchable = false;
982#endif
983 bool useOffset = false;
984 uint64_t offset = 0xffffffffffffffff;
985
986 size_t totalBytesWritten = 0;
987#if SC_PLATFORM_WINDOWS
988 detail::WinOverlappedOpaque overlapped;
989#endif
990};
991
995struct SC_ASYNC_EXPORT AsyncFileReadiness : public AsyncRequest
996{
997 AsyncFileReadiness() : AsyncRequest(Type::FileReadiness) {}
998
1001
1003 SC::Result start(AsyncEventLoop& eventLoop, FileDescriptor::Handle fileDescriptor);
1004
1005 Function<void(Result&)> callback;
1006
1007 private:
1008 friend struct AsyncEventLoop;
1009 SC::Result validate(AsyncEventLoop&);
1010
1011 FileDescriptor::Handle handle = FileDescriptor::Invalid;
1012};
1013
1017struct SC_ASYNC_EXPORT AsyncExternalCompletion : public AsyncRequest
1018{
1020 {
1021 size_t bytesTransferred = 0;
1022 };
1024
1025 AsyncExternalCompletion() : AsyncRequest(Type::ExternalCompletion) {}
1026
1028 SC::Result start(AsyncEventLoop& eventLoop);
1029
1030#if SC_PLATFORM_WINDOWS
1032 SC::Result start(AsyncEventLoop& eventLoop, FileDescriptor::Handle fileDescriptor);
1033
1035 [[nodiscard]] void* getWindowsOverlapped();
1036#endif
1037
1040
1043
1044 [[nodiscard]] bool hasSubmissionPending() const { return submissionPending; }
1045
1046 Function<void(Result&)> callback;
1047
1048 private:
1049 friend struct AsyncEventLoop;
1050 SC::Result validate(AsyncEventLoop&);
1051
1052 FileDescriptor::Handle handle = FileDescriptor::Invalid;
1053 size_t bytesTransferred = 0;
1054 bool manualMode = true;
1055 bool submissionPending = false;
1056 bool completionPosted = false;
1057#if SC_PLATFORM_WINDOWS
1058 detail::WinOverlappedOpaque overlapped;
1059#endif
1060};
1061
1086struct SC_ASYNC_EXPORT AsyncFileSend : public AsyncRequest
1087{
1088 AsyncFileSend() : AsyncRequest(Type::FileSend) {}
1089
1091 {
1092 size_t bytesTransferred = 0;
1093 bool usedZeroCopy = false;
1094 };
1095
1096 struct Result : public AsyncResultOf<AsyncFileSend, CompletionData>
1097 {
1098 using AsyncResultOf<AsyncFileSend, CompletionData>::AsyncResultOf;
1099
1101 [[nodiscard]] size_t getBytesTransferred() const { return completionData.bytesTransferred; }
1102
1104 [[nodiscard]] bool usedZeroCopy() const { return completionData.usedZeroCopy; }
1105
1107 [[nodiscard]] bool isComplete() const
1108 {
1109 return returnCode && completionData.bytesTransferred == getAsync().length;
1110 }
1111 };
1112
1113 using AsyncRequest::start;
1114
1124 SC::Result start(AsyncEventLoop& eventLoop, const FileDescriptor& file, const SocketDescriptor& socket,
1125 int64_t offset = 0, size_t length = 0, size_t pipeSize = 0);
1126
1127 Function<void(Result&)> callback;
1128
1129 // Internal handles (set by start())
1130 FileDescriptor::Handle fileHandle = FileDescriptor::Invalid;
1131 SocketDescriptor::Handle socketHandle = SocketDescriptor::Invalid;
1132
1133 int64_t offset = 0;
1134 size_t length = 0;
1135 size_t bytesSent = 0;
1136 private:
1137 friend struct AsyncEventLoop;
1138 SC::Result validate(AsyncEventLoop&);
1139
1140#if SC_PLATFORM_WINDOWS
1141 detail::WinOverlappedOpaque overlapped;
1142#elif SC_PLATFORM_LINUX
1143 size_t pipeBufferSize = 0;
1144 PipeDescriptor splicePipe;
1145#endif
1146};
1147
1148// forward declared because it must be defined after AsyncTaskSequence
1149struct AsyncLoopWork;
1151
1153{
1154 FileDescriptor::Handle handle = FileDescriptor::Invalid; // for open
1155
1156 int code = 0; // for open/close
1157 size_t numBytes = 0; // for read
1158};
1159
1160namespace detail
1161{
1162// A simple hand-made variant of all completion types
1163struct SC_ASYNC_EXPORT AsyncCompletionVariant
1164{
1165 AsyncCompletionVariant() {}
1166 ~AsyncCompletionVariant() { destroy(); }
1167
1168 AsyncCompletionVariant(const AsyncCompletionVariant&) = delete;
1169 AsyncCompletionVariant(AsyncCompletionVariant&&) = delete;
1170 AsyncCompletionVariant& operator=(const AsyncCompletionVariant&) = delete;
1171 AsyncCompletionVariant& operator=(AsyncCompletionVariant&&) = delete;
1172
1173 bool inited = false;
1174
1175 AsyncRequest::Type type;
1176 union
1177 {
1178 AsyncCompletionData completionDataLoopWork; // Defined after AsyncCompletionVariant / AsyncTaskSequence
1179 AsyncLoopTimeout::CompletionData completionDataLoopTimeout;
1180 AsyncLoopWakeUp::CompletionData completionDataLoopWakeUp;
1181 AsyncProcessExit::CompletionData completionDataProcessExit;
1182 AsyncSignal::CompletionData completionDataSignal;
1183 AsyncSocketAccept::CompletionData completionDataSocketAccept;
1184 AsyncSocketConnect::CompletionData completionDataSocketConnect;
1185 AsyncSocketSend::CompletionData completionDataSocketSend;
1186 AsyncSocketSendTo::CompletionData completionDataSocketSendTo;
1187 AsyncSocketReceive::CompletionData completionDataSocketReceive;
1188 AsyncSocketReceiveFrom::CompletionData completionDataSocketReceiveFrom;
1189 AsyncFileRead::CompletionData completionDataFileRead;
1190 AsyncFileWrite::CompletionData completionDataFileWrite;
1191 AsyncFileSend::CompletionData completionDataFileSend;
1192 AsyncFileReadiness::CompletionData completionDataFileReadiness;
1193 AsyncExternalCompletion::CompletionData completionDataExternalCompletion;
1194
1195 AsyncFileSystemOperationCompletionData completionDataFileSystemOperation;
1196 };
1197
1198 auto& getCompletion(AsyncLoopWork&) { return completionDataLoopWork; }
1199 auto& getCompletion(AsyncLoopTimeout&) { return completionDataLoopTimeout; }
1200 auto& getCompletion(AsyncLoopWakeUp&) { return completionDataLoopWakeUp; }
1201 auto& getCompletion(AsyncProcessExit&) { return completionDataProcessExit; }
1202 auto& getCompletion(AsyncSignal&) { return completionDataSignal; }
1203 auto& getCompletion(AsyncSocketAccept&) { return completionDataSocketAccept; }
1204 auto& getCompletion(AsyncSocketConnect&) { return completionDataSocketConnect; }
1205 auto& getCompletion(AsyncSocketSend&) { return completionDataSocketSend; }
1206 auto& getCompletion(AsyncSocketReceive&) { return completionDataSocketReceive; }
1207 auto& getCompletion(AsyncFileRead&) { return completionDataFileRead; }
1208 auto& getCompletion(AsyncFileWrite&) { return completionDataFileWrite; }
1209 auto& getCompletion(AsyncFileSend&) { return completionDataFileSend; }
1210 auto& getCompletion(AsyncFileReadiness&) { return completionDataFileReadiness; }
1211 auto& getCompletion(AsyncExternalCompletion&) { return completionDataExternalCompletion; }
1212 auto& getCompletion(AsyncFileSystemOperation&) { return completionDataFileSystemOperation; }
1213
1214 template <typename T>
1215 auto& construct(T& t)
1216 {
1217 destroy();
1218 placementNew(getCompletion(t));
1219 inited = true;
1220 type = t.getType();
1221 return getCompletion(t);
1222 }
1223 void destroy();
1224};
1225} // namespace detail
1226
1230struct SC_ASYNC_EXPORT AsyncTaskSequence : public AsyncSequence
1231{
1232 protected:
1233 ThreadPoolTask task;
1234 ThreadPool* threadPool = nullptr;
1235
1236 friend struct AsyncEventLoop;
1237 friend struct AsyncRequest;
1238
1239 detail::AsyncCompletionVariant completion;
1240
1241 SC::Result returnCode = SC::Result(true);
1242};
1243
1249struct SC_ASYNC_EXPORT AsyncLoopWork : public AsyncRequest
1250{
1251 AsyncLoopWork() : AsyncRequest(Type::LoopWork) {}
1252
1255
1258 SC::Result setThreadPool(ThreadPool& threadPool, AsyncThreadPoolMode mode = AsyncThreadPoolMode::NativePreferred);
1259
1260 Function<SC::Result()> work;
1261 Function<void(Result&)> callback;
1262
1263 private:
1264 friend struct AsyncEventLoop;
1265 SC::Result validate(AsyncEventLoop&);
1266 AsyncTaskSequence task;
1267};
1268
1302struct SC_ASYNC_EXPORT AsyncFileSystemOperation : public AsyncRequest
1303{
1304 AsyncFileSystemOperation() : AsyncRequest(Type::FileSystemOperation) {}
1305 ~AsyncFileSystemOperation() { destroy(); }
1306#ifdef CopyFile
1307#undef CopyFile
1308#endif
1309#ifdef RemoveDirectory
1310#undef RemoveDirectory
1311#endif
1312 enum class Operation
1313 {
1314 None = 0,
1315 Open,
1316 Close,
1317 Read,
1318 Write,
1319 CopyFile,
1320 CopyDirectory,
1321 Rename,
1322 RemoveDirectory,
1323 RemoveFile,
1324 };
1325
1328
1330 SC::Result setThreadPool(ThreadPool& threadPool, AsyncThreadPoolMode mode = AsyncThreadPoolMode::NativePreferred);
1331
1333 SC::Result stop(AsyncEventLoop& eventLoop, Function<void(AsyncResult&)>* afterStopped = nullptr);
1334
1335 Function<void(Result&)> callback;
1336
1342 SC::Result open(AsyncEventLoop& eventLoop, StringSpan path, FileOpen mode);
1343
1348 SC::Result close(AsyncEventLoop& eventLoop, FileDescriptor::Handle handle);
1349
1356 SC::Result read(AsyncEventLoop& eventLoop, FileDescriptor::Handle handle, Span<char> buffer, uint64_t offset);
1357
1364 SC::Result write(AsyncEventLoop& eventLoop, FileDescriptor::Handle handle, Span<const char> buffer,
1365 uint64_t offset);
1366
1373 SC::Result copyFile(AsyncEventLoop& eventLoop, StringSpan path, StringSpan destinationPath,
1375
1382 SC::Result copyDirectory(AsyncEventLoop& eventLoop, StringSpan path, StringSpan destinationPath,
1384
1390 SC::Result rename(AsyncEventLoop& eventLoop, StringSpan path, StringSpan newPath);
1391
1397 SC::Result removeEmptyDirectory(AsyncEventLoop& eventLoop, StringSpan path);
1398
1403 SC::Result removeFile(AsyncEventLoop& eventLoop, StringSpan path);
1404
1405 private:
1406 friend struct AsyncEventLoop;
1407 Operation operation = Operation::None;
1408 AsyncThreadPoolMode threadPoolMode = AsyncThreadPoolMode::NativePreferred;
1409 AsyncLoopWork loopWork;
1410 CompletionData completionData;
1411
1412 void onOperationCompleted(AsyncLoopWork::Result& res);
1413
1414 struct FileDescriptorData
1415 {
1416 FileDescriptor::Handle handle;
1417 };
1418
1419 struct OpenData
1420 {
1421 StringSpan path;
1422 FileOpen mode;
1423 };
1424
1425 struct ReadData
1426 {
1427 FileDescriptor::Handle handle;
1428 Span<char> buffer;
1429 uint64_t offset;
1430 };
1431
1432 struct WriteData
1433 {
1434 FileDescriptor::Handle handle;
1435 Span<const char> buffer;
1436 uint64_t offset;
1437 };
1438
1439 struct CopyFileData
1440 {
1441 StringSpan path;
1442 StringSpan destinationPath;
1443 FileSystemCopyFlags copyFlags;
1444 };
1445
1446 using CopyDirectoryData = CopyFileData;
1447
1448 using CloseData = FileDescriptorData;
1449
1450 struct RenameData
1451 {
1452 StringSpan path;
1453 StringSpan newPath;
1454 };
1455
1456 struct RemoveData
1457 {
1458 StringSpan path;
1459 };
1460
1461 union
1462 {
1463 OpenData openData;
1464 CloseData closeData;
1465 ReadData readData;
1466 WriteData writeData;
1467 CopyFileData copyFileData;
1468 CopyDirectoryData copyDirectoryData;
1469 RenameData renameData;
1470 RemoveData removeData;
1471 };
1472
1473 void destroy();
1474
1475 SC::Result start(AsyncEventLoop& eventLoop, FileDescriptor::Handle fileDescriptor);
1476 SC::Result validate(AsyncEventLoop&);
1477};
1478
1482struct SC_ASYNC_EXPORT AsyncKernelEvents
1483{
1484 Span<uint8_t> eventsMemory;
1485
1486 private:
1487 int numberOfEvents = 0;
1488 friend struct AsyncEventLoop;
1489 friend struct AsyncEventLoopMonitor;
1490};
1491
1493struct SC_ASYNC_EXPORT AsyncEventLoopListeners
1494{
1495 Function<void(AsyncEventLoop&)> beforeBlockingPoll;
1496 Function<void(AsyncEventLoop&)> afterBlockingPoll;
1497};
1498
1505struct SC_ASYNC_EXPORT AsyncEventLoop
1506{
1508 struct Options
1509 {
1510 enum class ApiType : uint8_t
1511 {
1512 Automatic = 0,
1513 ForceUseIoUring,
1514 ForceUseEpoll,
1515 };
1517
1518 Options() { apiType = ApiType::Automatic; }
1519 };
1520
1522
1523 AsyncEventLoop(const AsyncEventLoop&) = delete;
1524 AsyncEventLoop(AsyncEventLoop&&) = delete;
1525 AsyncEventLoop& operator=(AsyncEventLoop&&) = delete;
1526 AsyncEventLoop& operator=(const AsyncEventLoop&) = delete;
1527
1529 Result create(Options options = Options());
1530
1532 Result close();
1533
1536 Result start(AsyncRequest& async);
1537
1539 Result postExternalCompletion(AsyncExternalCompletion& async, size_t bytesTransferred = 0);
1540
1544
1546 [[nodiscard]] bool isInitialized() const;
1547
1549 [[nodiscard]] bool needsThreadPoolForFileOperations() const;
1550
1558 Result run();
1559
1569 Result runOnce();
1570
1576 Result runNoWait();
1577
1582 Result submitRequests(AsyncKernelEvents& kernelEvents);
1583
1604 Result blockingPoll(AsyncKernelEvents& kernelEvents);
1605
1613
1617
1620
1623
1626
1629 SocketFlags::ProtocolType protocol, SocketDescriptor& outDescriptor);
1630
1633
1635 Result associateExternallyCreatedSocketHandle(SocketDescriptor::Handle handle);
1636
1639
1641 Result associateExternallyCreatedFileDescriptorHandle(FileDescriptor::Handle handle);
1642
1644 static Result removeAllAssociationsFor(SocketDescriptor& outDescriptor);
1645
1647 static Result removeAllAssociationsForSocketHandle(SocketDescriptor::Handle handle);
1648
1650 static Result removeAllAssociationsFor(FileDescriptor& outDescriptor);
1651
1653 static Result removeAllAssociationsForFileDescriptorHandle(FileDescriptor::Handle handle);
1654
1657
1659 [[nodiscard]] TimeMs getLoopTime() const;
1660
1662 [[nodiscard]] int getNumberOfActiveRequests() const;
1663
1665 [[nodiscard]] int getNumberOfSubmittedRequests() const;
1666
1670
1675
1678
1683 void enumerateRequests(Function<void(AsyncRequest&)> enumerationCallback);
1684
1688
1690 [[nodiscard]] static bool isExcludedFromActiveCount(const AsyncRequest& async);
1691
1694 [[nodiscard]] static bool tryProbingIOUring();
1695
1698
1699 struct Internal;
1700
1702 using LoopWork = AsyncLoopWork;
1705 using Signal = AsyncSignal;
1712 using FileRead = AsyncFileRead;
1713 using FileWrite = AsyncFileWrite;
1714 using FileSend = AsyncFileSend;
1719 using ResultType = AsyncResult;
1720
1721 public:
1722 struct SC_ASYNC_EXPORT InternalDefinition
1723 {
1724 static constexpr int Windows = 576;
1725 static constexpr int Apple = 552;
1726 static constexpr int Linux = 816;
1727 static constexpr int Default = Linux;
1728
1729 static constexpr size_t Alignment = 8;
1730
1731 using Object = Internal;
1732 };
1733
1734 using InternalOpaque = OpaqueObject<InternalDefinition>;
1735
1736 private:
1737 InternalOpaque internalOpaque;
1738 Internal& internal;
1739
1740 friend struct AsyncRequest;
1741 friend struct AsyncLoopTimeout;
1742 friend struct AsyncFileWrite;
1743 friend struct AsyncFileRead;
1744 friend struct AsyncFileSystemOperation;
1745 friend struct AsyncResult;
1746};
1747
1751struct SC_ASYNC_EXPORT AsyncEventLoopMonitor
1752{
1753 Function<void(void)> onNewEventsAvailable;
1754
1757 Result create(AsyncEventLoop& eventLoop);
1758
1760 Result close();
1761
1769
1775
1776 private:
1777#if SC_COMPILER_MSVC
1778#pragma warning(push)
1779#pragma warning(disable : 4324) // useless warning on 32 bit... (structure was padded due to __declspec(align()))
1780#endif
1781 alignas(uint64_t) uint8_t eventsMemory[8 * 1024]; // 8 Kb of kernel events
1782#if SC_COMPILER_MSVC
1783#pragma warning(pop)
1784#endif
1785
1786 AsyncKernelEvents asyncKernelEvents;
1787 AsyncEventLoop* eventLoop = nullptr;
1788 AsyncLoopWakeUp eventLoopWakeUp;
1789
1790 Thread eventLoopThread;
1791 EventObject eventObjectEnterBlockingMode;
1792 EventObject eventObjectExitBlockingMode;
1793
1794 Atomic<bool> finished = false;
1795 Atomic<bool> needsWakeUp = true;
1796
1797 bool wakeUpHasBeenCalled = false;
1798
1799 Result monitoringLoopThread(Thread& thread);
1800};
1801
1802} // namespace SC
Empty base struct for all AsyncRequest-derived CompletionData (internal) structs.
Definition Async.h:281
Allow library user to provide callbacks signaling different phases of async event loop cycle.
Definition Async.h:1494
Monitors Async I/O events from a background thread using a blocking kernel function (no CPU usage on ...
Definition Async.h:1752
Function< void(void)> onNewEventsAvailable
Informs to call dispatchCompletions on GUI Event Loop.
Definition Async.h:1753
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:1509
ApiType apiType
Criteria to choose Async IO API.
Definition Async.h:1516
ApiType
Definition Async.h:1511
Asynchronous I/O (files, sockets, timers, processes, fs events, threads wake-up) (see Async) AsyncEve...
Definition Async.h:1506
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 ready requests if any, dispatching their completions, or returns immediately without blocking...
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 without running user callbacks.
void enumerateRequests(Function< void(AsyncRequest &)> enumerationCallback)
Enumerates user-visible request 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.
Result createAsyncSocket(SocketFlags::AddressFamily family, SocketFlags::SocketType socketType, SocketFlags::ProtocolType protocol, SocketDescriptor &outDescriptor)
Creates a non-blocking socket registered with the event loop.
AsyncLoopTimeout * findEarliestLoopTimeout() const
Returns the next AsyncLoopTimeout that will be executed (shortest relativeTimeout)
void setListeners(AsyncEventLoopListeners *listeners)
Sets listeners invoked around AsyncEventLoop::blockingPoll.
Result dispatchCompletions(AsyncKernelEvents &kernelEvents)
Invokes completions for the AsyncKernelEvents collected by a call to AsyncEventLoop::blockingPoll.
void interrupt()
Interrupts AsyncEventLoop::run, causing it to return even if counted active work remains.
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 ready completions.
void excludeFromActiveCount(AsyncRequest &async)
Excludes the request from active handles count so it does not keep AsyncEventLoop::run alive.
Result run()
Blocks until there are no more counted active, submitted, or cancelling requests, dispatching complet...
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:1018
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:843
Definition Async.h:849
Starts a file read operation, reading bytes from a file (or pipe).
Definition Async.h:839
FileDescriptor::Handle handle
The writeable span of memory where to data will be written.
Definition Async.h:867
Span< char > buffer
Callback called when some data has been read from the file into the buffer.
Definition Async.h:866
SC::Result closeHandle()
The file/pipe descriptor handle to read data from.
Definition Async.h:870
void setOffset(uint64_t fileOffset)
Sets the offset in bytes at which start reading.
Definition Async.h:877
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:873
Starts a file descriptor readiness operation.
Definition Async.h:996
SC::Result start(AsyncEventLoop &eventLoop, FileDescriptor::Handle fileDescriptor)
Starts a file descriptor poll operation, monitoring its readiness with appropriate OS API.
Definition Async.h:1091
Definition Async.h:1097
size_t getBytesTransferred() const
Get the number of bytes transferred.
Definition Async.h:1101
bool usedZeroCopy() const
Check if zero-copy was used for this transfer.
Definition Async.h:1104
bool isComplete() const
Check if the entire requested range was sent.
Definition Async.h:1107
Sends file contents to a socket using zero-copy when available (sendfile, TransmitFile).
Definition Async.h:1087
Function< void(Result &)> callback
Called when send completes or fails.
Definition Async.h:1127
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:1303
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 setThreadPool(ThreadPool &threadPool, AsyncThreadPoolMode mode=AsyncThreadPoolMode::NativePreferred)
Sets the thread pool to use for the operation.
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 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:1335
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:928
Starts a file write operation, writing bytes to a file (or pipe).
Definition Async.h:919
uint64_t getOffset() const
Returns the last offset set with AsyncFileWrite::setOffset.
Definition Async.h:964
FileDescriptor::Handle handle
The file/pipe descriptor to write data to.
Definition Async.h:954
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:968
Function< void(Result &)> callback
Callback called when descriptor is ready to be written with more data.
Definition Async.h:952
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:960
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:959
Allows user to supply a block of memory that will store kernel I/O events retrieved from AsyncEventLo...
Definition Async.h:1483
Span< uint8_t > eventsMemory
User supplied block of memory used to store kernel I/O events.
Definition Async.h:1484
Starts a Timeout that is invoked only once after expiration (relative) time has passed.
Definition Async.h:332
TimeMs getExpirationTime() const
Gets computed absolute expiration time that determines when this timeout get executed.
Definition Async.h:352
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:349
Function< void(Result &)> callback
Called after given expiration time since AsyncLoopTimeout::start has passed.
Definition Async.h:347
SC::Result unschedule(AsyncEventLoop &eventLoop)
Synchronously removes an unsequenced timeout from the event loop schedule without invoking its callba...
Options for AsyncLoopWakeUp configuration.
Definition Async.h:362
bool coalesce
Merge repeated pending wakeUp() calls into a single callback (default true, matching libuv uv_async_t...
Definition Async.h:365
Starts a wake-up operation, allowing threads to execute callbacks on loop thread.
Definition Async.h:388
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:407
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:1250
Function< void(Result &)> callback
Called to execute the work in a background threadpool thread.
Definition Async.h:1261
SC::Result setThreadPool(ThreadPool &threadPool, AsyncThreadPoolMode mode=AsyncThreadPoolMode::NativePreferred)
Sets the ThreadPool that will supply the thread to run the async work on.
Definition Async.h:434
Starts monitoring a process, notifying about its termination.
Definition Async.h:425
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:450
Base class for all async requests, holding state and type.
Definition Async.h:138
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:180
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:210
Function< void(AsyncResult &)> * getCloseCallback()
Returns currently set close callback (if any) passed to AsyncRequest::stop.
Definition Async.h:213
bool isActive() const
Returns true if this request is active or being reactivated.
Result executeOn(AsyncTaskSequence &task, ThreadPool &pool, AsyncThreadPoolMode mode=AsyncThreadPoolMode::NativePreferred)
Adds the request to be executed on a specific AsyncTaskSequence.
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:201
void setUserFlags(uint16_t externalFlags)
Sets user flags, holding some meaningful data for the caller.
Definition Async.h:207
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:158
Helper holding CompletionData for a specific AsyncRequest-derived class.
Definition Async.h:317
Base class for all async results (argument of completion callbacks).
Definition Async.h:287
const SC::Result & isValid() const
Check if the returnCode of this result is valid.
Definition Async.h:298
AsyncResult(AsyncEventLoop &eventLoop, AsyncRequest &request, SC::Result &res, bool *hasBeenReactivated=nullptr)
Constructs an async result from a request and a result.
Definition Async.h:289
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:263
Options for AsyncSignal request configuration.
Definition Async.h:468
Mode
Reserved signal watching policy.
Definition Async.h:474
@ Persistent
Default policy; future backend parity work may use it for automatic persistence.
@ OneShot
Future policy for explicit one-shot watchers.
Mode mode
Currently does not bypass the AsyncRequest reactivation contract.
Definition Async.h:478
bool coalesce
Backend hint; portable code should inspect CompletionData::deliveryCount.
Definition Async.h:479
Definition Async.h:506
Definition Async.h:512
Starts monitoring a signal, notifying about its reception.
Definition Async.h:502
Function< void(Result &)> callback
Called when the signal is raised.
Definition Async.h:520
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:599
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:619
Function< void(Result &)> callback
Called after socket is finally connected to endpoint.
Definition Async.h:630
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:800
Definition Async.h:748
SC::Result get(Span< char > &outData)
Get a Span of the actually read data.
Definition Async.h:756
SocketIPAddress getSourceAddress() const
Returns the source when it is an IPv4 or IPv6 address.
SocketAddress getSourceSocketAddress() const
Returns the family-neutral source address for receive-from operations.
Starts a socket receive operation, receiving bytes from a remote endpoint.
Definition Async.h:738
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:779
Span< char > buffer
The writeable span of memory where to data will be written.
Definition Async.h:776
Function< void(Result &)> callback
Called after data has been received.
Definition Async.h:774
Starts an unconnected socket send to operation, sending bytes to a remote endpoint.
Definition Async.h:700
Starts a socket send operation, sending bytes to a remote endpoint.
Definition Async.h:654
Function< void(Result &)> callback
Called when socket is ready to send more data.
Definition Async.h:669
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:676
Span< const char > buffer
Span of bytes to send (singleBuffer == true)
Definition Async.h:675
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:1231
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
Family-neutral native socket address.
Definition Socket.h:168
Low-level OS socket handle.
Definition Socket.h:207
SocketType
Sets the socket type to datagram or stream.
Definition Socket.h:82
AddressFamily
Sets the socket address family.
Definition Socket.h:74
ProtocolType
Sets the socket protocol type.
Definition Socket.h:89
Native representation of an IP Address.
Definition Socket.h:117
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