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 ProactorType,
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");
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);
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);
174 typename ProactorType::InvokeHandler fn = [
this, &pending] () {
193 while (!
_proactor->isProactorThread () && pending);
205 template <
size_t Count,
size_t Size>
208 return _proactor->registerBufferRing (group, arena);
218 return _proactor->unregisterBufferRing (group);
256 if (
_proactor->submit (wait->
op, flush,
false) == -1)
264 return static_cast<ssize_t
> (index);
302 if (
_proactor->submit (wait->
op, flush,
false) == -1)
310 return static_cast<ssize_t
> (index);
331#ifdef JOIN_HAS_IO_URING
336 int flush () noexcept
346 template <
size_t Count,
size_t... Sizes>
349 return _proactor->registerFixedBuffers (arena);
356 int unregisterFixedBuffers () noexcept
358 return _proactor->unregisterFixedBuffers ();
368 return _socket.localEndpoint ();
424 std::error_code code =
425 (result < 0) ? std::error_code (-result, std::generic_category ()) : std::error_code ();
427 dispatch (op, code, (result > 0) ?
static_cast<size_t> (result) : 0);
459 std::error_code result = code;
463 bool ready = (revents & wait->op.data.poll.events) != 0;
468 socklen_t len =
sizeof (err);
469 ::getsockopt (
_socket.handle (), SOL_SOCKET, SO_ERROR, &err, &len);
473 result = std::error_code (err, std::generic_category ());
486 if (wait->op.more && !result && !(revents & POLLHUP))
490 wait->waitHandler (result,
true);
496 WaitHandler handler = std::move (wait->waitHandler);
509 handler (result,
false);
520 static_assert (
sizeof (Op) <=
_opSize,
"operation larger than an allocator slot");
528 Op* operation =
new (chunk) Op;
545 _ops[index].store (
nullptr, std::memory_order_release);
553 for (
auto& slot :
_ops)
555 IoOperation* op = slot.load (std::memory_order_acquire);
568 for (
auto& slot :
_ops)
570 IoOperation* op = slot.load (std::memory_order_acquire);
583 for (
auto& slot :
_ops)
585 IoOperation* op = slot.load (std::memory_order_acquire);
599 for (
auto& slot :
_ops)
601 IoOperation* op = slot.load (std::memory_order_acquire);
602 if ((op !=
nullptr) &&
pending (*op))
623 if (
_proactor->cancel (op,
true,
true) == -1)
adaptive backoff for busy-wait loops, requires Rdtsc::calibrate ().
Definition backoff.hpp:47
basic asynchronous socket class.
Definition protocol.hpp:85
BasicAsyncSocket(const BasicAsyncSocket &other)=delete
copy constructor.
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:446
Socket _socket
underlying synchronous socket.
Definition async_socket.hpp:657
void completeWait(AsyncWait *wait, const std::error_code &code, size_t revents) noexcept
invoke the wait completion handler.
Definition async_socket.hpp:457
void close() noexcept
close the socket, cancelling the operations in flight.
Definition async_socket.hpp:171
int type() const noexcept
get the protocol communication semantic.
Definition async_socket.hpp:393
BasicAsyncSocket(ProactorType &proactor=ProactorThread::proactor())
create the socket instance.
Definition async_socket.hpp:76
std::array< std::atomic< IoOperation * >, _opCount > _ops
operations in flight.
Definition async_socket.hpp:663
void onCancel(IoOperation &op, int result) override
method called when an operation is cancelled.
Definition async_socket.hpp:435
BasicAsyncSocket(Socket &&sock, ProactorType &proactor=ProactorThread::proactor())
create the socket instance adopting an already opened socket.
Definition async_socket.hpp:86
typename AsyncWait::Wait WaitHandler
Definition async_socket.hpp:59
void releaseOperation(Op *operation) noexcept
return an operation to the allocator.
Definition async_socket.hpp:539
void onComplete(IoOperation &op, int result) override
method called when an operation completes.
Definition async_socket.hpp:422
int open(const Protocol &protocol=Protocol()) noexcept
open socket using the given protocol.
Definition async_socket.hpp:163
bool opened() const noexcept
check if the socket is opened.
Definition async_socket.hpp:375
int cancel(size_t index) noexcept
cancel the operation stored at the given index, if in flight.
Definition async_socket.hpp:318
bool pending(const IoOperation &op) const noexcept
check if an operation is in flight or completing.
Definition async_socket.hpp:646
int protocol() const noexcept
get socket protocol.
Definition async_socket.hpp:402
typename Protocol::Socket Socket
Definition async_socket.hpp:56
void resumeAll() noexcept
resume every suspended operation, redirecting it to this handler.
Definition async_socket.hpp:566
bool inFlight(const IoOperation &op) const noexcept
check if an operation is in flight.
Definition async_socket.hpp:636
~BasicAsyncSocket()
destroy the socket instance.
Definition async_socket.hpp:153
int family() const noexcept
get address family.
Definition async_socket.hpp:384
int unregisterBufferRing(uint16_t group)
unregister a provided buffer ring from the proactor driving this socket.
Definition async_socket.hpp:216
int handle() const noexcept
get socket native handle.
Definition async_socket.hpp:411
static constexpr size_t _opCount
number of operations in flight.
Definition async_socket.hpp:62
int cancelOperation(IoOperation &op) noexcept
cancel the given operation, if in flight.
Definition async_socket.hpp:616
BasicAsyncSocket & operator=(const BasicAsyncSocket &other)=delete
copy assignment operator.
Endpoint localEndpoint() const noexcept
determine the local endpoint associated with this socket.
Definition async_socket.hpp:366
BasicAsyncSocket(BasicAsyncSocket &&other) noexcept
move constructor.
Definition async_socket.hpp:102
typename Protocol::Endpoint Endpoint
Definition async_socket.hpp:57
int registerBufferRing(uint16_t group, LocalMem::SlabAllocator< Count, Size > &arena)
register a provided buffer ring on the proactor driving this socket.
Definition async_socket.hpp:206
static constexpr size_t _opSize
size of an operation slot.
Definition async_socket.hpp:67
Op * allocateOperation() noexcept
allocate an operation in the allocator.
Definition async_socket.hpp:518
void cancelAll() noexcept
cancel every operation in flight.
Definition async_socket.hpp:581
ssize_t asyncWait(WaitHandler handler, bool wantRead, bool wantWrite, bool flush=true) noexcept
start an asynchronous wait for the socket to become ready in one direction.
Definition async_socket.hpp:229
ProactorType * _proactor
proactor driving the operations.
Definition async_socket.hpp:654
bool pendingAny() const noexcept
check if at least one operation is in flight or completing.
Definition async_socket.hpp:597
OpAllocator _allocator
operations allocator.
Definition async_socket.hpp:660
ssize_t asyncWaitMulti(WaitHandler handler, bool wantRead, bool wantWrite, bool flush=true) noexcept
start an asynchronous multishot wait, staying armed until cancelled or failed.
Definition async_socket.hpp:275
void suspendAll() noexcept
suspend every operation in flight.
Definition async_socket.hpp:551
static BasicProactor & proactor()
get the Proactor instance owned by the singleton ProactorThread.
Definition proactor.hpp:1053
slab allocator owning a backend and managing one or more pools.
Definition slab_allocator.hpp:339
uint32_t getIndex(void *p) const noexcept
get the index of a chunk in the pool.
Definition slab_allocator.hpp:455
void * allocate(size_t size) noexcept
allocate memory from the first pool that fits (promotes if exhausted).
Definition slab_allocator.hpp:402
void deallocate(void *p) noexcept
return memory to the appropriate pool.
Definition slab_allocator.hpp:421
BasicSlabAllocator< LocalMem, Count, Sizes... > SlabAllocator
Definition memory.hpp:327
Definition acceptor.hpp:32
constexpr uint64_t nextPow2(uint64_t value) noexcept
round up to the next power of two.
Definition utils.hpp:475
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:149
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:48
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:95
State
operation lifecycle state.
Definition io_operation.hpp:53
std::atomic< State > state
operation state.
Definition io_operation.hpp:404
static IoOperation makePoll(int fd, uint32_t events, CompletionHandler *handler) noexcept
build a poll operation.
Definition io_operation.cpp:81
#define JOIN_LIKELY(x)
Definition utils.hpp:50
#define JOIN_UNLIKELY(x)
Definition utils.hpp:51