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
342 Function<void(Result&)> callback;
343
345
347 TimeMs getExpirationTime() const { return expirationTime; }
348
349 private:
350 SC::Result validate(AsyncEventLoop&);
351 friend struct AsyncEventLoop;
352 TimeMs expirationTime;
353};
354
357{
360 bool coalesce = true;
361};
362
382struct SC_ASYNC_EXPORT AsyncLoopWakeUp : public AsyncRequest
383{
384 AsyncLoopWakeUp() : AsyncRequest(Type::LoopWakeUp) {}
385
387 {
388 uint32_t deliveryCount = 1;
389 };
390
392
394 SC::Result start(AsyncEventLoop& eventLoop, AsyncLoopWakeUpOptions options = {});
395
397 SC::Result start(AsyncEventLoop& eventLoop, EventObject& eventObject, AsyncLoopWakeUpOptions options = {});
398
400 SC::Result wakeUp(AsyncEventLoop& eventLoop);
401
402 Function<void(Result&)> callback;
403 EventObject* eventObject = nullptr;
404
405 private:
406 friend struct AsyncEventLoop;
407 SC::Result validate(AsyncEventLoop&);
408 int32_t consumePendingWakeUps();
409 int32_t getPendingWakeUps() const;
410
411 AsyncLoopWakeUpOptions wakeUpOptions;
412 Atomic<int32_t> pendingWakeUps = 0;
413};
414
419struct SC_ASYNC_EXPORT AsyncProcessExit : public AsyncRequest
420{
421 AsyncProcessExit() : AsyncRequest(Type::ProcessExit) {}
422
424 {
425 int exitStatus;
426 };
427
428 struct Result : public AsyncResultOf<AsyncProcessExit, CompletionData>
429 {
430 using AsyncResultOf<AsyncProcessExit, CompletionData>::AsyncResultOf;
431
432 SC::Result get(int& status)
433 {
434 status = completionData.exitStatus;
435 return returnCode;
436 }
437 };
438 using AsyncRequest::start;
439
443 SC::Result start(AsyncEventLoop& eventLoop, FileDescriptor::Handle process);
444
445 Function<void(Result&)> callback;
446
447 private:
448 friend struct AsyncEventLoop;
449 SC::Result validate(AsyncEventLoop&);
450
451 FileDescriptor::Handle handle = FileDescriptor::Invalid;
452#if SC_PLATFORM_WINDOWS
453 detail::WinOverlappedOpaque overlapped;
454 detail::WinWaitHandle waitHandle;
455 AsyncEventLoop* eventLoop = nullptr;
456#elif SC_PLATFORM_LINUX
457 FileDescriptor pidFd;
458#endif
459};
460
463{
468 enum class Mode : uint8_t
469 {
470 Persistent,
471 OneShot
472 };
474 bool coalesce = true;
475};
476
496struct SC_ASYNC_EXPORT AsyncSignal : public AsyncRequest
497{
498 AsyncSignal() : AsyncRequest(Type::Signal) {}
499
501 {
502 int signalNumber = 0;
503 uint32_t deliveryCount = 1;
504 };
505
506 struct Result : public AsyncResultOf<AsyncSignal, CompletionData>
507 {
508 using AsyncResultOf<AsyncSignal, CompletionData>::AsyncResultOf;
509 };
510 using AsyncRequest::start;
511
513 SC::Result start(AsyncEventLoop& eventLoop, int num, AsyncSignalOptions options = {});
514
515 Function<void(Result&)> callback;
516
517 private:
518 friend struct AsyncEventLoop;
519 SC::Result validate(AsyncEventLoop&);
520
521 int signalNumber = 0;
522 AsyncSignalOptions signalOptions;
523#if SC_PLATFORM_WINDOWS
524 detail::WinOverlappedOpaque overlapped;
525 AsyncEventLoop* eventLoop = nullptr;
526#elif SC_PLATFORM_LINUX
527 FileDescriptor signalFd;
528 FileDescriptor::Handle signalFdHandle = FileDescriptor::Invalid;
529#endif
530};
531
532struct AsyncSocketAccept;
533namespace detail
534{
537struct SC_ASYNC_EXPORT AsyncSocketAcceptData
538{
539#if SC_PLATFORM_WINDOWS
540 void (*pAcceptEx)() = nullptr;
541 detail::WinOverlappedOpaque overlapped;
542 SocketDescriptor clientSocket;
543 uint8_t acceptBuffer[288] = {0};
544#elif SC_PLATFORM_LINUX
545 AlignedStorage<28> sockAddrHandle;
546 uint32_t sockAddrLen;
547#endif
548};
549
551struct SC_ASYNC_EXPORT AsyncSocketAcceptBase : public AsyncRequest
552{
553 AsyncSocketAcceptBase() : AsyncRequest(Type::SocketAccept) {}
554
555 struct CompletionData : public AsyncCompletionData
556 {
557 SocketDescriptor acceptedClient;
558 };
559
560 struct Result : public AsyncResultOf<AsyncSocketAccept, CompletionData>
561 {
562 using AsyncResultOf<AsyncSocketAccept, CompletionData>::AsyncResultOf;
563
564 SC::Result moveTo(SocketDescriptor& client)
565 {
566 SC_TRY(returnCode);
567 return SC::Result(client.assign(move(completionData.acceptedClient)));
568 }
569 };
570 using AsyncRequest::start;
571
573 SC::Result start(AsyncEventLoop& eventLoop, const SocketDescriptor& socketDescriptor, AsyncSocketAcceptData& data);
574 SC::Result validate(AsyncEventLoop&);
575
576 Function<void(Result&)> callback;
577 SocketDescriptor::Handle handle = SocketDescriptor::Invalid;
578 SocketFlags::AddressFamily addressFamily = SocketFlags::AddressFamilyIPV4;
579 AsyncSocketAcceptData* acceptData = nullptr;
580};
581
582} // namespace detail
583
593struct SC_ASYNC_EXPORT AsyncSocketAccept : public detail::AsyncSocketAcceptBase
594{
595 AsyncSocketAccept() { AsyncSocketAcceptBase::acceptData = &data; }
596 using AsyncSocketAcceptBase::start;
597
599 SC::Result start(AsyncEventLoop& eventLoop, const SocketDescriptor& socketDescriptor);
600
601 private:
602 detail::AsyncSocketAcceptData data;
603};
604
613struct SC_ASYNC_EXPORT AsyncSocketConnect : public AsyncRequest
614{
615 AsyncSocketConnect() : AsyncRequest(Type::SocketConnect) {}
616
619 using AsyncRequest::start;
620
622 SC::Result start(AsyncEventLoop& eventLoop, const SocketDescriptor& descriptor, SocketIPAddress address);
623
624 Function<void(Result&)> callback;
625
626 SocketDescriptor::Handle handle = SocketDescriptor::Invalid;
627 SocketIPAddress ipAddress;
628
629 private:
630 friend struct AsyncEventLoop;
631 SC::Result validate(AsyncEventLoop&);
632
633#if SC_PLATFORM_WINDOWS
634 void (*pConnectEx)() = nullptr;
635 detail::WinOverlappedOpaque overlapped;
636#endif
637};
638
647struct SC_ASYNC_EXPORT AsyncSocketSend : public AsyncRequest
648{
649 AsyncSocketSend() : AsyncRequest(Type::SocketSend) {}
651 {
652 size_t numBytes = 0;
653 };
655 using AsyncRequest::start;
656
658 SC::Result start(AsyncEventLoop& eventLoop, const SocketDescriptor& descriptor, Span<const char> data);
659
661 SC::Result start(AsyncEventLoop& eventLoop, const SocketDescriptor& descriptor, Span<Span<const char>> data);
662
663 Function<void(Result&)> callback;
664
665 SocketDescriptor::Handle handle = SocketDescriptor::Invalid;
666
667 SC::Result closeHandle() { return detail::SocketDescriptorDefinition::releaseHandle(handle); }
668
669 Span<const char> buffer;
670 Span<Span<const char>> buffers;
671 bool singleBuffer = true;
672
673 protected:
674 AsyncSocketSend(Type type) : AsyncRequest(type) {}
675 friend struct AsyncEventLoop;
676 SC::Result validate(AsyncEventLoop&);
677
678 size_t totalBytesWritten = 0;
679#if SC_PLATFORM_WINDOWS
680 detail::WinOverlappedOpaque overlapped;
681#endif
682};
683
693struct SC_ASYNC_EXPORT AsyncSocketSendTo : public AsyncSocketSend
694{
695 AsyncSocketSendTo() : AsyncSocketSend(Type::SocketSendTo) {}
696
697 SocketIPAddress address;
698
699 SC::Result start(AsyncEventLoop& eventLoop, const SocketDescriptor& descriptor, SocketIPAddress ipAddress,
700 Span<const char> data);
701
702 SC::Result start(AsyncEventLoop& eventLoop, const SocketDescriptor& descriptor, SocketIPAddress ipAddress,
703 Span<Span<const char>> data);
704
705 private:
706 using AsyncSocketSend::start;
707 friend struct AsyncEventLoop;
708 SC::Result validate(AsyncEventLoop&);
709#if SC_PLATFORM_LINUX
710 AlignedStorage<56> typeErasedMsgHdr;
711#endif
712};
713
725struct SC_ASYNC_EXPORT AsyncSocketReceive : public AsyncRequest
726{
727 AsyncSocketReceive() : AsyncRequest(Type::SocketReceive) {}
728
730 {
731 size_t numBytes = 0;
732 bool disconnected = false;
733 };
734
735 struct Result : public AsyncResultOf<AsyncSocketReceive, CompletionData>
736 {
737 using AsyncResultOf<AsyncSocketReceive, CompletionData>::AsyncResultOf;
738
739 bool isEnded() const { return completionData.disconnected; }
740
744 SC::Result get(Span<char>& outData)
745 {
746 SC_TRY(getAsync().buffer.sliceStartLength(0, completionData.numBytes, outData));
747 return returnCode;
748 }
749
750 SocketIPAddress getSourceAddress() const;
751 };
752 using AsyncRequest::start;
753
755 SC::Result start(AsyncEventLoop& eventLoop, const SocketDescriptor& descriptor, Span<char> data);
756
757 Function<void(Result&)> callback;
758
759 Span<char> buffer;
760 SocketDescriptor::Handle handle = SocketDescriptor::Invalid;
761
762 SC::Result closeHandle() { return detail::SocketDescriptorDefinition::releaseHandle(handle); }
763
764 protected:
765 AsyncSocketReceive(Type type) : AsyncRequest(type) {}
766 friend struct AsyncEventLoop;
767 SC::Result validate(AsyncEventLoop&);
768#if SC_PLATFORM_WINDOWS
769 detail::WinOverlappedOpaque overlapped;
770#endif
771};
772
782struct SC_ASYNC_EXPORT AsyncSocketReceiveFrom : public AsyncSocketReceive
783{
784 AsyncSocketReceiveFrom() : AsyncSocketReceive(Type::SocketReceiveFrom) {}
785 using AsyncSocketReceive::start;
786
787 private:
788 SocketIPAddress address;
789 friend struct AsyncSocketReceive;
790 friend struct AsyncEventLoop;
791#if SC_PLATFORM_LINUX
792 AlignedStorage<56> typeErasedMsgHdr;
793#endif
794};
795
818struct SC_ASYNC_EXPORT AsyncFileRead : public AsyncRequest
819{
820 AsyncFileRead() : AsyncRequest(Type::FileRead) { handle = FileDescriptor::Invalid; }
821
823 {
824 size_t numBytes = 0;
825 bool endOfFile = false;
826 };
827
828 struct Result : public AsyncResultOf<AsyncFileRead, CompletionData>
829 {
830 using AsyncResultOf<AsyncFileRead, CompletionData>::AsyncResultOf;
831
832 bool isEnded() const { return completionData.endOfFile; }
833
834 SC::Result get(Span<char>& data)
835 {
836 SC_TRY(getAsync().buffer.sliceStartLength(0, completionData.numBytes, data));
837 return returnCode;
838 }
839 };
840 using AsyncRequest::start;
841
843 SC::Result start(AsyncEventLoop& eventLoop, const FileDescriptor& descriptor, Span<char> data);
844
845 Function<void(Result&)> callback;
846 Span<char> buffer;
847 FileDescriptor::Handle handle;
849
850 SC::Result closeHandle() { return detail::FileDescriptorDefinition::releaseHandle(handle); }
851
853 uint64_t getOffset() const { return offset; }
854
857 void setOffset(uint64_t fileOffset)
858 {
859 useOffset = true;
860 offset = fileOffset;
861 }
862
863 private:
864 friend struct AsyncEventLoop;
865 SC::Result validate(AsyncEventLoop&);
866
867 bool useOffset = false;
868 bool endedSync = false;
869
870 uint64_t offset = 0;
871#if SC_PLATFORM_WINDOWS
872 uint64_t readCursor = 0;
873 detail::WinOverlappedOpaque overlapped;
874#endif
875};
876
898struct SC_ASYNC_EXPORT AsyncFileWrite : public AsyncRequest
899{
900 AsyncFileWrite() : AsyncRequest(Type::FileWrite) { handle = FileDescriptor::Invalid; }
901
903 {
904 size_t numBytes = 0;
905 };
906
907 struct Result : public AsyncResultOf<AsyncFileWrite, CompletionData>
908 {
909 using AsyncResultOf<AsyncFileWrite, CompletionData>::AsyncResultOf;
910
911 SC::Result get(size_t& writtenSizeInBytes)
912 {
913 writtenSizeInBytes = completionData.numBytes;
914 return returnCode;
915 }
916 };
917
918 using AsyncRequest::start;
919
921 SC::Result start(AsyncEventLoop& eventLoop, const FileDescriptor& descriptor, Span<Span<const char>> data);
922
924 SC::Result start(AsyncEventLoop& eventLoop, Span<Span<const char>> data);
925
927 SC::Result start(AsyncEventLoop& eventLoop, const FileDescriptor& descriptor, Span<const char> data);
928
930 SC::Result start(AsyncEventLoop& eventLoop, Span<const char> data);
931
932 Function<void(Result&)> callback;
933
934 FileDescriptor::Handle handle;
936
937 SC::Result closeHandle() { return detail::FileDescriptorDefinition::releaseHandle(handle); }
938
939 Span<const char> buffer;
940 Span<Span<const char>> buffers;
941 bool singleBuffer = true;
942
944 uint64_t getOffset() const { return offset; }
945
948 void setOffset(uint64_t fileOffset)
949 {
950 useOffset = true;
951 offset = fileOffset;
952 }
953
954 private:
955 friend struct AsyncEventLoop;
956 SC::Result validate(AsyncEventLoop&);
957
958#if SC_PLATFORM_WINDOWS
959 bool endedSync = false;
960#else
961 bool isWatchable = false;
962#endif
963 bool useOffset = false;
964 uint64_t offset = 0xffffffffffffffff;
965
966 size_t totalBytesWritten = 0;
967#if SC_PLATFORM_WINDOWS
968 detail::WinOverlappedOpaque overlapped;
969#endif
970};
971
975struct SC_ASYNC_EXPORT AsyncFileReadiness : public AsyncRequest
976{
977 AsyncFileReadiness() : AsyncRequest(Type::FileReadiness) {}
978
981
983 SC::Result start(AsyncEventLoop& eventLoop, FileDescriptor::Handle fileDescriptor);
984
985 Function<void(Result&)> callback;
986
987 private:
988 friend struct AsyncEventLoop;
989 SC::Result validate(AsyncEventLoop&);
990
991 FileDescriptor::Handle handle = FileDescriptor::Invalid;
992};
993
997struct SC_ASYNC_EXPORT AsyncExternalCompletion : public AsyncRequest
998{
1000 {
1001 size_t bytesTransferred = 0;
1002 };
1004
1005 AsyncExternalCompletion() : AsyncRequest(Type::ExternalCompletion) {}
1006
1008 SC::Result start(AsyncEventLoop& eventLoop);
1009
1010#if SC_PLATFORM_WINDOWS
1012 SC::Result start(AsyncEventLoop& eventLoop, FileDescriptor::Handle fileDescriptor);
1013
1015 [[nodiscard]] void* getWindowsOverlapped();
1016#endif
1017
1020
1023
1024 [[nodiscard]] bool hasSubmissionPending() const { return submissionPending; }
1025
1026 Function<void(Result&)> callback;
1027
1028 private:
1029 friend struct AsyncEventLoop;
1030 SC::Result validate(AsyncEventLoop&);
1031
1032 FileDescriptor::Handle handle = FileDescriptor::Invalid;
1033 size_t bytesTransferred = 0;
1034 bool manualMode = true;
1035 bool submissionPending = false;
1036 bool completionPosted = false;
1037#if SC_PLATFORM_WINDOWS
1038 detail::WinOverlappedOpaque overlapped;
1039#endif
1040};
1041
1066struct SC_ASYNC_EXPORT AsyncFileSend : public AsyncRequest
1067{
1068 AsyncFileSend() : AsyncRequest(Type::FileSend) {}
1069
1071 {
1072 size_t bytesTransferred = 0;
1073 bool usedZeroCopy = false;
1074 };
1075
1076 struct Result : public AsyncResultOf<AsyncFileSend, CompletionData>
1077 {
1078 using AsyncResultOf<AsyncFileSend, CompletionData>::AsyncResultOf;
1079
1081 [[nodiscard]] size_t getBytesTransferred() const { return completionData.bytesTransferred; }
1082
1084 [[nodiscard]] bool usedZeroCopy() const { return completionData.usedZeroCopy; }
1085
1087 [[nodiscard]] bool isComplete() const
1088 {
1089 return returnCode && completionData.bytesTransferred == getAsync().length;
1090 }
1091 };
1092
1093 using AsyncRequest::start;
1094
1104 SC::Result start(AsyncEventLoop& eventLoop, const FileDescriptor& file, const SocketDescriptor& socket,
1105 int64_t offset = 0, size_t length = 0, size_t pipeSize = 0);
1106
1107 Function<void(Result&)> callback;
1108
1109 // Internal handles (set by start())
1110 FileDescriptor::Handle fileHandle = FileDescriptor::Invalid;
1111 SocketDescriptor::Handle socketHandle = SocketDescriptor::Invalid;
1112
1113 int64_t offset = 0;
1114 size_t length = 0;
1115 size_t bytesSent = 0;
1116 private:
1117 friend struct AsyncEventLoop;
1118 SC::Result validate(AsyncEventLoop&);
1119
1120#if SC_PLATFORM_WINDOWS
1121 detail::WinOverlappedOpaque overlapped;
1122#elif SC_PLATFORM_LINUX
1123 size_t pipeBufferSize = 0;
1124 PipeDescriptor splicePipe;
1125#endif
1126};
1127
1128// forward declared because it must be defined after AsyncTaskSequence
1129struct AsyncLoopWork;
1131
1133{
1134 FileDescriptor::Handle handle = FileDescriptor::Invalid; // for open
1135
1136 int code = 0; // for open/close
1137 size_t numBytes = 0; // for read
1138};
1139
1140namespace detail
1141{
1142// A simple hand-made variant of all completion types
1143struct SC_ASYNC_EXPORT AsyncCompletionVariant
1144{
1145 AsyncCompletionVariant() {}
1146 ~AsyncCompletionVariant() { destroy(); }
1147
1148 AsyncCompletionVariant(const AsyncCompletionVariant&) = delete;
1149 AsyncCompletionVariant(AsyncCompletionVariant&&) = delete;
1150 AsyncCompletionVariant& operator=(const AsyncCompletionVariant&) = delete;
1151 AsyncCompletionVariant& operator=(AsyncCompletionVariant&&) = delete;
1152
1153 bool inited = false;
1154
1155 AsyncRequest::Type type;
1156 union
1157 {
1158 AsyncCompletionData completionDataLoopWork; // Defined after AsyncCompletionVariant / AsyncTaskSequence
1159 AsyncLoopTimeout::CompletionData completionDataLoopTimeout;
1160 AsyncLoopWakeUp::CompletionData completionDataLoopWakeUp;
1161 AsyncProcessExit::CompletionData completionDataProcessExit;
1162 AsyncSignal::CompletionData completionDataSignal;
1163 AsyncSocketAccept::CompletionData completionDataSocketAccept;
1164 AsyncSocketConnect::CompletionData completionDataSocketConnect;
1165 AsyncSocketSend::CompletionData completionDataSocketSend;
1166 AsyncSocketSendTo::CompletionData completionDataSocketSendTo;
1167 AsyncSocketReceive::CompletionData completionDataSocketReceive;
1168 AsyncSocketReceiveFrom::CompletionData completionDataSocketReceiveFrom;
1169 AsyncFileRead::CompletionData completionDataFileRead;
1170 AsyncFileWrite::CompletionData completionDataFileWrite;
1171 AsyncFileSend::CompletionData completionDataFileSend;
1172 AsyncFileReadiness::CompletionData completionDataFileReadiness;
1173 AsyncExternalCompletion::CompletionData completionDataExternalCompletion;
1174
1175 AsyncFileSystemOperationCompletionData completionDataFileSystemOperation;
1176 };
1177
1178 auto& getCompletion(AsyncLoopWork&) { return completionDataLoopWork; }
1179 auto& getCompletion(AsyncLoopTimeout&) { return completionDataLoopTimeout; }
1180 auto& getCompletion(AsyncLoopWakeUp&) { return completionDataLoopWakeUp; }
1181 auto& getCompletion(AsyncProcessExit&) { return completionDataProcessExit; }
1182 auto& getCompletion(AsyncSignal&) { return completionDataSignal; }
1183 auto& getCompletion(AsyncSocketAccept&) { return completionDataSocketAccept; }
1184 auto& getCompletion(AsyncSocketConnect&) { return completionDataSocketConnect; }
1185 auto& getCompletion(AsyncSocketSend&) { return completionDataSocketSend; }
1186 auto& getCompletion(AsyncSocketReceive&) { return completionDataSocketReceive; }
1187 auto& getCompletion(AsyncFileRead&) { return completionDataFileRead; }
1188 auto& getCompletion(AsyncFileWrite&) { return completionDataFileWrite; }
1189 auto& getCompletion(AsyncFileSend&) { return completionDataFileSend; }
1190 auto& getCompletion(AsyncFileReadiness&) { return completionDataFileReadiness; }
1191 auto& getCompletion(AsyncExternalCompletion&) { return completionDataExternalCompletion; }
1192 auto& getCompletion(AsyncFileSystemOperation&) { return completionDataFileSystemOperation; }
1193
1194 template <typename T>
1195 auto& construct(T& t)
1196 {
1197 destroy();
1198 placementNew(getCompletion(t));
1199 inited = true;
1200 type = t.getType();
1201 return getCompletion(t);
1202 }
1203 void destroy();
1204};
1205} // namespace detail
1206
1210struct SC_ASYNC_EXPORT AsyncTaskSequence : public AsyncSequence
1211{
1212 protected:
1213 ThreadPoolTask task;
1214 ThreadPool* threadPool = nullptr;
1215
1216 friend struct AsyncEventLoop;
1217 friend struct AsyncRequest;
1218
1219 detail::AsyncCompletionVariant completion;
1220
1221 SC::Result returnCode = SC::Result(true);
1222};
1223
1229struct SC_ASYNC_EXPORT AsyncLoopWork : public AsyncRequest
1230{
1231 AsyncLoopWork() : AsyncRequest(Type::LoopWork) {}
1232
1235
1238 SC::Result setThreadPool(ThreadPool& threadPool, AsyncThreadPoolMode mode = AsyncThreadPoolMode::NativePreferred);
1239
1240 Function<SC::Result()> work;
1241 Function<void(Result&)> callback;
1242
1243 private:
1244 friend struct AsyncEventLoop;
1245 SC::Result validate(AsyncEventLoop&);
1246 AsyncTaskSequence task;
1247};
1248
1282struct SC_ASYNC_EXPORT AsyncFileSystemOperation : public AsyncRequest
1283{
1284 AsyncFileSystemOperation() : AsyncRequest(Type::FileSystemOperation) {}
1285 ~AsyncFileSystemOperation() { destroy(); }
1286#ifdef CopyFile
1287#undef CopyFile
1288#endif
1289#ifdef RemoveDirectory
1290#undef RemoveDirectory
1291#endif
1292 enum class Operation
1293 {
1294 None = 0,
1295 Open,
1296 Close,
1297 Read,
1298 Write,
1299 CopyFile,
1300 CopyDirectory,
1301 Rename,
1302 RemoveDirectory,
1303 RemoveFile,
1304 };
1305
1308
1310 SC::Result setThreadPool(ThreadPool& threadPool, AsyncThreadPoolMode mode = AsyncThreadPoolMode::NativePreferred);
1311
1313 SC::Result stop(AsyncEventLoop& eventLoop, Function<void(AsyncResult&)>* afterStopped = nullptr);
1314
1315 Function<void(Result&)> callback;
1316
1322 SC::Result open(AsyncEventLoop& eventLoop, StringSpan path, FileOpen mode);
1323
1328 SC::Result close(AsyncEventLoop& eventLoop, FileDescriptor::Handle handle);
1329
1336 SC::Result read(AsyncEventLoop& eventLoop, FileDescriptor::Handle handle, Span<char> buffer, uint64_t offset);
1337
1344 SC::Result write(AsyncEventLoop& eventLoop, FileDescriptor::Handle handle, Span<const char> buffer,
1345 uint64_t offset);
1346
1353 SC::Result copyFile(AsyncEventLoop& eventLoop, StringSpan path, StringSpan destinationPath,
1355
1362 SC::Result copyDirectory(AsyncEventLoop& eventLoop, StringSpan path, StringSpan destinationPath,
1364
1370 SC::Result rename(AsyncEventLoop& eventLoop, StringSpan path, StringSpan newPath);
1371
1377 SC::Result removeEmptyDirectory(AsyncEventLoop& eventLoop, StringSpan path);
1378
1383 SC::Result removeFile(AsyncEventLoop& eventLoop, StringSpan path);
1384
1385 private:
1386 friend struct AsyncEventLoop;
1387 Operation operation = Operation::None;
1388 AsyncThreadPoolMode threadPoolMode = AsyncThreadPoolMode::NativePreferred;
1389 AsyncLoopWork loopWork;
1390 CompletionData completionData;
1391
1392 void onOperationCompleted(AsyncLoopWork::Result& res);
1393
1394 struct FileDescriptorData
1395 {
1396 FileDescriptor::Handle handle;
1397 };
1398
1399 struct OpenData
1400 {
1401 StringSpan path;
1402 FileOpen mode;
1403 };
1404
1405 struct ReadData
1406 {
1407 FileDescriptor::Handle handle;
1408 Span<char> buffer;
1409 uint64_t offset;
1410 };
1411
1412 struct WriteData
1413 {
1414 FileDescriptor::Handle handle;
1415 Span<const char> buffer;
1416 uint64_t offset;
1417 };
1418
1419 struct CopyFileData
1420 {
1421 StringSpan path;
1422 StringSpan destinationPath;
1423 FileSystemCopyFlags copyFlags;
1424 };
1425
1426 using CopyDirectoryData = CopyFileData;
1427
1428 using CloseData = FileDescriptorData;
1429
1430 struct RenameData
1431 {
1432 StringSpan path;
1433 StringSpan newPath;
1434 };
1435
1436 struct RemoveData
1437 {
1438 StringSpan path;
1439 };
1440
1441 union
1442 {
1443 OpenData openData;
1444 CloseData closeData;
1445 ReadData readData;
1446 WriteData writeData;
1447 CopyFileData copyFileData;
1448 CopyDirectoryData copyDirectoryData;
1449 RenameData renameData;
1450 RemoveData removeData;
1451 };
1452
1453 void destroy();
1454
1455 SC::Result start(AsyncEventLoop& eventLoop, FileDescriptor::Handle fileDescriptor);
1456 SC::Result validate(AsyncEventLoop&);
1457};
1458
1462struct SC_ASYNC_EXPORT AsyncKernelEvents
1463{
1464 Span<uint8_t> eventsMemory;
1465
1466 private:
1467 int numberOfEvents = 0;
1468 friend struct AsyncEventLoop;
1469 friend struct AsyncEventLoopMonitor;
1470};
1471
1473struct SC_ASYNC_EXPORT AsyncEventLoopListeners
1474{
1475 Function<void(AsyncEventLoop&)> beforeBlockingPoll;
1476 Function<void(AsyncEventLoop&)> afterBlockingPoll;
1477};
1478
1485struct SC_ASYNC_EXPORT AsyncEventLoop
1486{
1488 struct Options
1489 {
1490 enum class ApiType : uint8_t
1491 {
1492 Automatic = 0,
1493 ForceUseIoUring,
1494 ForceUseEpoll,
1495 };
1497
1498 Options() { apiType = ApiType::Automatic; }
1499 };
1500
1502
1503 AsyncEventLoop(const AsyncEventLoop&) = delete;
1504 AsyncEventLoop(AsyncEventLoop&&) = delete;
1505 AsyncEventLoop& operator=(AsyncEventLoop&&) = delete;
1506 AsyncEventLoop& operator=(const AsyncEventLoop&) = delete;
1507
1509 Result create(Options options = Options());
1510
1512 Result close();
1513
1516 Result start(AsyncRequest& async);
1517
1519 Result postExternalCompletion(AsyncExternalCompletion& async, size_t bytesTransferred = 0);
1520
1524
1526 [[nodiscard]] bool isInitialized() const;
1527
1529 [[nodiscard]] bool needsThreadPoolForFileOperations() const;
1530
1538 Result run();
1539
1549 Result runOnce();
1550
1556 Result runNoWait();
1557
1562 Result submitRequests(AsyncKernelEvents& kernelEvents);
1563
1584 Result blockingPoll(AsyncKernelEvents& kernelEvents);
1585
1593
1597
1600
1603
1606
1609
1611 Result associateExternallyCreatedSocketHandle(SocketDescriptor::Handle handle);
1612
1615
1617 Result associateExternallyCreatedFileDescriptorHandle(FileDescriptor::Handle handle);
1618
1620 static Result removeAllAssociationsFor(SocketDescriptor& outDescriptor);
1621
1623 static Result removeAllAssociationsForSocketHandle(SocketDescriptor::Handle handle);
1624
1626 static Result removeAllAssociationsFor(FileDescriptor& outDescriptor);
1627
1629 static Result removeAllAssociationsForFileDescriptorHandle(FileDescriptor::Handle handle);
1630
1633
1635 [[nodiscard]] TimeMs getLoopTime() const;
1636
1638 [[nodiscard]] int getNumberOfActiveRequests() const;
1639
1641 [[nodiscard]] int getNumberOfSubmittedRequests() const;
1642
1646
1651
1654
1659 void enumerateRequests(Function<void(AsyncRequest&)> enumerationCallback);
1660
1664
1666 [[nodiscard]] static bool isExcludedFromActiveCount(const AsyncRequest& async);
1667
1670 [[nodiscard]] static bool tryProbingIOUring();
1671
1674
1675 struct Internal;
1676
1678 using LoopWork = AsyncLoopWork;
1681 using Signal = AsyncSignal;
1688 using FileRead = AsyncFileRead;
1689 using FileWrite = AsyncFileWrite;
1690 using FileSend = AsyncFileSend;
1695 using ResultType = AsyncResult;
1696
1697 public:
1698 struct SC_ASYNC_EXPORT InternalDefinition
1699 {
1700 static constexpr int Windows = 576;
1701 static constexpr int Apple = 552;
1702 static constexpr int Linux = 816;
1703 static constexpr int Default = Linux;
1704
1705 static constexpr size_t Alignment = 8;
1706
1707 using Object = Internal;
1708 };
1709
1710 using InternalOpaque = OpaqueObject<InternalDefinition>;
1711
1712 private:
1713 InternalOpaque internalOpaque;
1714 Internal& internal;
1715
1716 friend struct AsyncRequest;
1717 friend struct AsyncFileWrite;
1718 friend struct AsyncFileRead;
1719 friend struct AsyncFileSystemOperation;
1720 friend struct AsyncResult;
1721};
1722
1726struct SC_ASYNC_EXPORT AsyncEventLoopMonitor
1727{
1728 Function<void(void)> onNewEventsAvailable;
1729
1732 Result create(AsyncEventLoop& eventLoop);
1733
1735 Result close();
1736
1744
1750
1751 private:
1752#if SC_COMPILER_MSVC
1753#pragma warning(push)
1754#pragma warning(disable : 4324) // useless warning on 32 bit... (structure was padded due to __declspec(align()))
1755#endif
1756 alignas(uint64_t) uint8_t eventsMemory[8 * 1024]; // 8 Kb of kernel events
1757#if SC_COMPILER_MSVC
1758#pragma warning(pop)
1759#endif
1760
1761 AsyncKernelEvents asyncKernelEvents;
1762 AsyncEventLoop* eventLoop = nullptr;
1763 AsyncLoopWakeUp eventLoopWakeUp;
1764
1765 Thread eventLoopThread;
1766 EventObject eventObjectEnterBlockingMode;
1767 EventObject eventObjectExitBlockingMode;
1768
1769 Atomic<bool> finished = false;
1770 Atomic<bool> needsWakeUp = true;
1771
1772 bool wakeUpHasBeenCalled = false;
1773
1774 Result monitoringLoopThread(Thread& thread);
1775};
1776
1777} // 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:1474
Monitors Async I/O events from a background thread using a blocking kernel function (no CPU usage on ...
Definition Async.h:1727
Function< void(void)> onNewEventsAvailable
Informs to call dispatchCompletions on GUI Event Loop.
Definition Async.h:1728
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:1489
ApiType apiType
Criteria to choose Async IO API.
Definition Async.h:1496
ApiType
Definition Async.h:1491
Asynchronous I/O (files, sockets, timers, processes, fs events, threads wake-up) (see Async) AsyncEve...
Definition Async.h:1486
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:998
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:823
Definition Async.h:829
Starts a file read operation, reading bytes from a file (or pipe).
Definition Async.h:819
FileDescriptor::Handle handle
The writeable span of memory where to data will be written.
Definition Async.h:847
Span< char > buffer
Callback called when some data has been read from the file into the buffer.
Definition Async.h:846
SC::Result closeHandle()
The file/pipe descriptor handle to read data from.
Definition Async.h:850
void setOffset(uint64_t fileOffset)
Sets the offset in bytes at which start reading.
Definition Async.h:857
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:853
Starts a file descriptor readiness operation.
Definition Async.h:976
SC::Result start(AsyncEventLoop &eventLoop, FileDescriptor::Handle fileDescriptor)
Starts a file descriptor poll operation, monitoring its readiness with appropriate OS API.
Definition Async.h:1071
Definition Async.h:1077
size_t getBytesTransferred() const
Get the number of bytes transferred.
Definition Async.h:1081
bool usedZeroCopy() const
Check if zero-copy was used for this transfer.
Definition Async.h:1084
bool isComplete() const
Check if the entire requested range was sent.
Definition Async.h:1087
Sends file contents to a socket using zero-copy when available (sendfile, TransmitFile).
Definition Async.h:1067
Function< void(Result &)> callback
Called when send completes or fails.
Definition Async.h:1107
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:1283
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:1315
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:908
Starts a file write operation, writing bytes to a file (or pipe).
Definition Async.h:899
uint64_t getOffset() const
Returns the last offset set with AsyncFileWrite::setOffset.
Definition Async.h:944
FileDescriptor::Handle handle
The file/pipe descriptor to write data to.
Definition Async.h:934
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:948
Function< void(Result &)> callback
Callback called when descriptor is ready to be written with more data.
Definition Async.h:932
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:940
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:939
Allows user to supply a block of memory that will store kernel I/O events retrieved from AsyncEventLo...
Definition Async.h:1463
Span< uint8_t > eventsMemory
User supplied block of memory used to store kernel I/O events.
Definition Async.h:1464
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:347
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:344
Function< void(Result &)> callback
Called after given expiration time since AsyncLoopTimeout::start has passed.
Definition Async.h:342
Options for AsyncLoopWakeUp configuration.
Definition Async.h:357
bool coalesce
Merge repeated pending wakeUp() calls into a single callback (default true, matching libuv uv_async_t...
Definition Async.h:360
Starts a wake-up operation, allowing threads to execute callbacks on loop thread.
Definition Async.h:383
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:402
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:1230
Function< void(Result &)> callback
Called to execute the work in a background threadpool thread.
Definition Async.h:1241
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:429
Starts monitoring a process, notifying about its termination.
Definition Async.h:420
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:445
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:463
Mode
Reserved signal watching policy.
Definition Async.h:469
@ 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:473
bool coalesce
Backend hint; portable code should inspect CompletionData::deliveryCount.
Definition Async.h:474
Definition Async.h:501
Definition Async.h:507
Starts monitoring a signal, notifying about its reception.
Definition Async.h:497
Function< void(Result &)> callback
Called when the signal is raised.
Definition Async.h:515
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:594
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:614
Function< void(Result &)> callback
Called after socket is finally connected to endpoint.
Definition Async.h:624
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:783
Definition Async.h:736
SC::Result get(Span< char > &outData)
Get a Span of the actually read data.
Definition Async.h:744
Starts a socket receive operation, receiving bytes from a remote endpoint.
Definition Async.h:726
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:762
Span< char > buffer
The writeable span of memory where to data will be written.
Definition Async.h:759
Function< void(Result &)> callback
Called after data has been received.
Definition Async.h:757
Starts an unconnected socket send to operation, sending bytes to a remote endpoint.
Definition Async.h:694
Starts a socket send operation, sending bytes to a remote endpoint.
Definition Async.h:648
Function< void(Result &)> callback
Called when socket is ready to send more data.
Definition Async.h:663
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:670
Span< const char > buffer
Span of bytes to send (singleBuffer == true)
Definition Async.h:669
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:1211
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