Socket state improvements
This commit is contained in:
parent
11405ebff5
commit
e5f8a08238
@ -6,7 +6,6 @@ target_sources(
|
|||||||
PUBLIC
|
PUBLIC
|
||||||
FILE_SET cxx_modules TYPE CXX_MODULES FILES
|
FILE_SET cxx_modules TYPE CXX_MODULES FILES
|
||||||
src/common.cppm
|
src/common.cppm
|
||||||
src/windows_binds.cppm
|
|
||||||
|
|
||||||
src/berkeley/context.cppm
|
src/berkeley/context.cppm
|
||||||
src/berkeley/internals.cppm
|
src/berkeley/internals.cppm
|
||||||
|
|||||||
@ -9,7 +9,7 @@ import :berkeley.internals;
|
|||||||
import :berkeley.address;
|
import :berkeley.address;
|
||||||
|
|
||||||
namespace LdH::Sockets::Berkeley {
|
namespace LdH::Sockets::Berkeley {
|
||||||
template<class ctx_t> requires BerkeleySocketsContext<ctx_t>
|
template<class ctx_t> requires BerkeleySocketsContext<ctx_t>
|
||||||
class _abstract_datagram_socket {
|
class _abstract_datagram_socket {
|
||||||
private:
|
private:
|
||||||
using _refcnt_t = signed long long;
|
using _refcnt_t = signed long long;
|
||||||
@ -20,41 +20,76 @@ template<class ctx_t> requires BerkeleySocketsContext<ctx_t>
|
|||||||
ctx_t::socket_t _value;
|
ctx_t::socket_t _value;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static constexpr _refcnt_t _refcnt_UNINITIALIZED = -0x0800'0000'0000'0000ll;
|
static constexpr _refcnt_t _refcnt_UNINITIALIZED = -0x4000'0000'0000'0000ll + 0;
|
||||||
static constexpr _refcnt_t _refcnt_MOVED = -0x0800'0000'0000'0001ll;
|
static constexpr _refcnt_t _refcnt_INITIALIZING = -0x4000'0000'0000'0000ll + 1;
|
||||||
static constexpr _refcnt_t _refcnt_CLOSED = -0x07FFF'FFFF'FFFF'FFFFll;
|
static constexpr _refcnt_t _refcnt_MOVING = -0x4000'0000'0000'0000ll + 2;
|
||||||
|
static constexpr _refcnt_t _refcnt_MOVED = -0x4000'0000'0000'0000ll + 3;
|
||||||
|
static constexpr _refcnt_t _refcnt_CLOSING = -0x4000'0000'0000'0000ll + 4;
|
||||||
|
static constexpr _refcnt_t _refcnt_CLOSED = -0x4000'0000'0000'0000ll + 5;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
explicit _abstract_datagram_socket(ctx_t::socket_t &&value) : _refcnt{0}, _value{std::move(value)} {
|
explicit _abstract_datagram_socket(ctx_t::socket_t &&value) : _refcnt{_refcnt_INITIALIZING}, _value{std::move(value)} {
|
||||||
|
this->_refcnt.store(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
_abstract_datagram_socket() : _refcnt{_refcnt_UNINITIALIZED}, _value{} {
|
_abstract_datagram_socket() : _refcnt{_refcnt_UNINITIALIZED}, _value{} {
|
||||||
};
|
};
|
||||||
|
|
||||||
_abstract_datagram_socket(_abstract_datagram_socket &&other) noexcept : _refcnt{other._refcnt.load()}, _value{std::move(other._value)} {
|
_abstract_datagram_socket(_abstract_datagram_socket &&other) noexcept : _abstract_datagram_socket{} {
|
||||||
|
this->operator=(std::move(other));
|
||||||
};
|
};
|
||||||
|
|
||||||
_abstract_datagram_socket &operator=(_abstract_datagram_socket &&other) noexcept {
|
_abstract_datagram_socket &operator=(_abstract_datagram_socket &&other) noexcept {
|
||||||
_refcnt_t current = other->_refcnt.load();
|
_refcnt_t other_state = other->_refcnt.load();
|
||||||
while (true) {
|
while (true) {
|
||||||
if (current > 0)
|
switch (other_state) {
|
||||||
|
case _refcnt_UNINITIALIZED:
|
||||||
|
case _refcnt_MOVED:
|
||||||
|
case _refcnt_CLOSED:
|
||||||
|
case 0:
|
||||||
|
break;
|
||||||
|
case _refcnt_INITIALIZING:
|
||||||
|
case _refcnt_MOVING:
|
||||||
|
case _refcnt_CLOSING:
|
||||||
LdH::abort("Can't move socket while it is in use");
|
LdH::abort("Can't move socket while it is in use");
|
||||||
if (this->_refcnt.compare_exchange_weak(current, _refcnt_MOVED))
|
default:
|
||||||
|
if (other_state > 0)
|
||||||
|
LdH::abort("Can't move socket while it is in use");
|
||||||
|
else if (other_state < 0)
|
||||||
|
LdH::abort("Source socket wrapper corrupted");
|
||||||
|
}
|
||||||
|
if (this->_refcnt.compare_exchange_weak(other_state, _refcnt_MOVING))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
current = this->_refcnt.load();
|
_refcnt_t this_state = this->_refcnt.load();
|
||||||
while (true) {
|
while (true) {
|
||||||
if (current >= 0) {
|
switch (this_state) {
|
||||||
other._refcnt.store(0); // rollback
|
case _refcnt_UNINITIALIZED:
|
||||||
|
case _refcnt_MOVED:
|
||||||
|
case _refcnt_CLOSED:
|
||||||
|
case 0:
|
||||||
|
break;
|
||||||
|
case _refcnt_INITIALIZING:
|
||||||
|
case _refcnt_MOVING:
|
||||||
|
case _refcnt_CLOSING:
|
||||||
|
goto ALREADY_INITIALIZED;
|
||||||
|
default:
|
||||||
|
if (this_state > 0) {
|
||||||
|
ALREADY_INITIALIZED:
|
||||||
|
other._refcnt.store(other_state); // rollback
|
||||||
LdH::abort("Variable already initialized");
|
LdH::abort("Variable already initialized");
|
||||||
|
} else if (this_state < 0)
|
||||||
|
LdH::abort("Destination socket wrapper corrupted");
|
||||||
}
|
}
|
||||||
if (this->_refcnt.compare_exchange_weak(current, 0))
|
if (this->_refcnt.compare_exchange_weak(this_state, 0))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
this->_value = std::move(other._value);
|
this->_value = std::move(other._value);
|
||||||
|
this->_refcnt.store(0);
|
||||||
|
other._refcnt.store(_refcnt_MOVED);
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
@ -66,9 +101,12 @@ template<class ctx_t> requires BerkeleySocketsContext<ctx_t>
|
|||||||
if (current < 0) {
|
if (current < 0) {
|
||||||
switch (current) {
|
switch (current) {
|
||||||
case _refcnt_UNINITIALIZED:
|
case _refcnt_UNINITIALIZED:
|
||||||
|
case _refcnt_INITIALIZING:
|
||||||
LdH::abort("Socket not initialized");
|
LdH::abort("Socket not initialized");
|
||||||
case _refcnt_MOVED:
|
case _refcnt_MOVED:
|
||||||
|
case _refcnt_MOVING:
|
||||||
LdH::abort("Socket was moved to another location");
|
LdH::abort("Socket was moved to another location");
|
||||||
|
case _refcnt_CLOSING:
|
||||||
case _refcnt_CLOSED:
|
case _refcnt_CLOSED:
|
||||||
LdH::abort("Socket was closed");
|
LdH::abort("Socket was closed");
|
||||||
default:
|
default:
|
||||||
@ -86,10 +124,13 @@ template<class ctx_t> requires BerkeleySocketsContext<ctx_t>
|
|||||||
if (current < 0) {
|
if (current < 0) {
|
||||||
switch (current) {
|
switch (current) {
|
||||||
case _refcnt_UNINITIALIZED:
|
case _refcnt_UNINITIALIZED:
|
||||||
|
case _refcnt_INITIALIZING:
|
||||||
LdH::abort("Socket not initialized");
|
LdH::abort("Socket not initialized");
|
||||||
case _refcnt_MOVED:
|
case _refcnt_MOVED:
|
||||||
|
case _refcnt_MOVING:
|
||||||
LdH::abort("Socket was moved to another location");
|
LdH::abort("Socket was moved to another location");
|
||||||
case _refcnt_CLOSED:
|
case _refcnt_CLOSED:
|
||||||
|
case _refcnt_CLOSING:
|
||||||
LdH::abort("Socket was closed");
|
LdH::abort("Socket was closed");
|
||||||
default:
|
default:
|
||||||
LdH::abort("Socket wrapper corrupted");
|
LdH::abort("Socket wrapper corrupted");
|
||||||
@ -107,10 +148,13 @@ template<class ctx_t> requires BerkeleySocketsContext<ctx_t>
|
|||||||
if (current != 0) {
|
if (current != 0) {
|
||||||
switch (current) {
|
switch (current) {
|
||||||
case _refcnt_UNINITIALIZED:
|
case _refcnt_UNINITIALIZED:
|
||||||
|
case _refcnt_INITIALIZING:
|
||||||
LdH::abort("Socket not initialized");
|
LdH::abort("Socket not initialized");
|
||||||
case _refcnt_MOVED:
|
case _refcnt_MOVED:
|
||||||
|
case _refcnt_MOVING:
|
||||||
LdH::abort("Socket was moved to another location");
|
LdH::abort("Socket was moved to another location");
|
||||||
case _refcnt_CLOSED:
|
case _refcnt_CLOSED:
|
||||||
|
case _refcnt_CLOSING:
|
||||||
LdH::abort("Socket was already closed");
|
LdH::abort("Socket was already closed");
|
||||||
default:
|
default:
|
||||||
if (current > 0)
|
if (current > 0)
|
||||||
|
|||||||
@ -9,66 +9,93 @@ import :berkeley.internals;
|
|||||||
import :berkeley.address;
|
import :berkeley.address;
|
||||||
|
|
||||||
namespace LdH::Sockets::Berkeley {
|
namespace LdH::Sockets::Berkeley {
|
||||||
enum _socket_state_t {
|
template<class ctx_t> requires BerkeleySocketsContext<ctx_t>
|
||||||
|
class _stream_socket_commons {
|
||||||
|
private:
|
||||||
|
enum _state_t {
|
||||||
_socket_state_UNINITIALIZED,
|
_socket_state_UNINITIALIZED,
|
||||||
|
_socket_state_INITIALIZING,
|
||||||
|
_socket_state_MOVING,
|
||||||
_socket_state_MOVED,
|
_socket_state_MOVED,
|
||||||
_socket_state_AVAILABLE,
|
_socket_state_AVAILABLE,
|
||||||
_socket_state_READING,
|
_socket_state_READING,
|
||||||
_socket_state_WRITING,
|
_socket_state_WRITING,
|
||||||
_socket_state_BOTH,
|
_socket_state_BOTH,
|
||||||
|
_socket_state_CLOSING,
|
||||||
_socket_state_CLOSED,
|
_socket_state_CLOSED,
|
||||||
};
|
};
|
||||||
|
|
||||||
template<class ctx_t> requires BerkeleySocketsContext<ctx_t>
|
|
||||||
class _berkeley_socket_commons {
|
std::atomic<_state_t> _state;
|
||||||
private:
|
|
||||||
std::atomic<_socket_state_t> _state;
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
ctx_t::socket_t _value;
|
ctx_t::socket_t _value;
|
||||||
|
|
||||||
explicit _berkeley_socket_commons(ctx_t::socket_t &&value) : _state{_socket_state_AVAILABLE}, _value{std::move(value)} {
|
explicit _stream_socket_commons(ctx_t::socket_t &&value) : _state{_socket_state_INITIALIZING}, _value{std::move(value)} {
|
||||||
|
this->_state.store(_socket_state_AVAILABLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
_berkeley_socket_commons() : _state{_socket_state_UNINITIALIZED}, _value{} {
|
_stream_socket_commons() : _state{_socket_state_UNINITIALIZED}, _value{} {
|
||||||
};
|
};
|
||||||
|
|
||||||
explicit _berkeley_socket_commons(_berkeley_socket_commons &&other) noexcept : _state{other._state.load()}, _value{std::move(other._value)} {
|
explicit _stream_socket_commons(_stream_socket_commons &&other) noexcept : _stream_socket_commons{} {
|
||||||
other._state.store(_socket_state_MOVED);
|
this->operator=(std::move(other));
|
||||||
}
|
}
|
||||||
|
|
||||||
_berkeley_socket_commons &operator=(_berkeley_socket_commons &&other) noexcept {
|
_stream_socket_commons &operator=(_stream_socket_commons &&other) noexcept {
|
||||||
_socket_state_t current = this->_state.load();
|
_state_t other_state = other._state.load();
|
||||||
while (true) {
|
while (true) {
|
||||||
switch (current) {
|
switch (other_state) {
|
||||||
|
case _socket_state_READING:
|
||||||
|
case _socket_state_WRITING:
|
||||||
|
case _socket_state_BOTH:
|
||||||
|
case _socket_state_INITIALIZING:
|
||||||
|
case _socket_state_MOVING:
|
||||||
|
case _socket_state_CLOSING:
|
||||||
|
LdH::abort("Can't move socket while it is in use");
|
||||||
|
default:
|
||||||
|
if (this->_state.compare_exchange_weak(other_state, _socket_state_MOVING))
|
||||||
|
goto CHECK_THIS_STATE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CHECK_THIS_STATE:
|
||||||
|
_state_t this_state = this->_state.load();
|
||||||
|
while (true) {
|
||||||
|
switch (this_state) {
|
||||||
case _socket_state_UNINITIALIZED:
|
case _socket_state_UNINITIALIZED:
|
||||||
case _socket_state_MOVED:
|
case _socket_state_MOVED:
|
||||||
case _socket_state_CLOSED:
|
case _socket_state_CLOSED:
|
||||||
if (this->_state.compare_exchange_weak(current, _socket_state_AVAILABLE))
|
case _socket_state_INITIALIZING:
|
||||||
goto DONE;
|
case _socket_state_MOVING:
|
||||||
|
case _socket_state_CLOSING:
|
||||||
|
if (this->_state.compare_exchange_weak(this_state, _socket_state_INITIALIZING))
|
||||||
|
goto DO_MOVE;
|
||||||
continue;
|
continue;
|
||||||
default:
|
default:
|
||||||
|
other._state.store(other_state); // rollback
|
||||||
LdH::abort("Variable already initialized");
|
LdH::abort("Variable already initialized");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DONE:
|
DO_MOVE:
|
||||||
this->_state.store(other._state.exchange(_socket_state_MOVED));
|
|
||||||
this->_value = std::move(other._value);
|
this->_value = std::move(other._value);
|
||||||
|
this->_state.store(_socket_state_AVAILABLE);
|
||||||
|
other._state.store(_socket_state_MOVED);
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
_socket_state_t _cas_state(_socket_state_t expected, _socket_state_t next) {
|
_state_t _cas_state(_state_t expected, _state_t next) {
|
||||||
this->_state.compare_exchange_strong(expected, next);
|
this->_state.compare_exchange_strong(expected, next);
|
||||||
return expected;
|
return expected;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<_socket_state_t exp1, _socket_state_t next1, _socket_state_t exp2, _socket_state_t next2>
|
template<_state_t exp1, _state_t next1, _state_t exp2, _state_t next2>
|
||||||
_socket_state_t _cas_state_2() {
|
_state_t _cas_state_2() {
|
||||||
_socket_state_t current = this->_state.load();
|
_state_t current = this->_state.load();
|
||||||
while (true) {
|
while (true) {
|
||||||
switch (current) {
|
switch (current) {
|
||||||
case exp1:
|
case exp1:
|
||||||
@ -89,7 +116,9 @@ namespace LdH::Sockets::Berkeley {
|
|||||||
void _start_reading(char const *busy_msg) {
|
void _start_reading(char const *busy_msg) {
|
||||||
switch (this->_cas_state_2<_socket_state_AVAILABLE, _socket_state_READING, _socket_state_WRITING, _socket_state_BOTH>()) {
|
switch (this->_cas_state_2<_socket_state_AVAILABLE, _socket_state_READING, _socket_state_WRITING, _socket_state_BOTH>()) {
|
||||||
case _socket_state_UNINITIALIZED:
|
case _socket_state_UNINITIALIZED:
|
||||||
|
case _socket_state_INITIALIZING:
|
||||||
LdH::abort("Socket not initialized");
|
LdH::abort("Socket not initialized");
|
||||||
|
case _socket_state_MOVING:
|
||||||
case _socket_state_MOVED:
|
case _socket_state_MOVED:
|
||||||
LdH::abort("Socket was moved to another location");
|
LdH::abort("Socket was moved to another location");
|
||||||
case _socket_state_AVAILABLE:
|
case _socket_state_AVAILABLE:
|
||||||
@ -99,6 +128,7 @@ namespace LdH::Sockets::Berkeley {
|
|||||||
case _socket_state_BOTH:
|
case _socket_state_BOTH:
|
||||||
LdH::abort(busy_msg);
|
LdH::abort(busy_msg);
|
||||||
case _socket_state_CLOSED:
|
case _socket_state_CLOSED:
|
||||||
|
case _socket_state_CLOSING:
|
||||||
LdH::abort("Socket was closed");
|
LdH::abort("Socket was closed");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -110,8 +140,10 @@ namespace LdH::Sockets::Berkeley {
|
|||||||
void _start_writing(char const *busy_msg) {
|
void _start_writing(char const *busy_msg) {
|
||||||
switch (this->_cas_state_2<_socket_state_AVAILABLE, _socket_state_WRITING, _socket_state_READING, _socket_state_BOTH>()) {
|
switch (this->_cas_state_2<_socket_state_AVAILABLE, _socket_state_WRITING, _socket_state_READING, _socket_state_BOTH>()) {
|
||||||
case _socket_state_UNINITIALIZED:
|
case _socket_state_UNINITIALIZED:
|
||||||
|
case _socket_state_INITIALIZING:
|
||||||
LdH::abort("Socket not initialized");
|
LdH::abort("Socket not initialized");
|
||||||
case _socket_state_MOVED:
|
case _socket_state_MOVED:
|
||||||
|
case _socket_state_MOVING:
|
||||||
LdH::abort("Socket was moved to another location");
|
LdH::abort("Socket was moved to another location");
|
||||||
case _socket_state_AVAILABLE:
|
case _socket_state_AVAILABLE:
|
||||||
case _socket_state_READING:
|
case _socket_state_READING:
|
||||||
@ -120,6 +152,7 @@ namespace LdH::Sockets::Berkeley {
|
|||||||
case _socket_state_BOTH:
|
case _socket_state_BOTH:
|
||||||
LdH::abort(busy_msg);
|
LdH::abort(busy_msg);
|
||||||
case _socket_state_CLOSED:
|
case _socket_state_CLOSED:
|
||||||
|
case _socket_state_CLOSING:
|
||||||
LdH::abort("Socket was closed");
|
LdH::abort("Socket was closed");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -129,10 +162,12 @@ namespace LdH::Sockets::Berkeley {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void _close(char const *busy_msg) {
|
void _close(char const *busy_msg) {
|
||||||
switch (this->_cas_state(_socket_state_AVAILABLE, _socket_state_CLOSED)) {
|
switch (this->_cas_state(_socket_state_AVAILABLE, _socket_state_CLOSING)) {
|
||||||
case _socket_state_UNINITIALIZED:
|
case _socket_state_UNINITIALIZED:
|
||||||
|
case _socket_state_INITIALIZING:
|
||||||
LdH::abort("Socket not initialized");
|
LdH::abort("Socket not initialized");
|
||||||
case _socket_state_MOVED:
|
case _socket_state_MOVED:
|
||||||
|
case _socket_state_MOVING:
|
||||||
LdH::abort("Socket was moved to another location");
|
LdH::abort("Socket was moved to another location");
|
||||||
case _socket_state_AVAILABLE:
|
case _socket_state_AVAILABLE:
|
||||||
break;
|
break;
|
||||||
@ -140,11 +175,13 @@ namespace LdH::Sockets::Berkeley {
|
|||||||
case _socket_state_WRITING:
|
case _socket_state_WRITING:
|
||||||
case _socket_state_BOTH:
|
case _socket_state_BOTH:
|
||||||
LdH::abort(busy_msg);
|
LdH::abort(busy_msg);
|
||||||
|
case _socket_state_CLOSING:
|
||||||
case _socket_state_CLOSED:
|
case _socket_state_CLOSED:
|
||||||
LdH::abort("Socket already was closed");
|
LdH::abort("Socket already was closed");
|
||||||
}
|
}
|
||||||
|
|
||||||
this->_value.close();
|
this->_value.close();
|
||||||
|
this->_state.store(_socket_state_CLOSED);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -155,17 +192,11 @@ namespace LdH::Sockets::Berkeley {
|
|||||||
|
|
||||||
export
|
export
|
||||||
template<class ctx_t> requires BerkeleySocketsContext<ctx_t>
|
template<class ctx_t> requires BerkeleySocketsContext<ctx_t>
|
||||||
class StreamSocket : public _berkeley_socket_commons<ctx_t>, public virtual LdH::Streams::InputStream, public virtual LdH::Streams::OutputStream {
|
class StreamSocket : public _stream_socket_commons<ctx_t>, public virtual LdH::Streams::InputStream, public virtual LdH::Streams::OutputStream {
|
||||||
private:
|
private:
|
||||||
explicit StreamSocket(ctx_t::socket_t &&value) : _berkeley_socket_commons<ctx_t>{std::move(value)} {
|
explicit StreamSocket(ctx_t::socket_t &&value) : _stream_socket_commons<ctx_t>{std::move(value)} {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template<class ctx_t2> requires BerkeleySocketsContext<ctx_t2>
|
|
||||||
friend
|
|
||||||
class StreamSocketsServer;
|
|
||||||
|
|
||||||
|
|
||||||
template<class>
|
template<class>
|
||||||
friend
|
friend
|
||||||
class _socket_internals;
|
class _socket_internals;
|
||||||
@ -205,22 +236,10 @@ namespace LdH::Sockets::Berkeley {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
export
|
|
||||||
template<class ctx_t, class sock_t>
|
|
||||||
class SocketWithAddress {
|
|
||||||
public:
|
|
||||||
Address<ctx_t> addr;
|
|
||||||
sock_t sock;
|
|
||||||
|
|
||||||
SocketWithAddress(Address<ctx_t> addr, sock_t &&sock) : addr{addr}, sock{std::move(sock)} {
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<class ctx_t> requires BerkeleySocketsContext<ctx_t>
|
template<class ctx_t> requires BerkeleySocketsContext<ctx_t>
|
||||||
class StreamSocketsServer : public _berkeley_socket_commons<ctx_t> {
|
class StreamSocketsServer : public _stream_socket_commons<ctx_t> {
|
||||||
private:
|
private:
|
||||||
explicit StreamSocketsServer(ctx_t::socket_t &&value) : _berkeley_socket_commons<ctx_t>{std::move(value)} {
|
explicit StreamSocketsServer(ctx_t::socket_t &&value) : _stream_socket_commons<ctx_t>{std::move(value)} {
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class>
|
template<class>
|
||||||
@ -235,13 +254,15 @@ namespace LdH::Sockets::Berkeley {
|
|||||||
StreamSocketsServer &operator=(StreamSocketsServer &&other) noexcept = default;
|
StreamSocketsServer &operator=(StreamSocketsServer &&other) noexcept = default;
|
||||||
|
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
SocketWithAddress<ctx_t, StreamSocket<ctx_t> > wait_for_connection() {
|
StreamSocket<ctx_t> wait_for_connection(Address<ctx_t> *addr) {
|
||||||
this->_start_reading("Socket already waiting for connections");
|
this->_start_reading("Socket already waiting for connections");
|
||||||
|
|
||||||
typename ctx_t::address_t addr{};
|
typename ctx_t::address_t addr_raw{};
|
||||||
typename ctx_t::socket_t raw = this->_value.accept(&addr);
|
typename ctx_t::socket_t raw = this->_value.accept(&addr_raw);
|
||||||
this->_finish_reading();
|
this->_finish_reading();
|
||||||
return SocketWithAddress<ctx_t, StreamSocket<ctx_t> >{_addr_internals<ctx_t>::wrap(addr), _socket_internals<StreamSocket<ctx_t> >::wrap(std::move(raw))};
|
|
||||||
|
*addr = std::move(_addr_internals<ctx_t>::wrap(addr_raw));
|
||||||
|
return _socket_internals<StreamSocket<ctx_t> >::wrap(std::move(raw));
|
||||||
}
|
}
|
||||||
|
|
||||||
void close() {
|
void close() {
|
||||||
|
|||||||
@ -197,10 +197,6 @@ namespace LdH::Sockets {
|
|||||||
|
|
||||||
export using Address = Berkeley::Address<_WinsockContext>;
|
export using Address = Berkeley::Address<_WinsockContext>;
|
||||||
|
|
||||||
export
|
|
||||||
template<class sock_t>
|
|
||||||
using SocketWithAddress = Berkeley::SocketWithAddress<_WinsockContext, sock_t>;
|
|
||||||
|
|
||||||
export using StreamSocket = Berkeley::StreamSocket<_WinsockContext>;
|
export using StreamSocket = Berkeley::StreamSocket<_WinsockContext>;
|
||||||
|
|
||||||
export using StreamSocketsServer = Berkeley::StreamSocketsServer<_WinsockContext>;
|
export using StreamSocketsServer = Berkeley::StreamSocketsServer<_WinsockContext>;
|
||||||
|
|||||||
@ -1,13 +0,0 @@
|
|||||||
module;
|
|
||||||
|
|
||||||
#include <Winsock2.h>
|
|
||||||
#include <ws2tcpip.h>
|
|
||||||
#include <Windows.h>
|
|
||||||
|
|
||||||
export module ru.landgrafhomyak.BGTU.networks_1.sockets:binds;
|
|
||||||
|
|
||||||
namespace LdH::Sockets::_Binds {
|
|
||||||
export using ::sockaddr_in;
|
|
||||||
export using ::sockaddr_in6;
|
|
||||||
export using ::SOCKET;
|
|
||||||
}
|
|
||||||
@ -4,5 +4,5 @@ import std;
|
|||||||
namespace LdH {
|
namespace LdH {
|
||||||
export
|
export
|
||||||
template<class lambda_t>
|
template<class lambda_t>
|
||||||
concept ThreadRoutine = std::invocable<lambda_t> && std::same_as<std::invoke_result_t<lambda_t>, void> /*&& std::movable<lambda_t>*/ && std::destructible<lambda_t>;
|
concept ThreadRoutine = std::invocable<lambda_t> && std::same_as<std::invoke_result_t<lambda_t>, void> && std::move_constructible<lambda_t> && std::destructible<lambda_t>;
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user