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<28> 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
629 Function<void(Result&)> callback;
630
631 SocketDescriptor::Handle handle = SocketDescriptor::Invalid;
632 SocketIPAddress ipAddress;
633
634 private:
635 friend struct AsyncEventLoop;
636 SC::Result validate(AsyncEventLoop&);
637
638#if SC_PLATFORM_WINDOWS
639 void (*pConnectEx)() = nullptr;
640 detail::WinOverlappedOpaque overlapped;
641#endif
642};
643
652struct SC_ASYNC_EXPORT AsyncSocketSend : public AsyncRequest
653{
654 AsyncSocketSend() : AsyncRequest(Type::SocketSend) {}
656 {
657 size_t numBytes = 0;
658 };
660 using AsyncRequest::start;
661
663 SC::Result start(AsyncEventLoop& eventLoop, const SocketDescriptor& descriptor, Span<const char> data);
664
666 SC::Result start(AsyncEventLoop& eventLoop, const SocketDescriptor& descriptor, Span<Span<const char>> data);
667
668 Function<void(Result&)> callback;
669
670 SocketDescriptor::Handle handle = SocketDescriptor::Invalid;
671
672 SC::Result closeHandle() { return detail::SocketDescriptorDefinition::releaseHandle(handle); }
673
674 Span<const char> buffer;
675 Span<Span<const char>> buffers;
676 bool singleBuffer = true;
677
678 protected:
679 AsyncSocketSend(Type type) : AsyncRequest(type) {}
680 friend struct AsyncEventLoop;
681 SC::Result validate(AsyncEventLoop&);
682
683 size_t totalBytesWritten = 0;
684#if SC_PLATFORM_WINDOWS
685 detail::WinOverlappedOpaque overlapped;
686#endif
687};
688
698struct SC_ASYNC_EXPORT AsyncSocketSendTo : public AsyncSocketSend
699{
700 AsyncSocketSendTo() : AsyncSocketSend(Type::SocketSendTo) {}
701
702 SocketIPAddress address;
703
704 SC::Result start(AsyncEventLoop& eventLoop, const SocketDescriptor& descriptor, SocketIPAddress ipAddress,
705 Span<const char> data);
706
707 SC::Result start(AsyncEventLoop& eventLoop, const SocketDescriptor& descriptor, SocketIPAddress ipAddress,
708 Span<Span<const char>> data);
709
710 private:
711 using AsyncSocketSend::start;
712 friend struct AsyncEventLoop;
713 SC::Result validate(AsyncEventLoop&);
714#if SC_PLATFORM_LINUX
715 AlignedStorage<56> typeErasedMsgHdr;
716#endif
717};
718
730struct SC_ASYNC_EXPORT AsyncSocketReceive : public AsyncRequest
731{
732 AsyncSocketReceive() : AsyncRequest(Type::SocketReceive) {}
733
735 {
736 size_t numBytes = 0;
737 bool disconnected = false;
738 };
739
740 struct Result : public AsyncResultOf<AsyncSocketReceive, CompletionData>
741 {
742 using AsyncResultOf<AsyncSocketReceive, CompletionData>::AsyncResultOf;
743
744 bool isEnded() const { return completionData.disconnected; }
745
749 SC::Result get(Span<char>& outData)
750 {
751 SC_TRY(getAsync().buffer.sliceStartLength(0, completionData.numBytes, outData));
752 return returnCode;
753 }
754
755 SocketIPAddress getSourceAddress() const;
756 };
757 using AsyncRequest::start;
758
760 SC::Result start(AsyncEventLoop& eventLoop, const SocketDescriptor& descriptor, Span<char> data);
761
762 Function<void(Result&)> callback;
763
764 Span<char> buffer;
765 SocketDescriptor::Handle handle = SocketDescriptor::Invalid;
766
767 SC::Result closeHandle() { return detail::SocketDescriptorDefinition::releaseHandle(handle); }
768
769 protected:
770 AsyncSocketReceive(Type type) : AsyncRequest(type) {}
771 friend struct AsyncEventLoop;
772 SC::Result validate(AsyncEventLoop&);
773#if SC_PLATFORM_WINDOWS
774 detail::WinOverlappedOpaque overlapped;
775#endif
776};
777
787struct SC_ASYNC_EXPORT AsyncSocketReceiveFrom : public AsyncSocketReceive
788{
789 AsyncSocketReceiveFrom() : AsyncSocketReceive(Type::SocketReceiveFrom) {}
790 using AsyncSocketReceive::start;
791
792 private:
793 SocketIPAddress address;
794 friend struct AsyncSocketReceive;
795 friend struct AsyncEventLoop;
796#if SC_PLATFORM_LINUX
797 AlignedStorage<56> typeErasedMsgHdr;
798#endif
799};
800
823struct SC_ASYNC_EXPORT AsyncFileRead : public AsyncRequest
824{
825 AsyncFileRead() : AsyncRequest(Type::FileRead) { handle = FileDescriptor::Invalid; }
826
828 {
829 size_t numBytes = 0;
830 bool endOfFile = false;
831 };
832
833 struct Result : public AsyncResultOf<AsyncFileRead, CompletionData>
834 {
835 using AsyncResultOf<AsyncFileRead, CompletionData>::AsyncResultOf;
836
837 bool isEnded() const { return completionData.endOfFile; }
838
839 SC::Result get(Span<char>& data)
840 {
841 SC_TRY(getAsync().buffer.sliceStartLength(0, completionData.numBytes, data));
842 return returnCode;
843 }
844 };
845 using AsyncRequest::start;
846
848 SC::Result start(AsyncEventLoop& eventLoop, const FileDescriptor& descriptor, Span<char> data);
849
850 Function<void(Result&)> callback;
851 Span<char> buffer;
852 FileDescriptor::Handle handle;
854
855 SC::Result closeHandle() { return detail::FileDescriptorDefinition::releaseHandle(handle); }
856
858 uint64_t getOffset() const { return offset; }
859
862 void setOffset(uint64_t fileOffset)
863 {
864 useOffset = true;
865 offset = fileOffset;
866 }
867
868 private:
869 friend struct AsyncEventLoop;
870 SC::Result validate(AsyncEventLoop&);
871
872 bool useOffset = false;
873 bool endedSync = false;
874
875 uint64_t offset = 0;
876#if SC_PLATFORM_WINDOWS
877 uint64_t readCursor = 0;
878 detail::WinOverlappedOpaque overlapped;
879#endif
880};
881
903struct SC_ASYNC_EXPORT AsyncFileWrite : public AsyncRequest
904{
905 AsyncFileWrite() : AsyncRequest(Type::FileWrite) { handle = FileDescriptor::Invalid; }
906
908 {
909 size_t numBytes = 0;
910 };
911
912 struct Result : public AsyncResultOf<AsyncFileWrite, CompletionData>
913 {
914 using AsyncResultOf<AsyncFileWrite, CompletionData>::AsyncResultOf;
915
916 SC::Result get(size_t& writtenSizeInBytes)
917 {
918 writtenSizeInBytes = completionData.numBytes;
919 return returnCode;
920 }
921 };
922
923 using AsyncRequest::start;
924
926 SC::Result start(AsyncEventLoop& eventLoop, const FileDescriptor& descriptor, Span<Span<const char>> data);
927
929 SC::Result start(AsyncEventLoop& eventLoop, Span<Span<const char>> data);
930
932 SC::Result start(AsyncEventLoop& eventLoop, const FileDescriptor& descriptor, Span<const char> data);
933
935 SC::Result start(AsyncEventLoop& eventLoop, Span<const char> data);
936
937 Function<void(Result&)> callback;
938
939 FileDescriptor::Handle handle;
941
942 SC::Result closeHandle() { return detail::FileDescriptorDefinition::releaseHandle(handle); }
943
944 Span<const char> buffer;
945 Span<Span<const char>> buffers;
946 bool singleBuffer = true;
947
949 uint64_t getOffset() const { return offset; }
950
953 void setOffset(uint64_t fileOffset)
954 {
955 useOffset = true;
956 offset = fileOffset;
957 }
958
959 private:
960 friend struct AsyncEventLoop;
961 SC::Result validate(AsyncEventLoop&);
962
963#if SC_PLATFORM_WINDOWS
964 bool endedSync = false;
965#else
966 bool isWatchable = false;
967#endif
968 bool useOffset = false;
969 uint64_t offset = 0xffffffffffffffff;
970
971 size_t totalBytesWritten = 0;
972#if SC_PLATFORM_WINDOWS
973 detail::WinOverlappedOpaque overlapped;
974#endif
975};
976
980struct SC_ASYNC_EXPORT AsyncFileReadiness : public AsyncRequest
981{
982 AsyncFileReadiness() : AsyncRequest(Type::FileReadiness) {}
983
986
988 SC::Result start(AsyncEventLoop& eventLoop, FileDescriptor::Handle fileDescriptor);
989
990 Function<void(Result&)> callback;
991
992 private:
993 friend struct AsyncEventLoop;
994 SC::Result validate(AsyncEventLoop&);
995
996 FileDescriptor::Handle handle = FileDescriptor::Invalid;
997};
998
1002struct SC_ASYNC_EXPORT AsyncExternalCompletion : public AsyncRequest
1003{
1005 {
1006 size_t bytesTransferred = 0;
1007 };
1009
1010 AsyncExternalCompletion() : AsyncRequest(Type::ExternalCompletion) {}
1011
1013 SC::Result start(AsyncEventLoop& eventLoop);
1014
1015#if SC_PLATFORM_WINDOWS
1017 SC::Result start(AsyncEventLoop& eventLoop, FileDescriptor::Handle fileDescriptor);
1018
1020 [[nodiscard]] void* getWindowsOverlapped();
1021#endif
1022
1025
1028
1029 [[nodiscard]] bool hasSubmissionPending() const { return submissionPending; }
1030
1031 Function<void(Result&)> callback;
1032
1033 private:
1034 friend struct AsyncEventLoop;
1035 SC::Result validate(AsyncEventLoop&);
1036
1037 FileDescriptor::Handle handle = FileDescriptor::Invalid;
1038 size_t bytesTransferred = 0;
1039 bool manualMode = true;
1040 bool submissionPending = false;
1041 bool completionPosted = false;
1042#if SC_PLATFORM_WINDOWS
1043 detail::WinOverlappedOpaque overlapped;
1044#endif
1045};
1046
1071struct SC_ASYNC_EXPORT AsyncFileSend : public AsyncRequest
1072{
1073 AsyncFileSend() : AsyncRequest(Type::FileSend) {}
1074
1076 {
1077 size_t bytesTransferred = 0;
1078 bool usedZeroCopy = false;
1079 };
1080
1081 struct Result : public AsyncResultOf<AsyncFileSend, CompletionData>
1082 {
1083 using AsyncResultOf<AsyncFileSend, CompletionData>::AsyncResultOf;
1084
1086 [[nodiscard]] size_t getBytesTransferred() const { return completionData.bytesTransferred; }
1087
1089 [[nodiscard]] bool usedZeroCopy() const { return completionData.usedZeroCopy; }
1090
1092 [[nodiscard]] bool isComplete() const
1093 {
1094 return returnCode && completionData.bytesTransferred == getAsync().length;
1095 }
1096 };
1097
1098 using AsyncRequest::start;
1099
1109 SC::Result start(AsyncEventLoop& eventLoop, const FileDescriptor& file, const SocketDescriptor& socket,
1110 int64_t offset = 0, size_t length = 0, size_t pipeSize = 0);
1111
1112 Function<void(Result&)> callback;
1113
1114 // Internal handles (set by start())
1115 FileDescriptor::Handle fileHandle = FileDescriptor::Invalid;
1116 SocketDescriptor::Handle socketHandle = SocketDescriptor::Invalid;
1117
1118 int64_t offset = 0;
1119 size_t length = 0;
1120 size_t bytesSent = 0;
1121 private:
1122 friend struct AsyncEventLoop;
1123 SC::Result validate(AsyncEventLoop&);
1124
1125#if SC_PLATFORM_WINDOWS
1126 detail::WinOverlappedOpaque overlapped;
1127#elif SC_PLATFORM_LINUX
1128 size_t pipeBufferSize = 0;
1129 PipeDescriptor splicePipe;
1130#endif
1131};
1132
1133// forward declared because it must be defined after AsyncTaskSequence
1134struct AsyncLoopWork;
1136
1138{
1139 FileDescriptor::Handle handle = FileDescriptor::Invalid; // for open
1140
1141 int code = 0; // for open/close
1142 size_t numBytes = 0; // for read
1143};
1144
1145namespace detail
1146{
1147// A simple hand-made variant of all completion types
1148struct SC_ASYNC_EXPORT AsyncCompletionVariant
1149{
1150 AsyncCompletionVariant() {}
1151 ~AsyncCompletionVariant() { destroy(); }
1152
1153 AsyncCompletionVariant(const AsyncCompletionVariant&) = delete;
1154 AsyncCompletionVariant(AsyncCompletionVariant&&) = delete;
1155 AsyncCompletionVariant& operator=(const AsyncCompletionVariant&) = delete;
1156 AsyncCompletionVariant& operator=(AsyncCompletionVariant&&) = delete;
1157
1158 bool inited = false;
1159
1160 AsyncRequest::Type type;
1161 union
1162 {
1163 AsyncCompletionData completionDataLoopWork; // Defined after AsyncCompletionVariant / AsyncTaskSequence
1164 AsyncLoopTimeout::CompletionData completionDataLoopTimeout;
1165 AsyncLoopWakeUp::CompletionData completionDataLoopWakeUp;
1166 AsyncProcessExit::CompletionData completionDataProcessExit;
1167 AsyncSignal::CompletionData completionDataSignal;
1168 AsyncSocketAccept::CompletionData completionDataSocketAccept;
1169 AsyncSocketConnect::CompletionData completionDataSocketConnect;
1170 AsyncSocketSend::CompletionData completionDataSocketSend;
1171 AsyncSocketSendTo::CompletionData completionDataSocketSendTo;
1172 AsyncSocketReceive::CompletionData completionDataSocketReceive;
1173 AsyncSocketReceiveFrom::CompletionData completionDataSocketReceiveFrom;
1174 AsyncFileRead::CompletionData completionDataFileRead;
1175 AsyncFileWrite::CompletionData completionDataFileWrite;
1176 AsyncFileSend::CompletionData completionDataFileSend;
1177 AsyncFileReadiness::CompletionData completionDataFileReadiness;
1178 AsyncExternalCompletion::CompletionData completionDataExternalCompletion;
1179
1180 AsyncFileSystemOperationCompletionData completionDataFileSystemOperation;
1181 };
1182
1183 auto& getCompletion(AsyncLoopWork&) { return completionDataLoopWork; }
1184 auto& getCompletion(AsyncLoopTimeout&) { return completionDataLoopTimeout; }
1185 auto& getCompletion(AsyncLoopWakeUp&) { return completionDataLoopWakeUp; }
1186 auto& getCompletion(AsyncProcessExit&) { return completionDataProcessExit; }
1187 auto& getCompletion(AsyncSignal&) { return completionDataSignal; }
1188 auto& getCompletion(AsyncSocketAccept&) { return completionDataSocketAccept; }
1189 auto& getCompletion(AsyncSocketConnect&) { return completionDataSocketConnect; }
1190 auto& getCompletion(AsyncSocketSend&) { return completionDataSocketSend; }
1191 auto& getCompletion(AsyncSocketReceive&) { return completionDataSocketReceive; }
1192 auto& getCompletion(AsyncFileRead&) { return completionDataFileRead; }
1193 auto& getCompletion(AsyncFileWrite&) { return completionDataFileWrite; }
1194 auto& getCompletion(AsyncFileSend&) { return completionDataFileSend; }
1195 auto& getCompletion(AsyncFileReadiness&) { return completionDataFileReadiness; }
1196 auto& getCompletion(AsyncExternalCompletion&) { return completionDataExternalCompletion; }
1197 auto& getCompletion(AsyncFileSystemOperation&) { return completionDataFileSystemOperation; }
1198
1199 template <typename T>
1200 auto& construct(T& t)
1201 {
1202 destroy();
1203 placementNew(getCompletion(t));
1204 inited = true;
1205 type = t.getType();
1206 return getCompletion(t);
1207 }
1208 void destroy();
1209};
1210} // namespace detail
1211
1215struct SC_ASYNC_EXPORT AsyncTaskSequence : public AsyncSequence
1216{
1217 protected:
1218 ThreadPoolTask task;
1219 ThreadPool* threadPool = nullptr;
1220
1221 friend struct AsyncEventLoop;
1222 friend struct AsyncRequest;
1223
1224 detail::AsyncCompletionVariant completion;
1225
1226 SC::Result returnCode = SC::Result(true);
1227};
1228
1234struct SC_ASYNC_EXPORT AsyncLoopWork : public AsyncRequest
1235{
1236 AsyncLoopWork() : AsyncRequest(Type::LoopWork) {}
1237
1240
1243 SC::Result setThreadPool(ThreadPool& threadPool, AsyncThreadPoolMode mode = AsyncThreadPoolMode::NativePreferred);
1244
1245 Function<SC::Result()> work;
1246 Function<void(Result&)> callback;
1247
1248 private:
1249 friend struct AsyncEventLoop;
1250 SC::Result validate(AsyncEventLoop&);
1251 AsyncTaskSequence task;
1252};
1253
1287struct SC_ASYNC_EXPORT AsyncFileSystemOperation : public AsyncRequest
1288{
1289 AsyncFileSystemOperation() : AsyncRequest(Type::FileSystemOperation) {}
1290 ~AsyncFileSystemOperation() { destroy(); }
1291#ifdef CopyFile
1292#undef CopyFile
1293#endif
1294#ifdef RemoveDirectory
1295#undef RemoveDirectory
1296#endif
1297 enum class Operation
1298 {
1299 None = 0,
1300 Open,
1301 Close,
1302 Read,
1303 Write,
1304 CopyFile,
1305 CopyDirectory,
1306 Rename,
1307 RemoveDirectory,
1308 RemoveFile,
1309 };
1310
1313
1315 SC::Result setThreadPool(ThreadPool& threadPool, AsyncThreadPoolMode mode = AsyncThreadPoolMode::NativePreferred);
1316
1318 SC::Result stop(AsyncEventLoop& eventLoop, Function<void(AsyncResult&)>* afterStopped = nullptr);
1319
1320 Function<void(Result&)> callback;
1321
1327 SC::Result open(AsyncEventLoop& eventLoop, StringSpan path, FileOpen mode);
1328
1333 SC::Result close(AsyncEventLoop& eventLoop, FileDescriptor::Handle handle);
1334
1341 SC::Result read(AsyncEventLoop& eventLoop, FileDescriptor::Handle handle, Span<char> buffer, uint64_t offset);
1342
1349 SC::Result write(AsyncEventLoop& eventLoop, FileDescriptor::Handle handle, Span<const char> buffer,
1350 uint64_t offset);
1351
1358 SC::Result copyFile(AsyncEventLoop& eventLoop, StringSpan path, StringSpan destinationPath,
1360
1367 SC::Result copyDirectory(AsyncEventLoop& eventLoop, StringSpan path, StringSpan destinationPath,
1369
1375 SC::Result rename(AsyncEventLoop& eventLoop, StringSpan path, StringSpan newPath);
1376
1382 SC::Result removeEmptyDirectory(AsyncEventLoop& eventLoop, StringSpan path);
1383
1388 SC::Result removeFile(AsyncEventLoop& eventLoop, StringSpan path);
1389
1390 private:
1391 friend struct AsyncEventLoop;
1392 Operation operation = Operation::None;
1393 AsyncThreadPoolMode threadPoolMode = AsyncThreadPoolMode::NativePreferred;
1394 AsyncLoopWork loopWork;
1395 CompletionData completionData;
1396
1397 void onOperationCompleted(AsyncLoopWork::Result& res);
1398
1399 struct FileDescriptorData
1400 {
1401 FileDescriptor::Handle handle;
1402 };
1403
1404 struct OpenData
1405 {
1406 StringSpan path;
1407 FileOpen mode;
1408 };
1409
1410 struct ReadData
1411 {
1412 FileDescriptor::Handle handle;
1413 Span<char> buffer;
1414 uint64_t offset;
1415 };
1416
1417 struct WriteData
1418 {
1419 FileDescriptor::Handle handle;
1420 Span<const char> buffer;
1421 uint64_t offset;
1422 };
1423
1424 struct CopyFileData
1425 {
1426 StringSpan path;
1427 StringSpan destinationPath;
1428 FileSystemCopyFlags copyFlags;
1429 };
1430
1431 using CopyDirectoryData = CopyFileData;
1432
1433 using CloseData = FileDescriptorData;
1434
1435 struct RenameData
1436 {
1437 StringSpan path;
1438 StringSpan newPath;
1439 };
1440
1441 struct RemoveData
1442 {
1443 StringSpan path;
1444 };
1445
1446 union
1447 {
1448 OpenData openData;
1449 CloseData closeData;
1450 ReadData readData;
1451 WriteData writeData;
1452 CopyFileData copyFileData;
1453 CopyDirectoryData copyDirectoryData;
1454 RenameData renameData;
1455 RemoveData removeData;
1456 };
1457
1458 void destroy();
1459
1460 SC::Result start(AsyncEventLoop& eventLoop, FileDescriptor::Handle fileDescriptor);
1461 SC::Result validate(AsyncEventLoop&);
1462};
1463
1467struct SC_ASYNC_EXPORT AsyncKernelEvents
1468{
1469 Span<uint8_t> eventsMemory;
1470
1471 private:
1472 int numberOfEvents = 0;
1473 friend struct AsyncEventLoop;
1474 friend struct AsyncEventLoopMonitor;
1475};
1476
1478struct SC_ASYNC_EXPORT AsyncEventLoopListeners
1479{
1480 Function<void(AsyncEventLoop&)> beforeBlockingPoll;
1481 Function<void(AsyncEventLoop&)> afterBlockingPoll;
1482};
1483
1490struct SC_ASYNC_EXPORT AsyncEventLoop
1491{
1493 struct Options
1494 {
1495 enum class ApiType : uint8_t
1496 {
1497 Automatic = 0,
1498 ForceUseIoUring,
1499 ForceUseEpoll,
1500 };
1502
1503 Options() { apiType = ApiType::Automatic; }
1504 };
1505
1507
1508 AsyncEventLoop(const AsyncEventLoop&) = delete;
1509 AsyncEventLoop(AsyncEventLoop&&) = delete;
1510 AsyncEventLoop& operator=(AsyncEventLoop&&) = delete;
1511 AsyncEventLoop& operator=(const AsyncEventLoop&) = delete;
1512
1514 Result create(Options options = Options());
1515
1517 Result close();
1518
1521 Result start(AsyncRequest& async);
1522
1524 Result postExternalCompletion(AsyncExternalCompletion& async, size_t bytesTransferred = 0);
1525
1529
1531 [[nodiscard]] bool isInitialized() const;
1532
1534 [[nodiscard]] bool needsThreadPoolForFileOperations() const;
1535
1543 Result run();
1544
1554 Result runOnce();
1555
1561 Result runNoWait();
1562
1567 Result submitRequests(AsyncKernelEvents& kernelEvents);
1568
1589 Result blockingPoll(AsyncKernelEvents& kernelEvents);
1590
1598
1602
1605
1608
1611
1614
1616 Result associateExternallyCreatedSocketHandle(SocketDescriptor::Handle handle);
1617
1620
1622 Result associateExternallyCreatedFileDescriptorHandle(FileDescriptor::Handle handle);
1623
1625 static Result removeAllAssociationsFor(SocketDescriptor& outDescriptor);
1626
1628 static Result removeAllAssociationsForSocketHandle(SocketDescriptor::Handle handle);
1629
1631 static Result removeAllAssociationsFor(FileDescriptor& outDescriptor);
1632
1634 static Result removeAllAssociationsForFileDescriptorHandle(FileDescriptor::Handle handle);
1635
1638
1640 [[nodiscard]] TimeMs getLoopTime() const;
1641
1643 [[nodiscard]] int getNumberOfActiveRequests() const;
1644
1646 [[nodiscard]] int getNumberOfSubmittedRequests() const;
1647
1651
1656
1659
1664 void enumerateRequests(Function<void(AsyncRequest&)> enumerationCallback);
1665
1669
1671 [[nodiscard]] static bool isExcludedFromActiveCount(const AsyncRequest& async);
1672
1675 [[nodiscard]] static bool tryProbingIOUring();
1676
1679
1680 struct Internal;
1681
1683 using LoopWork = AsyncLoopWork;
1686 using Signal = AsyncSignal;
1693 using FileRead = AsyncFileRead;
1694 using FileWrite = AsyncFileWrite;
1695 using FileSend = AsyncFileSend;
1700 using ResultType = AsyncResult;
1701
1702 public:
1703 struct SC_ASYNC_EXPORT InternalDefinition
1704 {
1705 static constexpr int Windows = 576;
1706 static constexpr int Apple = 552;
1707 static constexpr int Linux = 816;
1708 static constexpr int Default = Linux;
1709
1710 static constexpr size_t Alignment = 8;
1711
1712 using Object = Internal;
1713 };
1714
1715 using InternalOpaque = OpaqueObject<InternalDefinition>;
1716
1717 private:
1718 InternalOpaque internalOpaque;
1719 Internal& internal;
1720
1721 friend struct AsyncRequest;
1722 friend struct AsyncLoopTimeout;
1723 friend struct AsyncFileWrite;
1724 friend struct AsyncFileRead;
1725 friend struct AsyncFileSystemOperation;
1726 friend struct AsyncResult;
1727};
1728
1732struct SC_ASYNC_EXPORT AsyncEventLoopMonitor
1733{
1734 Function<void(void)> onNewEventsAvailable;
1735
1738 Result create(AsyncEventLoop& eventLoop);
1739
1741 Result close();
1742
1750
1756
1757 private:
1758#if SC_COMPILER_MSVC
1759#pragma warning(push)
1760#pragma warning(disable : 4324) // useless warning on 32 bit... (structure was padded due to __declspec(align()))
1761#endif
1762 alignas(uint64_t) uint8_t eventsMemory[8 * 1024]; // 8 Kb of kernel events
1763#if SC_COMPILER_MSVC
1764#pragma warning(pop)
1765#endif
1766
1767 AsyncKernelEvents asyncKernelEvents;
1768 AsyncEventLoop* eventLoop = nullptr;
1769 AsyncLoopWakeUp eventLoopWakeUp;
1770
1771 Thread eventLoopThread;
1772 EventObject eventObjectEnterBlockingMode;
1773 EventObject eventObjectExitBlockingMode;
1774
1775 Atomic<bool> finished = false;
1776 Atomic<bool> needsWakeUp = true;
1777
1778 bool wakeUpHasBeenCalled = false;
1779
1780 Result monitoringLoopThread(Thread& thread);
1781};
1782
1783} // 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:1479
Monitors Async I/O events from a background thread using a blocking kernel function (no CPU usage on ...
Definition Async.h:1733
Function< void(void)> onNewEventsAvailable
Informs to call dispatchCompletions on GUI Event Loop.
Definition Async.h:1734
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:1494
ApiType apiType
Criteria to choose Async IO API.
Definition Async.h:1501
ApiType
Definition Async.h:1496
Asynchronous I/O (files, sockets, timers, processes, fs events, threads wake-up) (see Async) AsyncEve...
Definition Async.h:1491
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.
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:1003
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:828
Definition Async.h:834
Starts a file read operation, reading bytes from a file (or pipe).
Definition Async.h:824
FileDescriptor::Handle handle
The writeable span of memory where to data will be written.
Definition Async.h:852
Span< char > buffer
Callback called when some data has been read from the file into the buffer.
Definition Async.h:851
SC::Result closeHandle()
The file/pipe descriptor handle to read data from.
Definition Async.h:855
void setOffset(uint64_t fileOffset)
Sets the offset in bytes at which start reading.
Definition Async.h:862
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:858
Starts a file descriptor readiness operation.
Definition Async.h:981
SC::Result start(AsyncEventLoop &eventLoop, FileDescriptor::Handle fileDescriptor)
Starts a file descriptor poll operation, monitoring its readiness with appropriate OS API.
Definition Async.h:1076
Definition Async.h:1082
size_t getBytesTransferred() const
Get the number of bytes transferred.
Definition Async.h:1086
bool usedZeroCopy() const
Check if zero-copy was used for this transfer.
Definition Async.h:1089
bool isComplete() const
Check if the entire requested range was sent.
Definition Async.h:1092
Sends file contents to a socket using zero-copy when available (sendfile, TransmitFile).
Definition Async.h:1072
Function< void(Result &)> callback
Called when send completes or fails.
Definition Async.h:1112
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:1288
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:1320
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:913
Starts a file write operation, writing bytes to a file (or pipe).
Definition Async.h:904
uint64_t getOffset() const
Returns the last offset set with AsyncFileWrite::setOffset.
Definition Async.h:949
FileDescriptor::Handle handle
The file/pipe descriptor to write data to.
Definition Async.h:939
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:953
Function< void(Result &)> callback
Callback called when descriptor is ready to be written with more data.
Definition Async.h:937
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:945
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:944
Allows user to supply a block of memory that will store kernel I/O events retrieved from AsyncEventLo...
Definition Async.h:1468
Span< uint8_t > eventsMemory
User supplied block of memory used to store kernel I/O events.
Definition Async.h:1469
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:1235
Function< void(Result &)> callback
Called to execute the work in a background threadpool thread.
Definition Async.h:1246
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:629
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:788
Definition Async.h:741
SC::Result get(Span< char > &outData)
Get a Span of the actually read data.
Definition Async.h:749
Starts a socket receive operation, receiving bytes from a remote endpoint.
Definition Async.h:731
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:767
Span< char > buffer
The writeable span of memory where to data will be written.
Definition Async.h:764
Function< void(Result &)> callback
Called after data has been received.
Definition Async.h:762
Starts an unconnected socket send to operation, sending bytes to a remote endpoint.
Definition Async.h:699
Starts a socket send operation, sending bytes to a remote endpoint.
Definition Async.h:653
Function< void(Result &)> callback
Called when socket is ready to send more data.
Definition Async.h:668
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:675
Span< const char > buffer
Span of bytes to send (singleBuffer == true)
Definition Async.h:674
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:1216
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