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"
48struct AsyncKernelEvents;
50struct AsyncEventLoopMonitor;
54template <
typename T,
typename C>
56struct AsyncCompletionData;
59template <
typename AsyncType>
67struct AsyncWinOverlapped;
68struct AsyncWinOverlappedDefinition
70 static constexpr int Windows =
sizeof(
void*) * 4 +
sizeof(
uint64_t);
71 static constexpr size_t Alignment =
alignof(
void*);
73 using Object = AsyncWinOverlapped;
75using WinOverlappedOpaque = OpaqueObject<AsyncWinOverlappedDefinition>;
77struct AsyncWinWaitDefinition
79 using Handle = FileDescriptor::Handle;
80 static constexpr Handle Invalid = FileDescriptor::Invalid;
82 static Result releaseHandle(Handle& waitHandle);
84struct WinWaitHandle :
public UniqueHandle<AsyncWinWaitDefinition>
136 void setDebugName(
const char* newDebugName);
195 [[nodiscard]]
Result validateAsync();
210 [[nodiscard]]
static const char* TypeToString(
Type type);
221#if SC_CONFIGURATION_DEBUG
222 const char* debugName =
"None";
257 bool shouldBeReactivated =
false;
258 bool shouldCallCallback =
true;
266template <
typename T,
typename C>
269 T& getAsync() {
return static_cast<T&
>(AsyncResult::async); }
270 const T& getAsync()
const {
return static_cast<const T&
>(AsyncResult::async); }
291 void freeTask() { async =
nullptr; }
292 bool isFree()
const {
return async ==
nullptr; }
306template <
typename AsyncType>
309 typename AsyncType::CompletionData asyncCompletionData;
448 status = completionData.exitStatus;
463 ProcessDescriptor::Handle handle = ProcessDescriptor::Invalid;
464#if SC_PLATFORM_WINDOWS
466 detail::WinWaitHandle waitHandle;
467#elif SC_PLATFORM_LINUX
499 return client.assign(
move(completionData.acceptedClient));
514 SocketDescriptor::Handle handle = SocketDescriptor::Invalid;
516#if SC_PLATFORM_WINDOWS
517 void (*pAcceptEx)() =
nullptr;
520 uint8_t acceptBuffer[288] = {0};
521#elif SC_PLATFORM_LINUX
558 SocketDescriptor::Handle handle = SocketDescriptor::Invalid;
560#if SC_PLATFORM_WINDOWS
561 void (*pConnectEx)() =
nullptr;
606 SocketDescriptor::Handle
handle = SocketDescriptor::Invalid;
611#if SC_PLATFORM_WINDOWS
614 size_t totalBytesSent = 0;
637 bool disconnected =
false;
650 SC_TRY(getAsync().
buffer.sliceStartLength(0, completionData.numBytes, outData));
674 SocketDescriptor::Handle handle = SocketDescriptor::Invalid;
677#if SC_PLATFORM_WINDOWS
712 SocketDescriptor::Handle handle = SocketDescriptor::Invalid;
743 bool endOfFile =
false;
753 SC_TRY(getAsync().
buffer.sliceStartLength(0, completionData.numBytes, data));
789 bool useOffset =
false;
791#if SC_PLATFORM_WINDOWS
829 [[nodiscard]]
SC::Result get(
size_t& writtenSizeInBytes)
831 writtenSizeInBytes = completionData.numBytes;
867 bool useOffset =
false;
868 uint64_t offset = 0xffffffffffffffff;
869#if SC_PLATFORM_WINDOWS
898 FileDescriptor::Handle fileDescriptor = FileDescriptor::Invalid;
918#if SC_PLATFORM_WINDOWS
919 [[nodiscard]]
auto& getOverlappedOpaque() {
return overlapped; }
927 FileDescriptor::Handle fileDescriptor = FileDescriptor::Invalid;
928#if SC_PLATFORM_WINDOWS
945 int numberOfEvents = 0;
1090 struct InternalDefinition
1092 static constexpr int Windows = 496;
1093 static constexpr int Apple = 488;
1094 static constexpr int Linux = 696;
1095 static constexpr int Default = Linux;
1097 static constexpr size_t Alignment = 8;
1099 using Object = Internal;
1106 InternalOpaque internalOpaque;
1155 bool wakeUpHasBeenCalled =
false;
int int32_t
Platform independent (4) bytes signed int.
Definition: PrimitiveTypes.h:46
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
#define SC_TRY(expression)
Checks the value of the given expression and if failed, returns this value to caller.
Definition: Result.h:48
short int16_t
Platform independent (2) bytes signed int.
Definition: PrimitiveTypes.h:45
A buffer of bytes with given alignment.
Definition: AlignedStorage.h:25
Empty base struct for all AsyncRequest-derived CompletionData (internal) structs.
Definition: Async.h:232
Options given to AsyncEventLoop::create.
Definition: Async.h:959
ApiType apiType
Criteria to choose Async IO API.
Definition: Async.h:966
ApiType
Definition: Async.h:961
@ 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:956
Result associateExternallyCreatedFileDescriptor(FileDescriptor &outDescriptor)
Associates a File descriptor created externally with the eventLoop.
Time::HighResolutionCounter getLoopTime() const
Get Loop time.
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 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.
Monitors Async I/O events from a background thread using a blocking kernel function (no CPU usage on ...
Definition: Async.h:1118
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:1119
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.
Starts a file close operation, closing the OS file descriptor.
Definition: Async.h:880
int code
Return code of close socket operation.
Definition: Async.h:892
Function< void(Result &)> callback
Callback called after fully closing the file descriptor.
Definition: Async.h:894
Starts an handle polling operation.
Definition: Async.h:906
SC::Result start(AsyncEventLoop &loop, FileDescriptor::Handle fileDescriptor)
Starts a file descriptor poll operation, monitoring its readiness with appropriate OS API.
Completion data for AsyncFileRead.
Definition: Async.h:741
Callback result for AsyncFileRead.
Definition: Async.h:748
Starts a file read operation, reading bytes from a file (or pipe).
Definition: Async.h:736
Span< char > buffer
Callback called when some data has been read from the file into the buffer.
Definition: Async.h:772
FileDescriptor::Handle fileDescriptor
The writeable span of memory where to data will be written.
Definition: Async.h:773
SC::Result start(AsyncEventLoop &eventLoop)
Starts a file receive operation, that completes when data has been read from file / pipe.
void setOffset(uint64_t fileOffset)
Sets the offset in bytes at which start reading.
Definition: Async.h:781
uint64_t getOffset() const
The file/pipe descriptor handle to read data from.
Definition: Async.h:777
Completion data for AsyncFileWrite.
Definition: Async.h:820
Callback result for AsyncFileWrite.
Definition: Async.h:826
Starts a file write operation, writing bytes to a file (or pipe).
Definition: Async.h:815
uint64_t getOffset() const
The file/pipe descriptor to write data to.
Definition: Async.h:855
FileDescriptor::Handle fileDescriptor
The read-only span of memory where to read the data from.
Definition: Async.h:851
void setOffset(uint64_t fileOffset)
Sets the offset in bytes at which start writing.
Definition: Async.h:859
SC::Result start(AsyncEventLoop &eventLoop)
Starts a file write operation that completes when it's ready to receive more bytes.
Span< const char > buffer
Callback called when descriptor is ready to be written with more data.
Definition: Async.h:850
Allows user to supply a block of memory that will store kernel I/O events retrieved from AsyncEventLo...
Definition: Async.h:941
Span< uint8_t > eventsMemory
User supplied block of memory used to store kernel I/O events.
Definition: Async.h:942
Starts a Timeout that is invoked only once after expiration (relative) time has passed.
Definition: Async.h:323
SC::Result start(AsyncEventLoop &eventLoop, Time::Milliseconds relativeTimeout)
Starts a Timeout that is invoked (only once) after the specific relative expiration time has passed.
Function< void(Result &)> callback
Called after given expiration time since AsyncLoopTimeout::start has passed.
Definition: Async.h:345
Time::Milliseconds relativeTimeout
First timer expiration (relative) time in milliseconds.
Definition: Async.h:347
SC::Result start(AsyncEventLoop &eventLoop)
Starts a Timeout that is invoked (only once) after the specific relative expiration time has passed.
Starts a wake-up operation, allowing threads to execute callbacks on loop thread.
Definition: Async.h:369
SC::Result start(AsyncEventLoop &eventLoop, EventObject *eventObject=nullptr)
Starts a wake up request, that will be fulfilled when an external thread calls AsyncLoopWakeUp::wakeU...
Function< void(Result &)> callback
Callback called by SC::AsyncEventLoop::run after SC::AsyncLoopWakeUp::wakeUp.
Definition: Async.h:387
SC::Result wakeUp()
Wakes up event loop, scheduling AsyncLoopWakeUp::callback on next AsyncEventLoop::run (or its variati...
Executes work in a thread pool and then invokes a callback on the event loop thread.
Definition: Async.h:402
Function< void(Result &)> callback
Called to execute the work in a background threadpool thread.
Definition: Async.h:421
SC::Result setThreadPool(ThreadPool &threadPool)
Sets the ThreadPool that will supply the thread to run the async work on.
SC::Result start(AsyncEventLoop &eventLoop)
Schedule work to be executed on a background thread, notifying the event loop when it's finished.
Completion data for AsyncProcessExit.
Definition: Async.h:437
Callback result for AsyncProcessExit.
Definition: Async.h:443
Starts monitoring a process, notifying about its termination.
Definition: Async.h:432
SC::Result start(AsyncEventLoop &eventLoop, ProcessDescriptor::Handle process)
Starts monitoring a process, notifying about its termination.
Function< void(Result &)> callback
Called when process has exited.
Definition: Async.h:459
Base class for all async requests, holding state and type.
Definition: Async.h:132
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:173
AsyncEventLoop * getEventLoop() const
Get the event loop associated with this AsyncRequest.
Definition: Async.h:139
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:143
bool isFree() const
Returns true if this request is free.
Type getType() const
Returns request type.
Definition: Async.h:192
Type
Type of async request.
Definition: Async.h:155
@ 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.
Base class for all async results (argument of completion callbacks).
Definition: Async.h:238
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:250
AsyncResult(AsyncRequest &request)
Constructs an async result from a request.
Definition: Async.h:243
AsyncResult(AsyncRequest &request, SC::Result &&res)
Constructs an async result from a request and a result.
Definition: Async.h:240
Helper holding CompletionData for a specific AsyncRequest-derived class.
Definition: Async.h:268
Completion data for AsyncSocketAccept.
Definition: Async.h:487
Callback result for AsyncSocketAccept.
Definition: Async.h:493
Starts a socket accept operation, obtaining a new socket from a listening socket.
Definition: Async.h:482
Function< void(Result &)> callback
Called when a new socket has been accepted.
Definition: Async.h:510
SC::Result start(AsyncEventLoop &eventLoop, const SocketDescriptor &socketDescriptor)
Starts a socket accept operation, that returns a new socket connected to the given listening endpoint...
Starts a socket close operation.
Definition: Async.h:688
SC::Result start(AsyncEventLoop &eventLoop, const SocketDescriptor &socketDescriptor)
Starts a socket close operation.
int code
Return code of close socket operation.
Definition: Async.h:705
Function< void(Result &)> callback
Callback called after fully closing the socket.
Definition: Async.h:707
Starts a socket connect operation, connecting to a remote endpoint.
Definition: Async.h:536
Function< void(Result &)> callback
Called after socket is finally connected to endpoint.
Definition: Async.h:554
SC::Result start(AsyncEventLoop &eventLoop, const SocketDescriptor &socketDescriptor, SocketIPAddress ipAddress)
Starts a socket connect operation.
Completion data for AsyncSocketReceive.
Definition: Async.h:635
Callback result for AsyncSocketReceive.
Definition: Async.h:642
SC::Result get(Span< char > &outData)
Get a Span of the actually read data.
Definition: Async.h:648
Starts a socket receive operation, receiving bytes from a remote endpoint.
Definition: Async.h:630
SC::Result start(AsyncEventLoop &eventLoop)
Starts a socket receive operation.
SC::Result start(AsyncEventLoop &eventLoop, const SocketDescriptor &socketDescriptor, Span< char > data)
Starts a socket receive operation.
Span< char > buffer
The writeable span of memory where to data will be written.
Definition: Async.h:673
Function< void(Result &)> callback
Called after data has been received.
Definition: Async.h:671
Completion data for AsyncSocketSend.
Definition: Async.h:580
Starts a socket send operation, sending bytes to a remote endpoint.
Definition: Async.h:575
Function< void(Result &)> callback
Called when socket is ready to send more data.
Definition: Async.h:603
SC::Result start(AsyncEventLoop &eventLoop)
Starts a socket send operation.
Span< const char > buffer
Span of bytes to send.
Definition: Async.h:605
SocketDescriptor::Handle handle
The socket to send data to.
Definition: Async.h:606
SC::Result start(AsyncEventLoop &eventLoop, const SocketDescriptor &socketDescriptor, Span< const char > data)
Starts a socket send operation.
Holds (reference to) a SC::ThreadPool and SC::ThreadPool::Task to execute an SC::AsyncRequest in a ba...
Definition: Async.h:284
Create an async Callback result for a given AsyncRequest-derived class.
Definition: Async.h:308
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 containers).
Definition: FileDescriptor.h:52
Wraps function pointers, member functions and lambdas without ever allocating.
Definition: Function.h:50
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:24
A native OS thread.
Definition: Threading.h:118
Simple thread pool that executes tasks in a fixed number of worker threads.
Definition: ThreadPool.h:41
A small task containing a function to execute that can be queued in the thread pool.
Definition: ThreadPool.h:19
An high resolution time counter.
Definition: Time.h:171
Type-safe wrapper of uint64 used to represent milliseconds.
Definition: Time.h:42