5#include "../Foundation/Function.h"
6#include "../Foundation/OpaqueObject.h"
7#include "../Foundation/Span.h"
8#include "../Threading/Atomic.h"
9#include "../Threading/ThreadPool.h"
10#include "../Time/Time.h"
13#include "../File/FileDescriptor.h"
14#include "../Process/ProcessDescriptor.h"
15#include "../Socket/SocketDescriptor.h"
57struct AsyncWinOverlapped;
58struct AsyncWinOverlappedDefinition
60 static constexpr int Windows =
sizeof(
void*) * 4 +
sizeof(
uint64_t);
61 static constexpr size_t Alignment =
alignof(
void*);
63 using Object = AsyncWinOverlapped;
65using WinOverlappedOpaque = OpaqueObject<AsyncWinOverlappedDefinition>;
67struct AsyncWinWaitDefinition
69 using Handle = FileDescriptor::Handle;
70 static constexpr Handle Invalid = FileDescriptor::Invalid;
72 static Result releaseHandle(Handle& waitHandle);
74struct WinWaitHandle :
public UniqueHandle<AsyncWinWaitDefinition>
122 void setDebugName(
const char* newDebugName);
184 [[nodiscard]]
Result checkState();
199 [[nodiscard]]
static const char* TypeToString(
Type type);
210#if SC_CONFIGURATION_DEBUG
211 const char* debugName =
"None";
246 bool shouldBeReactivated =
false;
247 bool shouldCallCallback =
true;
255template <
typename T,
typename C>
258 T& getAsync() {
return static_cast<T&
>(AsyncResult::async); }
259 const T& getAsync()
const {
return static_cast<const T&
>(AsyncResult::async); }
348 status = completionData.exitStatus;
363 ProcessDescriptor::Handle handle = ProcessDescriptor::Invalid;
364#if SC_PLATFORM_WINDOWS
366 detail::WinWaitHandle waitHandle;
367#elif SC_PLATFORM_LINUX
397 return client.assign(
move(completionData.acceptedClient));
411 SocketDescriptor::Handle handle = SocketDescriptor::Invalid;
413#if SC_PLATFORM_WINDOWS
414 void (*pAcceptEx)() =
nullptr;
417 uint8_t acceptBuffer[288] = {0};
418#elif SC_PLATFORM_LINUX
449 SocketDescriptor::Handle handle = SocketDescriptor::Invalid;
451#if SC_PLATFORM_WINDOWS
452 void (*pConnectEx)() =
nullptr;
483 SocketDescriptor::Handle
handle = SocketDescriptor::Invalid;
493 size_t totalBytesWritten = 0;
494#if SC_PLATFORM_WINDOWS
517 bool disconnected =
false;
540 SocketDescriptor::Handle handle = SocketDescriptor::Invalid;
545#if SC_PLATFORM_WINDOWS
574 SocketDescriptor::Handle handle = SocketDescriptor::Invalid;
605 bool endOfFile =
false;
639 bool useOffset =
false;
641#if SC_PLATFORM_WINDOWS
679 writtenSizeInBytes = completionData.numBytes;
716 bool isWatchable =
false;
717 bool useOffset =
false;
718 uint64_t offset = 0xffffffffffffffff;
720 size_t totalBytesWritten = 0;
721#if SC_PLATFORM_WINDOWS
753 FileDescriptor::Handle handle = FileDescriptor::Invalid;
770#if SC_PLATFORM_WINDOWS
771 [[nodiscard]]
auto& getOverlappedOpaque() {
return overlapped; }
780 FileDescriptor::Handle handle = FileDescriptor::Invalid;
781#if SC_PLATFORM_WINDOWS
791struct AsyncCompletionVariant
793 AsyncCompletionVariant() {}
794 ~AsyncCompletionVariant() { destroy(); }
796 AsyncCompletionVariant(
const AsyncCompletionVariant&) =
delete;
797 AsyncCompletionVariant(AsyncCompletionVariant&&) =
delete;
798 AsyncCompletionVariant& operator=(
const AsyncCompletionVariant&) =
delete;
799 AsyncCompletionVariant& operator=(AsyncCompletionVariant&&) =
delete;
805 AsyncCompletionData completionDataLoopWork;
806 AsyncLoopTimeout::CompletionData completionDataLoopTimeout;
807 AsyncLoopWakeUp::CompletionData completionDataLoopWakeUp;
808 AsyncProcessExit::CompletionData completionDataProcessExit;
809 AsyncSocketAccept::CompletionData completionDataSocketAccept;
810 AsyncSocketConnect::CompletionData completionDataSocketConnect;
811 AsyncSocketSend::CompletionData completionDataSocketSend;
812 AsyncSocketReceive::CompletionData completionDataSocketReceive;
813 AsyncSocketClose::CompletionData completionDataSocketClose;
814 AsyncFileRead::CompletionData completionDataFileRead;
815 AsyncFileWrite::CompletionData completionDataFileWrite;
817 AsyncFilePoll::CompletionData completionDataFilePoll;
820 auto& getCompletion(AsyncLoopWork&) {
return completionDataLoopWork; }
821 auto& getCompletion(AsyncLoopTimeout&) {
return completionDataLoopTimeout; }
822 auto& getCompletion(AsyncLoopWakeUp&) {
return completionDataLoopWakeUp; }
823 auto& getCompletion(AsyncProcessExit&) {
return completionDataProcessExit; }
824 auto& getCompletion(AsyncSocketAccept&) {
return completionDataSocketAccept; }
825 auto& getCompletion(AsyncSocketConnect&) {
return completionDataSocketConnect; }
826 auto& getCompletion(AsyncSocketSend&) {
return completionDataSocketSend; }
827 auto& getCompletion(AsyncSocketReceive&) {
return completionDataSocketReceive; }
828 auto& getCompletion(AsyncSocketClose&) {
return completionDataSocketClose; }
829 auto& getCompletion(AsyncFileRead&) {
return completionDataFileRead; }
830 auto& getCompletion(AsyncFileWrite&) {
return completionDataFileWrite; }
831 auto& getCompletion(AsyncFileClose&) {
return completionDataFileClose; }
832 auto& getCompletion(AsyncFilePoll&) {
return completionDataFilePoll; }
834 template <
typename T>
835 auto& construct(T& t)
838 placementNew(getCompletion(t));
841 return getCompletion(t);
863 void freeTask() { async =
nullptr; }
864 bool isFree()
const {
return async ==
nullptr; }
866 detail::AsyncCompletionVariant completion;
907 int numberOfEvents = 0;
1072 struct InternalDefinition
1074 static constexpr int Windows = 488;
1075 static constexpr int Apple = 480;
1076 static constexpr int Linux = 688;
1077 static constexpr int Default = Linux;
1079 static constexpr size_t Alignment = 8;
1081 using Object = Internal;
1088 InternalOpaque internalOpaque;
1126#pragma warning(push)
1127#pragma warning(disable : 4324)
1145 bool wakeUpHasBeenCalled =
false;
constexpr T && move(T &value)
Converts an lvalue to an rvalue reference.
Definition Compiler.h:269
unsigned char uint8_t
Platform independent (1) byte unsigned int.
Definition PrimitiveTypes.h:36
unsigned long long uint64_t
Platform independent (8) bytes unsigned int.
Definition PrimitiveTypes.h:42
unsigned int uint32_t
Platform independent (4) bytes unsigned int.
Definition PrimitiveTypes.h:38
short int16_t
Platform independent (2) bytes signed int.
Definition PrimitiveTypes.h:45
int int32_t
Platform independent (4) bytes signed int.
Definition PrimitiveTypes.h:46
#define SC_TRY(expression)
Checks the value of the given expression and if failed, returns this value to caller.
Definition Result.h:48
A buffer of bytes with given alignment.
Definition AlignedStorage.h:29
Empty base struct for all AsyncRequest-derived CompletionData (internal) structs.
Definition Async.h:221
Allow library user to provide callbacks signaling different phases of async event loop cycle.
Definition Async.h:913
Monitors Async I/O events from a background thread using a blocking kernel function (no CPU usage on ...
Definition Async.h:1100
Result create(AsyncEventLoop &loop)
Create the monitoring thread for an AsyncEventLoop.
Function< void(void)> onNewEventsAvailable
Informs to call dispatchCompletions on GUI Event Loop.
Definition Async.h:1101
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.
Options given to AsyncEventLoop::create.
Definition Async.h:928
ApiType apiType
Criteria to choose Async IO API.
Definition Async.h:935
ApiType
Definition Async.h:930
@ Automatic
Platform specific backend chooses the best API.
@ ForceUseEpoll
(Linux only) Tries to use epoll
@ ForceUseIOURing
(Linux only) Tries to use io_uring (failing if it's not found on the system)
Asynchronous I/O (files, sockets, timers, processes, fs events, threads wake-up) (see Async) AsyncEve...
Definition Async.h:925
Time::Monotonic getLoopTime() const
Get Loop time.
Result associateExternallyCreatedFileDescriptor(FileDescriptor &outDescriptor)
Associates a File descriptor created externally with the eventLoop.
Result wakeUpFromExternalThread()
Wake up the event loop from a thread different than the one where run() is called (and potentially bl...
Result runNoWait()
Process active requests if any, dispatching their completions, or returns immediately without blockin...
void updateTime()
Updates loop time to "now".
static bool isExcludedFromActiveCount(const AsyncRequest &async)
Checks if excludeFromActiveCount() has been called on the given request.
Result blockingPoll(AsyncKernelEvents &kernelEvents)
Blocks until at least one event happens, ensuring forward progress, without executing completions.
int getNumberOfSubmittedRequests() const
Obtain the total number of submitted requests.
Result submitRequests(AsyncKernelEvents &kernelEvents)
Submits all queued async requests.
void enumerateRequests(Function< void(AsyncRequest &)> enumerationCallback)
Enumerates all requests objects associated with this loop.
Result start(AsyncRequest &async)
Queues an async request request that has been correctly setup.
AsyncLoopTimeout * findEarliestLoopTimeout() const
Returns the next AsyncLoopTimeout that will be executed (shortest relativeTimeout)
void setListeners(AsyncEventLoopListeners *listeners)
Sets reference to listeners that will signal different events in loop lifetime.
Result dispatchCompletions(AsyncKernelEvents &kernelEvents)
Invokes completions for the AsyncKernelEvents collected by a call to AsyncEventLoop::blockingPoll.
void interrupt()
Interrupts the event loop even if it has active request on it.
Result wakeUpFromExternalThread(AsyncLoopWakeUp &wakeUp)
Wake up the event loop from a thread different than the one where run() is called (and potentially bl...
bool isInitialized() const
Returns true if create has been already called (successfully)
Result create(Options options=Options())
Creates the event loop kernel object.
static bool tryLoadingLiburing()
Check if liburing is loadable (only on Linux)
Result createAsyncTCPSocket(SocketFlags::AddressFamily family, SocketDescriptor &outDescriptor)
Helper to creates a TCP socket with AsyncRequest flags of the given family (IPV4 / IPV6).
Result associateExternallyCreatedTCPSocket(SocketDescriptor &outDescriptor)
Associates a TCP Socket created externally (without using createAsyncTCPSocket) with the eventLoop.
Result close()
Closes the event loop kernel object.
Result runOnce()
Blocks until at least one request proceeds, ensuring forward progress, dispatching all completions.
void excludeFromActiveCount(AsyncRequest &async)
Excludes the request from active handles count (to avoid it keeping event loop alive)
Result run()
Blocks until there are no more active queued requests, dispatching all completions.
void includeInActiveCount(AsyncRequest &async)
Reverses the effect of excludeFromActiveCount for the request.
int getNumberOfActiveRequests() const
Obtain the total number of active requests.
Starts a file close operation, closing the OS file descriptor.
Definition Async.h:732
int code
Return code of close socket operation.
Definition Async.h:745
SC::Result start(AsyncEventLoop &eventLoop, FileDescriptor::Handle fileDescriptor)
Sets async request members and calls AsyncEventLoop::start.
AsyncCompletionData CompletionData
Completion data for AsyncFileClose.
Definition Async.h:736
Function< void(Result &)> callback
Callback called after fully closing the file descriptor.
Definition Async.h:747
Starts an handle polling operation.
Definition Async.h:761
SC::Result start(AsyncEventLoop &loop, FileDescriptor::Handle fileDescriptor)
Starts a file descriptor poll operation, monitoring its readiness with appropriate OS API.
Starts a file read operation, reading bytes from a file (or pipe).
Definition Async.h:599
FileDescriptor::Handle handle
The writeable span of memory where to data will be written.
Definition Async.h:622
Span< char > buffer
Callback called when some data has been read from the file into the buffer.
Definition Async.h:621
void setOffset(uint64_t fileOffset)
Sets the offset in bytes at which start reading.
Definition Async.h:630
uint64_t getOffset() const
The file/pipe descriptor handle to read data from.
Definition Async.h:626
Starts a file write operation, writing bytes to a file (or pipe).
Definition Async.h:665
uint64_t getOffset() const
Returns the last offset set with AsyncFileWrite::setOffset.
Definition Async.h:702
FileDescriptor::Handle handle
The file/pipe descriptor to write data to.
Definition Async.h:694
SC::Result start(AsyncEventLoop &eventLoop, 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:706
Function< void(Result &)> callback
Callback called when descriptor is ready to be written with more data.
Definition Async.h:692
Span< Span< const char > > buffers
The read-only spans of memory where to read the data from.
Definition Async.h:698
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:697
bool singleBuffer
Controls if buffer or buffers will be used.
Definition Async.h:699
Allows user to supply a block of memory that will store kernel I/O events retrieved from AsyncEventLo...
Definition Async.h:903
Span< uint8_t > eventsMemory
User supplied block of memory used to store kernel I/O events.
Definition Async.h:904
Starts a Timeout that is invoked only once after expiration (relative) time has passed.
Definition Async.h:271
SC::Result start(AsyncEventLoop &eventLoop, Time::Milliseconds relativeTimeout)
Sets async request members and calls AsyncEventLoop::start.
Time::Absolute getExpirationTime() const
Gets computed absolute expiration time that determines when this timeout get executed.
Definition Async.h:285
Function< void(Result &)> callback
Called after given expiration time since AsyncLoopTimeout::start has passed.
Definition Async.h:280
Time::Milliseconds relativeTimeout
First timer expiration (relative) time in milliseconds.
Definition Async.h:282
Starts a wake-up operation, allowing threads to execute callbacks on loop thread.
Definition Async.h:306
SC::Result start(AsyncEventLoop &eventLoop, EventObject &eventObject)
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:319
SC::Result wakeUp()
Wakes up event loop, scheduling AsyncLoopWakeUp::callback on next AsyncEventLoop::run (or its variati...
EventObject * eventObject
Optional EventObject to let external threads wait for the callback to end.
Definition Async.h:320
Executes work in a thread pool and then invokes a callback on the event loop thread.
Definition Async.h:877
Function< void(Result &)> callback
Called to execute the work in a background threadpool thread.
Definition Async.h:891
SC::Result setThreadPool(ThreadPool &threadPool)
Sets the ThreadPool that will supply the thread to run the async work on.
Starts monitoring a process, notifying about its termination.
Definition Async.h:334
SC::Result start(AsyncEventLoop &eventLoop, ProcessDescriptor::Handle process)
Sets async request members and calls AsyncEventLoop::start.
Function< void(Result &)> callback
Called when process has exited.
Definition Async.h:357
Base class for all async requests, holding state and type.
Definition Async.h:118
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:159
AsyncEventLoop * getEventLoop() const
Get the event loop associated with this AsyncRequest.
Definition Async.h:125
void resetThreadPoolAndTask()
Resets anything previously set with setThreadPoolAndTask.
Result stop(Function< void(AsyncResult &)> *afterStopped=nullptr)
Ask to stop current async operation.
bool isActive() const
Returns true if this request is active or being reactivated.
Result setThreadPoolAndTask(ThreadPool &pool, AsyncTask &task)
Sets the thread pool and task to use for this request.
void cacheInternalEventLoop(AsyncEventLoop &loop)
Caches the event loop associated with this AsyncRequest.
Definition Async.h:129
bool isFree() const
Returns true if this request is free.
Type getType() const
Returns request type.
Definition Async.h:178
Type
Type of async request.
Definition Async.h:141
@ FileClose
Request is an AsyncFileClose object.
@ SocketSend
Request is an AsyncSocketSend object.
@ SocketReceive
Request is an AsyncSocketReceive object.
@ SocketAccept
Request is an AsyncSocketAccept object.
@ FileWrite
Request is an AsyncFileWrite object.
@ LoopTimeout
Request is an AsyncLoopTimeout object.
@ ProcessExit
Request is an AsyncProcessExit object.
@ FileRead
Request is an AsyncFileRead object.
@ FilePoll
Request is an AsyncFilePoll object.
@ LoopWakeUp
Request is an AsyncLoopWakeUp object.
@ SocketClose
Request is an AsyncSocketClose object.
@ SocketConnect
Request is an AsyncSocketConnect object.
@ LoopWork
Request is an AsyncLoopWork object.
Result start(AsyncEventLoop &loop)
Shortcut for AsyncEventLoop::start.
Helper holding CompletionData for a specific AsyncRequest-derived class.
Definition Async.h:257
Base class for all async results (argument of completion callbacks).
Definition Async.h:227
void reactivateRequest(bool value)
Ask the event loop to re-activate this request after it was already completed.
const SC::Result & isValid() const
Check if the returnCode of this result is valid.
Definition Async.h:239
AsyncResult(AsyncRequest &request)
Constructs an async result from a request.
Definition Async.h:232
AsyncResult(AsyncRequest &request, SC::Result &&res)
Constructs an async result from a request and a result.
Definition Async.h:229
Starts a socket accept operation, obtaining a new socket from a listening socket.
Definition Async.h:382
Function< void(Result &)> callback
Called when a new socket has been accepted.
Definition Async.h:405
SC::Result start(AsyncEventLoop &eventLoop, const SocketDescriptor &socketDescriptor)
Sets async request members and calls AsyncEventLoop::start.
Starts a socket close operation.
Definition Async.h:555
int code
Return code of close socket operation.
Definition Async.h:566
SC::Result start(AsyncEventLoop &eventLoop, const SocketDescriptor &descriptor)
Sets async request members and calls AsyncEventLoop::start.
Function< void(Result &)> callback
Callback called after fully closing the socket.
Definition Async.h:568
Starts a socket connect operation, connecting to a remote endpoint.
Definition Async.h:433
Function< void(Result &)> callback
Called after socket is finally connected to endpoint.
Definition Async.h:443
SC::Result start(AsyncEventLoop &eventLoop, const SocketDescriptor &descriptor, SocketIPAddress address)
Sets async request members and calls AsyncEventLoop::start.
SC::Result get(Span< char > &outData)
Get a Span of the actually read data.
Definition Async.h:527
Starts a socket receive operation, receiving bytes from a remote endpoint.
Definition Async.h:511
SC::Result start(AsyncEventLoop &eventLoop, const SocketDescriptor &descriptor, Span< char > data)
Sets async request members and calls AsyncEventLoop::start.
Span< char > buffer
The writeable span of memory where to data will be written.
Definition Async.h:539
Function< void(Result &)> callback
Called after data has been received.
Definition Async.h:537
Starts a socket send operation, sending bytes to a remote endpoint.
Definition Async.h:466
Function< void(Result &)> callback
Called when socket is ready to send more data.
Definition Async.h:481
bool singleBuffer
Controls if buffer or buffers will be used.
Definition Async.h:487
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:486
Span< const char > buffer
Span of bytes to send (singleBuffer == true)
Definition Async.h:485
SC::Result start(AsyncEventLoop &eventLoop, const SocketDescriptor &descriptor, Span< Span< const char > > data)
Sets async request members and calls AsyncEventLoop::start.
SocketDescriptor::Handle handle
The socket to send data to.
Definition Async.h:483
Holds (reference to) a SC::ThreadPool and SC::ThreadPool::Task to execute an SC::AsyncRequest in a ba...
Definition Async.h:854
Atomic variables (only for int and bool for now).
Definition Atomic.h:97
An automatically reset event object to synchronize two threads.
Definition Threading.h:174
File Descriptor (use SC::File to open and use it with strings and buffers).
Definition FileDescriptor.h:52
Wraps function pointers, member functions and lambdas without ever allocating.
Definition Function.h:19
Hides implementation details from public headers (static PIMPL).
Definition OpaqueObject.h:77
Definition ProcessDescriptor.h:44
An ascii string used as boolean result. SC_TRY macro forwards errors to caller.
Definition Result.h:12
Low-level OS socket handle.
Definition SocketDescriptor.h:147
AddressFamily
Sets the address family of an IP Address (IPv4 or IPV6)
Definition SocketDescriptor.h:73
@ AddressFamilyIPV4
IP Address is IPV4.
Definition SocketDescriptor.h:74
Native representation of an IP Address.
Definition SocketDescriptor.h:110
View over a contiguous sequence of items (pointer + size in elements).
Definition Span.h:32
constexpr bool sliceStartLength(SizeType offsetInElements, SizeType lengthInElements, Span &destination) const
Creates another Span, starting at an offset in elements from current Span of specified length.
Definition Span.h:179
A small task containing a function to execute that can be queued in the thread pool.
Definition ThreadPool.h:19
Simple thread pool that executes tasks in a fixed number of worker threads.
Definition ThreadPool.h:41
A native OS thread.
Definition Threading.h:118
Absolute time as realtime or monotonically increasing clock.
Definition Time.h:114
Type-safe wrapper of uint64 used to represent milliseconds.
Definition Time.h:44
Represent monotonically increasing time (use Monotonic::now for current time)
Definition Time.h:180