25#ifndef JOIN_CORE_ASYNC_SOCKET_HPP
26#define JOIN_CORE_ASYNC_SOCKET_HPP
37#include <system_error>
44#include <sys/socket.h>
52 template <
class Protocol,
class Proactor,
size_t OpCount>
53 class BasicAsyncSocket :
public CompletionHandler
56 using Socket =
typename Protocol::Socket;
64 static_assert (OpCount > 0,
"a socket needs at least one operation slot");
107 _arena = std::move (other._arena);
109 for (
size_t i = 0; i < other._ops.size (); ++i)
111 _ops[i].store (other._ops[i].exchange (
nullptr, std::memory_order_acq_rel), std::memory_order_release);
114 _socket = std::move (other._socket);
138 _arena = std::move (other._arena);
140 for (
size_t i = 0; i < other._ops.size (); ++i)
142 _ops[i].store (other._ops[i].exchange (
nullptr, std::memory_order_acq_rel), std::memory_order_release);
145 _socket = std::move (other._socket);
193 template <
size_t Count,
size_t Size>
252 return static_cast<ssize_t
> (index);
298 return static_cast<ssize_t
> (index);
314 return cancelOp (
_ops[index].load (std::memory_order_acquire));
317#ifdef JOIN_HAS_IO_URING
322 int flush () noexcept
332 template <
size_t Count,
size_t... Sizes>
335 return _proactor->registerFixedBuffers (arena);
342 int unregisterFixedBuffers () noexcept
344 return _proactor->unregisterFixedBuffers ();
354 return _socket.localEndpoint ();
410 std::error_code code =
411 (result < 0) ? std::error_code (-result, std::generic_category ()) : std::error_code ();
413 dispatch (op, code, (result > 0) ?
static_cast<size_t> (result) : 0);
445 std::error_code result = code;
449 bool ready = (revents & wait->op.data.poll.events) != 0;
454 socklen_t len =
sizeof (err);
455 ::getsockopt (
_socket.handle (), SOL_SOCKET, SO_ERROR, &err, &len);
459 result = std::error_code (err, std::generic_category ());
472 if (wait->op.more && !result && !(revents & POLLHUP))
476 wait->waitHandler (result,
true);
482 WaitHandler handler = std::move (wait->waitHandler);
495 handler (result,
false);
506 static_assert (
sizeof (Op) <=
_opSize,
"operation larger than an arena slot");
514 Op* operation =
new (chunk) Op ();
537 for (
auto& slot :
_ops)
548 for (
auto& slot :
_ops)
559 for (
auto& slot :
_ops)
561 cancelOp (slot.load (std::memory_order_acquire));
571 for (
auto& slot :
_ops)
573 IoOperation* op = slot.load (std::memory_order_acquire);
574 if ((op !=
nullptr) &&
pending (*op))
590 if ((op ==
nullptr) || !
inFlight (*op))
adaptive backoff strategy for busy-wait loops.
Definition backoff.hpp:43
memory arena owning backend and managing one or more pools.
Definition memory.hpp:53
uint32_t getIndex(void *p) const noexcept
get the index of a chunk in the pool.
Definition allocator.hpp:498
void * allocate(size_t size) noexcept
allocate memory from the first pool that fits (promotes if exhausted).
Definition allocator.hpp:455
void deallocate(void *p) noexcept
return memory to the appropriate pool.
Definition allocator.hpp:474
basic asynchronous socket class.
Definition protocol.hpp:82
ssize_t asyncWaitMulti(bool wantRead, bool wantWrite, WaitHandler handler, bool flush=true) noexcept
start an asynchronous multishot wait, staying armed until cancelled or failed.
Definition async_socket.hpp:263
Socket _socket
underlying synchronous socket.
Definition async_socket.hpp:629
bool pending(const IoOperation &op) const noexcept
check if an operation is in flight or completing.
Definition async_socket.hpp:618
bool pendingAny() const noexcept
check if at least one operation is in flight or completing.
Definition async_socket.hpp:569
void close() noexcept
close the socket, cancelling the operations in flight.
Definition async_socket.hpp:171
~BasicAsyncSocket()
destroy the socket instance.
Definition async_socket.hpp:153
static constexpr size_t _opSize
size of an operation slot.
Definition async_socket.hpp:67
int registerBufferRing(uint16_t group, LocalMem::Allocator< Count, Size > &arena)
register a provided buffer ring on the proactor driving this socket.
Definition async_socket.hpp:194
void cancelAll() noexcept
cancel every operation in flight.
Definition async_socket.hpp:557
virtual void dispatch(IoOperation &op, const std::error_code &code, size_t size) noexcept
invoke the completion handler of the given operation, then release it.
Definition async_socket.hpp:432
void releaseOp(Op *operation) noexcept
return an operation to the arena.
Definition async_socket.hpp:525
ssize_t asyncWait(bool wantRead, bool wantWrite, WaitHandler handler, bool flush=true) noexcept
start an asynchronous wait for the socket to become ready in one direction.
Definition async_socket.hpp:217
void onCancel(IoOperation &op, int result) override
method called when an operation is cancelled.
Definition async_socket.hpp:421
Endpoint localEndpoint() const noexcept
determine the local endpoint associated with this socket.
Definition async_socket.hpp:352
bool opened() const noexcept
check if the socket is opened.
Definition async_socket.hpp:361
int protocol() const noexcept
get socket protocol.
Definition async_socket.hpp:388
typename Protocol::Endpoint Endpoint
Definition async_socket.hpp:57
int cancelOp(IoOperation *op) noexcept
cancel the given operation, if in flight.
Definition async_socket.hpp:588
OpArena _arena
operations arena.
Definition async_socket.hpp:632
typename Protocol::Socket Socket
Definition async_socket.hpp:56
static constexpr size_t _opCount
number of operations in flight.
Definition async_socket.hpp:62
int unregisterBufferRing(uint16_t group)
unregister a provided buffer ring from the proactor driving this socket.
Definition async_socket.hpp:204
Op * allocateOp() noexcept
allocate an operation in the arena.
Definition async_socket.hpp:504
int handle() const noexcept
get socket native handle.
Definition async_socket.hpp:397
BasicAsyncSocket(BasicAsyncSocket &&other) noexcept
move constructor.
Definition async_socket.hpp:102
bool inFlight(const IoOperation &op) const noexcept
check if an operation is in flight.
Definition async_socket.hpp:608
BasicAsyncSocket(Socket &&sock, Proactor &proactor=ProactorThread::proactor())
create the socket instance adopting an already opened socket.
Definition async_socket.hpp:86
int type() const noexcept
get the protocol communication semantic.
Definition async_socket.hpp:379
void suspendAll() noexcept
suspend every operation in flight.
Definition async_socket.hpp:535
BasicAsyncSocket & operator=(const BasicAsyncSocket &other)=delete
copy assignment operator.
int cancel(size_t index) noexcept
cancel the operation stored at the given index, if in flight.
Definition async_socket.hpp:306
int family() const noexcept
get address family.
Definition async_socket.hpp:370
typename AsyncWait::Wait WaitHandler
Definition async_socket.hpp:59
std::array< std::atomic< IoOperation * >, _opCount > _ops
operations in flight.
Definition async_socket.hpp:635
BasicAsyncSocket(const BasicAsyncSocket &other)=delete
copy constructor.
Proactor * _proactor
proactor driving the operations.
Definition async_socket.hpp:626
int open(const Protocol &protocol=Protocol()) noexcept
open socket using the given protocol.
Definition async_socket.hpp:163
void resumeAll() noexcept
resume every suspended operation, redirecting it to this handler.
Definition async_socket.hpp:546
void completeWait(AsyncWait *wait, const std::error_code &code, size_t revents) noexcept
invoke the wait completion handler.
Definition async_socket.hpp:443
void onComplete(IoOperation &op, int result) override
method called when an operation completes.
Definition async_socket.hpp:408
BasicAsyncSocket(Proactor &proactor=ProactorThread::proactor())
create the socket instance.
Definition async_socket.hpp:76
static BasicProactor & proactor()
get the Proactor instance owned by the singleton ProactorThread.
Definition proactor.hpp:982
basic proactor class.
Definition proactor.hpp:156
int unregisterBufferRing(uint16_t group)
unregister a provided buffer ring.
Definition proactor_epoll_impl.hpp:154
void suspend(IoOperation *op) noexcept
suspend an I/O operation.
Definition proactor.hpp:799
int registerBufferRing(uint16_t group, LocalMem::Allocator< Count, Size > &arena)
register a provided buffer ring.
Definition proactor_epoll_impl.hpp:107
int submit(IoOperation &op, bool flush=false, bool sync=false) noexcept
submit an asynchronous operation to the proactor.
Definition proactor.hpp:655
bool isProactorThread() const noexcept
check if the calling thread is the proactor thread.
Definition proactor_epoll_impl.hpp:252
void resume(IoOperation *op, CompletionHandler *handler) noexcept
resume an I/O operation.
Definition proactor.hpp:837
int cancel(IoOperation &op, bool flush=false, bool sync=false) noexcept
cancel an in-flight operation.
Definition proactor.hpp:703
BasicArena< LocalMem, Count, Sizes... > Allocator
Definition memory.hpp:125
Definition acceptor.hpp:32
constexpr uint64_t nextPow2(uint64_t value) noexcept
round up to the next power of two.
Definition utils.hpp:506
std::error_code make_error_code(join::Errc code) noexcept
Create an std::error_code object.
Definition error.cpp:195
asynchronous operation traits.
Definition async_operation.hpp:147
asynchronous wait operation.
Definition async_operation.hpp:48
IoOperation op
operation submitted to the proactor.
Definition async_operation.hpp:53
Function< void(const std::error_code &, bool), 16 > Wait
handler invoked on completion.
Definition async_operation.hpp:50
Wait waitHandler
handler invoked on completion.
Definition async_operation.hpp:56
Describes a single asynchronous operation submitted to the Proactor.
Definition io_operation.hpp:47
static IoOperation makePollMulti(int fd, uint32_t events, CompletionHandler *handler) noexcept
build a multishot poll operation, staying armed until cancelled or failed.
Definition io_operation.cpp:87
State
operation lifecycle state.
Definition io_operation.hpp:52
std::atomic< State > state
operation state.
Definition io_operation.hpp:392
static IoOperation makePoll(int fd, uint32_t events, CompletionHandler *handler) noexcept
build a poll operation.
Definition io_operation.cpp:73
#define JOIN_LIKELY(x)
Definition utils.hpp:45
#define JOIN_UNLIKELY(x)
Definition utils.hpp:46