simpler emitter, better compile-time

This commit is contained in:
Michele Caini 2022-04-03 00:15:24 +02:00
parent ba337a7104
commit 3d3790c06c
12 changed files with 107 additions and 332 deletions

View File

@ -329,10 +329,10 @@ No need to keep track of them.
## The event-based approach
`uvw` offers an event-based approach, so resources are small event emitters
to which listeners can be attached.<br/>
Attaching a listener to a resource is the recommended way to be notified about
changes.<br/>
`uvw` offers an event-based approach where resources are small event emitters to
which listeners are attached.<br/>
Attaching listeners to resources is the recommended way to receive notifications
about their operations.<br/>
Listeners are callable objects of type `void(event_type &, resource_type &)`,
where:
@ -346,24 +346,18 @@ It means that the following function types are all valid:
* `void(event_type &, const resource_type &)`
* `void(const event_type &, const resource_type &)`
Please note that there is no need to keep around references to the resources:
they will pass themselves as an argument whenever an event is published.
Please note that there is no need to keep around references to the resources,
since they pass themselves as an argument whenever an event is published.<br/>
The `on` member function is the way to go to register long-running listeners:
There exist two methods to attach a listener to a resource:
```cpp
resource.on<event_type>(listener)
```
* `resource.once<event_type>(listener)`: the listener will be automatically
removed after the first event of the given type.
* `resource.on<event_type>(listener)`: to be used for long-running listeners.
Both of them return an object of type `resource_type::connection` (as an
example, `tcp_handle::connection`).<br/>
A connection object can be used later as an argument to the `erase` member
function of the resource to remove the listener.<br/>
There exists also the `clear` member function to drop all the listeners at once.
Note that `clear` should only be invoked on non-active handles. The handles
exploit the same event mechanism made available to users to satisfy pending
requests. Invoking `clear` on an active handle, for example with requests still
in progress, risks leading to memory leaks or unexpected behavior.
To know if a listener exists for a given type, the class offers a `has` function
template. Similarly, the `reset` function template is be used to reset and thus
disconnect listeners, if any. A non-template version of `reset` also exists to
clear an emitter as a whole.
Almost all the resources emit `error_event` in case of errors.<br/>
All the other events are specific for the given resource and documented in the
@ -379,7 +373,7 @@ tcp->on<uvw::error_event>([](const uvw::error_event &, uvw::tcp_handle &) { /* s
tcp->on<uvw::listen_event>([](const uvw::listen_event &, uvw::tcp_handle &srv) {
std::shared_ptr<uvw::tcp_handle> client = srv.parent().resource<uvw::tcp_handle>();
client->once<uvw::end_event>([](const uvw::end_event &, uvw::tcp_handle &client) { client.close(); });
client->on<uvw::end_event>([](const uvw::end_event &, uvw::tcp_handle &client) { client.close(); });
client->on<uvw::data_event>([](const uvw::data_event &, uvw::tcp_handle &) { /* data received */ });
srv.accept(*client);
client->read();

View File

@ -83,91 +83,32 @@ template<typename T>
class emitter {
struct base_handler {
virtual ~base_handler() UVW_NOEXCEPT = default;
virtual bool empty() const UVW_NOEXCEPT = 0;
virtual void clear() UVW_NOEXCEPT = 0;
virtual bool has() const UVW_NOEXCEPT = 0;
virtual void reset() UVW_NOEXCEPT = 0;
};
template<typename E>
struct event_handler final: base_handler {
using listener = std::function<void(E &, T &)>;
using listener_list = std::list<std::pair<bool, listener>>;
using connection = typename listener_list::iterator;
bool empty() const UVW_NOEXCEPT override {
for(auto &&curr: once_list) {
if(!curr.first) {
return false;
}
}
for(auto &&curr: on_list) {
if(!curr.first) {
return false;
}
}
return true;
bool has() const UVW_NOEXCEPT override {
return static_cast<bool>(listener);
}
void clear() UVW_NOEXCEPT override {
if(publishing) {
for(auto &&curr: once_list) {
curr.first = true;
}
for(auto &&curr: on_list) {
curr.first = true;
}
} else {
once_list.clear();
on_list.clear();
}
void reset() UVW_NOEXCEPT override {
listener = nullptr;
}
connection once(listener f) {
return once_list.emplace(once_list.cend(), false, std::move(f));
}
connection on(listener f) {
return on_list.emplace(on_list.cend(), false, std::move(f));
}
void erase(connection conn) UVW_NOEXCEPT {
conn->first = true;
if(!publishing) {
auto pred = [](auto &&elem) { return elem.first; };
once_list.remove_if(pred);
on_list.remove_if(pred);
}
void on(std::function<void(E &, T &)> func) {
listener = std::move(func);
}
void publish(E event, T &ref) {
listener_list curr;
once_list.swap(curr);
publishing = true;
for(auto first = on_list.rbegin(), last = on_list.rend(); first != last; ++first) {
if(!first->first) {
first->second(event, ref);
}
if(listener) {
listener(event, ref);
}
for(auto first = curr.rbegin(), last = curr.rend(); first != last; ++first) {
if(!first->first) {
first->second(event, ref);
}
}
publishing = false;
on_list.remove_if([](auto &&elem) { return elem.first; });
}
private:
bool publishing{false};
listener_list once_list{};
listener_list on_list{};
std::function<void(E &, T &)> listener;
};
template<typename E>
@ -188,32 +129,6 @@ protected:
}
public:
template<typename E>
using listener = typename event_handler<E>::listener;
/**
* @brief Connection type for a given event type.
*
* Given an event type `E`, `connection<E>` is the type of the connection
* object returned by the event emitter whenever a listener for the given
* type is registered.
*/
template<typename E>
struct connection: private event_handler<E>::connection {
template<typename>
friend class emitter;
connection() = default;
connection(const connection &) = default;
connection(connection &&) = default;
connection(typename event_handler<E>::connection conn)
: event_handler<E>::connection{std::move(conn)} {}
connection &operator=(const connection &) = default;
connection &operator=(connection &&) = default;
};
virtual ~emitter() UVW_NOEXCEPT {
static_assert(std::is_base_of_v<emitter<T>, T>);
}
@ -221,93 +136,44 @@ public:
/**
* @brief Registers a long-lived listener with the event emitter.
*
* This method can be used to register a listener that is meant to be
* invoked more than once for the given event type.<br/>
* The connection object returned by the method can be freely discarded. It
* can be used later to disconnect the listener, if needed.
*
* This method is used to register a listener with the emitter.<br/>
* A listener is usually defined as a callable object assignable to a
* `std::function<void(const E &, T &)`, where `E` is the type of the event
* and `T` is the type of the resource.
*
* @param f A valid listener to be registered.
* @return Connection object to be used later to disconnect the listener.
*/
template<typename E>
connection<E> on(listener<E> f) {
void on(std::function<void(E &, T &)> f) {
return handler<E>().on(std::move(f));
}
/**
* @brief Registers a short-lived listener with the event emitter.
*
* This method can be used to register a listener that is meant to be
* invoked only once for the given event type.<br/>
* The connection object returned by the method can be freely discarded. It
* can be used later to disconnect the listener, if needed.
*
* a listener is usually defined as a callable object assignable to a
* `std::function<void(const E &, T &)`, where `E` is the type of the event
* and `T` is the type of the resource.
*
* @param f A valid listener to be registered.
* @return Connection object to be used later to disconnect the listener.
* @brief Disconnects the listener for the given event type.
*/
template<typename E>
connection<E> once(listener<E> f) {
return handler<E>().once(std::move(f));
void reset() UVW_NOEXCEPT {
handler<E>().reset();
}
/**
* @brief Disconnects a listener from the event emitter.
* @param conn A valid connection object
* @brief Disconnects all listeners.
*/
template<typename E>
void erase(connection<E> conn) UVW_NOEXCEPT {
handler<E>().erase(std::move(conn));
}
/**
* @brief Disconnects all the listeners for the given event type.
*/
template<typename E>
void clear() UVW_NOEXCEPT {
handler<E>().clear();
}
/**
* @brief Disconnects all the listeners.
*/
void clear() UVW_NOEXCEPT {
void reset() UVW_NOEXCEPT {
for(auto &&curr: handlers) {
curr.second->clear();
curr.second->reset();
}
}
/**
* @brief Checks if there are listeners registered for the specific event.
* @return True if there are no listeners registered for the specific event,
* @brief Checks if there is a listener registered for the specific event.
* @return True if there is a listener registered for the specific event,
* false otherwise.
*/
template<typename E>
bool empty() const UVW_NOEXCEPT {
bool has() const UVW_NOEXCEPT {
const auto id = type<E>();
return (!handlers.count(id) || static_cast<event_handler<E> &>(*handlers.at(id)).empty());
}
/**
* @brief Checks if there are listeners registered with the event emitter.
* @return True if there are no listeners registered with the event emitter,
* false otherwise.
*/
bool empty() const UVW_NOEXCEPT {
for(auto &&curr: handlers) {
if(!curr.second->empty()) {
return false;
}
}
return true;
return (handlers.count(id) && static_cast<event_handler<E> &>(*handlers.at(id)).has());
}
private:

View File

@ -32,8 +32,8 @@ UVW_INLINE void pipe_handle::connect(const std::string &name) {
};
auto connect = parent().resource<details::connect_req>();
connect->once<error_event>(listener);
connect->once<connect_event>(listener);
connect->on<error_event>(listener);
connect->on<connect_event>(listener);
connect->connect(&uv_pipe_connect, raw(), name.data());
}

View File

@ -175,8 +175,8 @@ public:
};
auto shutdown = this->parent().template resource<details::shutdown_req>();
shutdown->template once<error_event>(listener);
shutdown->template once<shutdown_event>(listener);
shutdown->template on<error_event>(listener);
shutdown->template on<shutdown_event>(listener);
shutdown->shutdown(as_uv_stream());
}
@ -265,8 +265,8 @@ public:
ptr->publish(event);
};
req->template once<error_event>(listener);
req->template once<write_event>(listener);
req->template on<error_event>(listener);
req->template on<write_event>(listener);
req->write(as_uv_stream());
}
@ -288,8 +288,8 @@ public:
ptr->publish(event);
};
req->template once<error_event>(listener);
req->template once<write_event>(listener);
req->template on<error_event>(listener);
req->template on<write_event>(listener);
req->write(as_uv_stream());
}
@ -319,8 +319,8 @@ public:
ptr->publish(event);
};
req->template once<error_event>(listener);
req->template once<write_event>(listener);
req->template on<error_event>(listener);
req->template on<write_event>(listener);
req->write(as_uv_stream(), send.as_uv_stream());
}
@ -350,8 +350,8 @@ public:
ptr->publish(event);
};
req->template once<error_event>(listener);
req->template once<write_event>(listener);
req->template on<error_event>(listener);
req->template on<write_event>(listener);
req->write(as_uv_stream(), send.as_uv_stream());
}

View File

@ -77,8 +77,8 @@ UVW_INLINE void tcp_handle::connect(const sockaddr &addr) {
};
auto req = parent().resource<details::connect_req>();
req->once<error_event>(listener);
req->once<connect_event>(listener);
req->on<error_event>(listener);
req->on<connect_event>(listener);
req->connect(&uv_tcp_connect, raw(), &addr);
}

View File

@ -146,8 +146,8 @@ UVW_INLINE void udp_handle::send(const sockaddr &addr, std::unique_ptr<char[]> d
ptr->publish(event);
};
req->once<error_event>(listener);
req->once<send_event>(listener);
req->on<error_event>(listener);
req->on<send_event>(listener);
req->send(raw(), &addr);
}
@ -166,8 +166,8 @@ UVW_INLINE void udp_handle::send(const sockaddr &addr, char *data, unsigned int
ptr->publish(event);
};
req->once<error_event>(listener);
req->once<send_event>(listener);
req->on<error_event>(listener);
req->on<send_event>(listener);
req->send(raw(), &addr);
}

View File

@ -62,7 +62,7 @@ function(ADD_UVW_TEST TEST_NAME TEST_SOURCE)
${TEST_NAME}
PRIVATE
$<$<NOT:$<PLATFORM_ID:Windows>>:-Wall>
$<$<PLATFORM_ID:Windows>:/EHsc>
$<$<PLATFORM_ID:Windows>:/EHsc -ftime-trace>
)
target_compile_definitions(${TEST_NAME} PRIVATE $<$<NOT:$<TARGET_EXISTS:uvw::uvw>>:UVW_AS_LIB>)

View File

@ -8,7 +8,7 @@ void listen(uvw::loop &loop) {
std::shared_ptr<uvw::tcp_handle> tcp = loop.resource<uvw::tcp_handle>();
tcp->on<uvw::error_event>([](const uvw::error_event &, uvw::tcp_handle &) { assert(false); });
tcp->once<uvw::listen_event>([](const uvw::listen_event &, uvw::tcp_handle &srv) {
tcp->on<uvw::listen_event>([](const uvw::listen_event &, uvw::tcp_handle &srv) {
std::cout << "listen" << std::endl;
std::shared_ptr<uvw::tcp_handle> client = srv.parent().resource<uvw::tcp_handle>();
@ -43,7 +43,7 @@ void listen(uvw::loop &loop) {
client->read();
});
tcp->once<uvw::close_event>([](const uvw::close_event &, uvw::tcp_handle &) {
tcp->on<uvw::close_event>([](const uvw::close_event &, uvw::tcp_handle &) {
std::cout << "close" << std::endl;
});
@ -55,12 +55,12 @@ void conn(uvw::loop &loop) {
auto tcp = loop.resource<uvw::tcp_handle>();
tcp->on<uvw::error_event>([](const uvw::error_event &, uvw::tcp_handle &) { assert(false); });
tcp->once<uvw::write_event>([](const uvw::write_event &, uvw::tcp_handle &handle) {
tcp->on<uvw::write_event>([](const uvw::write_event &, uvw::tcp_handle &handle) {
std::cout << "write" << std::endl;
handle.close();
});
tcp->once<uvw::connect_event>([](const uvw::connect_event &, uvw::tcp_handle &handle) {
tcp->on<uvw::connect_event>([](const uvw::connect_event &, uvw::tcp_handle &handle) {
std::cout << "connect" << std::endl;
auto dataTryWrite = std::unique_ptr<char[]>(new char[1]{'a'});
@ -71,7 +71,7 @@ void conn(uvw::loop &loop) {
handle.write(std::move(dataWrite), 2);
});
tcp->once<uvw::close_event>([](const uvw::close_event &, uvw::tcp_handle &) {
tcp->on<uvw::close_event>([](const uvw::close_event &, uvw::tcp_handle &) {
std::cout << "close" << std::endl;
});

View File

@ -24,125 +24,40 @@ TEST(ErrorEvent, Functionalities) {
ASSERT_TRUE(static_cast<bool>(uvw::error_event{ecode}));
}
TEST(Emitter, EmptyAndClear) {
TEST(Emitter, Functionalities) {
TestEmitter emitter{};
ASSERT_TRUE(emitter.empty());
emitter.on<uvw::error_event>([](const auto &, auto &) {});
ASSERT_FALSE(emitter.empty());
ASSERT_FALSE(emitter.empty<uvw::error_event>());
ASSERT_TRUE(emitter.empty<FakeEvent>());
ASSERT_TRUE(emitter.has<uvw::error_event>());
ASSERT_FALSE(emitter.has<FakeEvent>());
emitter.clear<FakeEvent>();
emitter.reset<FakeEvent>();
ASSERT_FALSE(emitter.empty());
ASSERT_FALSE(emitter.empty<uvw::error_event>());
ASSERT_TRUE(emitter.empty<FakeEvent>());
ASSERT_TRUE(emitter.has<uvw::error_event>());
ASSERT_FALSE(emitter.has<FakeEvent>());
emitter.clear<uvw::error_event>();
emitter.reset<uvw::error_event>();
ASSERT_TRUE(emitter.empty());
ASSERT_TRUE(emitter.empty<uvw::error_event>());
ASSERT_TRUE(emitter.empty<FakeEvent>());
ASSERT_FALSE(emitter.has<uvw::error_event>());
ASSERT_FALSE(emitter.has<FakeEvent>());
bool sentinel = false;
emitter.on<uvw::error_event>([](const auto &, auto &) {});
emitter.on<FakeEvent>([](const auto &, auto &) {});
emitter.on<FakeEvent>([&](const auto &, auto &) { sentinel = true; });
ASSERT_FALSE(emitter.empty());
ASSERT_FALSE(emitter.empty<uvw::error_event>());
ASSERT_FALSE(emitter.empty<FakeEvent>());
emitter.clear();
ASSERT_TRUE(emitter.empty());
ASSERT_TRUE(emitter.empty<uvw::error_event>());
ASSERT_TRUE(emitter.empty<FakeEvent>());
}
TEST(Emitter, On) {
TestEmitter emitter{};
emitter.on<FakeEvent>([](const auto &, auto &) {});
ASSERT_FALSE(emitter.empty());
ASSERT_FALSE(emitter.empty<FakeEvent>());
ASSERT_FALSE(sentinel);
ASSERT_TRUE(emitter.has<uvw::error_event>());
ASSERT_TRUE(emitter.has<FakeEvent>());
emitter.emit();
ASSERT_FALSE(emitter.empty());
ASSERT_FALSE(emitter.empty<FakeEvent>());
}
TEST(Emitter, Once) {
TestEmitter emitter{};
emitter.once<FakeEvent>([](const auto &, auto &) {});
ASSERT_FALSE(emitter.empty());
ASSERT_FALSE(emitter.empty<FakeEvent>());
emitter.emit();
ASSERT_TRUE(emitter.empty());
ASSERT_TRUE(emitter.empty<FakeEvent>());
}
TEST(Emitter, OnceAndErase) {
TestEmitter emitter{};
auto conn = emitter.once<FakeEvent>([](const auto &, auto &) {});
ASSERT_FALSE(emitter.empty());
ASSERT_FALSE(emitter.empty<FakeEvent>());
emitter.erase(conn);
ASSERT_TRUE(emitter.empty());
ASSERT_TRUE(emitter.empty<FakeEvent>());
}
TEST(Emitter, OnAndErase) {
TestEmitter emitter{};
auto conn = emitter.on<FakeEvent>([](const auto &, auto &) {});
ASSERT_FALSE(emitter.empty());
ASSERT_FALSE(emitter.empty<FakeEvent>());
emitter.erase(conn);
ASSERT_TRUE(emitter.empty());
ASSERT_TRUE(emitter.empty<FakeEvent>());
}
TEST(Emitter, CallbackClear) {
TestEmitter emitter{};
emitter.on<FakeEvent>([](const auto &, auto &ref) {
ref.template on<FakeEvent>([](const auto &, auto &) {});
ref.clear();
});
ASSERT_FALSE(emitter.empty());
ASSERT_FALSE(emitter.empty<FakeEvent>());
emitter.emit();
ASSERT_TRUE(emitter.empty());
ASSERT_TRUE(emitter.empty<FakeEvent>());
emitter.on<FakeEvent>([](const auto &, auto &ref) {
ref.clear();
ref.template on<FakeEvent>([](const auto &, auto &) {});
});
ASSERT_FALSE(emitter.empty());
ASSERT_FALSE(emitter.empty<FakeEvent>());
emitter.emit();
ASSERT_FALSE(emitter.empty());
ASSERT_FALSE(emitter.empty<FakeEvent>());
ASSERT_TRUE(sentinel);
ASSERT_TRUE(emitter.has<uvw::error_event>());
ASSERT_TRUE(emitter.has<FakeEvent>());
emitter.reset();
ASSERT_FALSE(emitter.has<uvw::error_event>());
ASSERT_FALSE(emitter.has<FakeEvent>());
}

View File

@ -17,7 +17,7 @@ TEST(Pipe, ReadWrite) {
FAIL();
});
server->once<uvw::listen_event>([](const uvw::listen_event &, uvw::pipe_handle &handle) {
server->on<uvw::listen_event>([](const uvw::listen_event &, uvw::pipe_handle &handle) {
std::shared_ptr<uvw::pipe_handle> socket = handle.parent().resource<uvw::pipe_handle>();
socket->on<uvw::error_event>([](const uvw::error_event &, uvw::pipe_handle &) { FAIL(); });
@ -28,11 +28,11 @@ TEST(Pipe, ReadWrite) {
socket->read();
});
client->once<uvw::write_event>([](const uvw::write_event &, uvw::pipe_handle &handle) {
client->on<uvw::write_event>([](const uvw::write_event &, uvw::pipe_handle &handle) {
handle.close();
});
client->once<uvw::connect_event>([](const uvw::connect_event &, uvw::pipe_handle &handle) {
client->on<uvw::connect_event>([](const uvw::connect_event &, uvw::pipe_handle &handle) {
ASSERT_TRUE(handle.writable());
ASSERT_TRUE(handle.readable());
@ -63,7 +63,7 @@ TEST(Pipe, SockPeer) {
server->on<uvw::error_event>([](const auto &, auto &) { FAIL(); });
client->on<uvw::error_event>([](const auto &, auto &) { FAIL(); });
server->once<uvw::listen_event>([&peername](const uvw::listen_event &, uvw::pipe_handle &handle) {
server->on<uvw::listen_event>([&peername](const uvw::listen_event &, uvw::pipe_handle &handle) {
std::shared_ptr<uvw::pipe_handle> socket = handle.parent().resource<uvw::pipe_handle>();
socket->on<uvw::error_event>([](const uvw::error_event &, uvw::pipe_handle &) { FAIL(); });
@ -76,7 +76,7 @@ TEST(Pipe, SockPeer) {
ASSERT_EQ(handle.sock(), peername);
});
client->once<uvw::connect_event>([&peername](const uvw::connect_event &, uvw::pipe_handle &handle) {
client->on<uvw::connect_event>([&peername](const uvw::connect_event &, uvw::pipe_handle &handle) {
ASSERT_EQ(handle.peer(), peername);
handle.close();
@ -105,7 +105,7 @@ TEST(Pipe, Shutdown) {
server->on<uvw::error_event>([](const auto &, auto &) { FAIL(); });
client->on<uvw::error_event>([](const auto &, auto &) { FAIL(); });
server->once<uvw::listen_event>([](const uvw::listen_event &, uvw::pipe_handle &handle) {
server->on<uvw::listen_event>([](const uvw::listen_event &, uvw::pipe_handle &handle) {
std::shared_ptr<uvw::pipe_handle> socket = handle.parent().resource<uvw::pipe_handle>();
socket->on<uvw::error_event>([](const uvw::error_event &, uvw::pipe_handle &) { FAIL(); });
@ -116,11 +116,11 @@ TEST(Pipe, Shutdown) {
socket->read();
});
client->once<uvw::shutdown_event>([](const uvw::shutdown_event &, uvw::pipe_handle &handle) {
client->on<uvw::shutdown_event>([](const uvw::shutdown_event &, uvw::pipe_handle &handle) {
handle.close();
});
client->once<uvw::connect_event>([&data](const uvw::connect_event &, uvw::pipe_handle &handle) {
client->on<uvw::connect_event>([&data](const uvw::connect_event &, uvw::pipe_handle &handle) {
handle.write(data.get(), 3);
handle.shutdown();
});

View File

@ -24,7 +24,7 @@ TEST(TCP, ReadWrite) {
server->on<uvw::error_event>([](const auto &, auto &) { FAIL(); });
client->on<uvw::error_event>([](const auto &, auto &) { FAIL(); });
server->once<uvw::listen_event>([](const uvw::listen_event &, uvw::tcp_handle &handle) {
server->on<uvw::listen_event>([](const uvw::listen_event &, uvw::tcp_handle &handle) {
std::shared_ptr<uvw::tcp_handle> socket = handle.parent().resource<uvw::tcp_handle>();
socket->on<uvw::error_event>([](const uvw::error_event &, uvw::tcp_handle &) { FAIL(); });
@ -35,11 +35,11 @@ TEST(TCP, ReadWrite) {
socket->read();
});
client->once<uvw::write_event>([](const uvw::write_event &, uvw::tcp_handle &handle) {
client->on<uvw::write_event>([](const uvw::write_event &, uvw::tcp_handle &handle) {
handle.close();
});
client->once<uvw::connect_event>([](const uvw::connect_event &, uvw::tcp_handle &handle) {
client->on<uvw::connect_event>([](const uvw::connect_event &, uvw::tcp_handle &handle) {
ASSERT_TRUE(handle.writable());
ASSERT_TRUE(handle.readable());
@ -67,7 +67,7 @@ TEST(TCP, SockPeer) {
server->on<uvw::error_event>([](const auto &, auto &) { FAIL(); });
client->on<uvw::error_event>([](const auto &, auto &) { FAIL(); });
server->once<uvw::listen_event>([&address](const uvw::listen_event &, uvw::tcp_handle &handle) {
server->on<uvw::listen_event>([&address](const uvw::listen_event &, uvw::tcp_handle &handle) {
std::shared_ptr<uvw::tcp_handle> socket = handle.parent().resource<uvw::tcp_handle>();
socket->on<uvw::error_event>([](const uvw::error_event &, uvw::tcp_handle &) { FAIL(); });
@ -82,7 +82,7 @@ TEST(TCP, SockPeer) {
ASSERT_EQ(addr.ip, address);
});
client->once<uvw::connect_event>([&address](const uvw::connect_event &, uvw::tcp_handle &handle) {
client->on<uvw::connect_event>([&address](const uvw::connect_event &, uvw::tcp_handle &handle) {
uvw::socket_address addr = handle.peer();
ASSERT_EQ(addr.ip, address);
@ -108,7 +108,7 @@ TEST(TCP, Shutdown) {
server->on<uvw::error_event>([](const auto &, auto &) { FAIL(); });
client->on<uvw::error_event>([](const auto &, auto &) { FAIL(); });
server->once<uvw::listen_event>([](const uvw::listen_event &, uvw::tcp_handle &handle) {
server->on<uvw::listen_event>([](const uvw::listen_event &, uvw::tcp_handle &handle) {
std::shared_ptr<uvw::tcp_handle> socket = handle.parent().resource<uvw::tcp_handle>();
socket->on<uvw::error_event>([](const uvw::error_event &, uvw::tcp_handle &) { FAIL(); });
@ -119,11 +119,11 @@ TEST(TCP, Shutdown) {
socket->read();
});
client->once<uvw::shutdown_event>([](const uvw::shutdown_event &, uvw::tcp_handle &handle) {
client->on<uvw::shutdown_event>([](const uvw::shutdown_event &, uvw::tcp_handle &handle) {
handle.close();
});
client->once<uvw::connect_event>([](const uvw::connect_event &, uvw::tcp_handle &handle) {
client->on<uvw::connect_event>([](const uvw::connect_event &, uvw::tcp_handle &handle) {
handle.shutdown();
});
@ -144,13 +144,13 @@ TEST(TCP, WriteError) {
bool checkTryWriteNakedPtrErrorEvent = false;
handle->close();
handle->once<uvw::error_event>([&checkWriteSmartPtrErrorEvent](const auto &, auto &) { checkWriteSmartPtrErrorEvent = true; });
handle->on<uvw::error_event>([&checkWriteSmartPtrErrorEvent](const auto &, auto &) { checkWriteSmartPtrErrorEvent = true; });
handle->write(std::unique_ptr<char[]>{}, 0);
handle->once<uvw::error_event>([&checkWriteNakedPtrErrorEvent](const auto &, auto &) { checkWriteNakedPtrErrorEvent = true; });
handle->on<uvw::error_event>([&checkWriteNakedPtrErrorEvent](const auto &, auto &) { checkWriteNakedPtrErrorEvent = true; });
handle->write(nullptr, 0);
handle->once<uvw::error_event>([&checkTryWriteSmartPtrErrorEvent](const auto &, auto &) { checkTryWriteSmartPtrErrorEvent = true; });
handle->on<uvw::error_event>([&checkTryWriteSmartPtrErrorEvent](const auto &, auto &) { checkTryWriteSmartPtrErrorEvent = true; });
handle->try_write(std::unique_ptr<char[]>{}, 0);
handle->once<uvw::error_event>([&checkTryWriteNakedPtrErrorEvent](const auto &, auto &) { checkTryWriteNakedPtrErrorEvent = true; });
handle->on<uvw::error_event>([&checkTryWriteNakedPtrErrorEvent](const auto &, auto &) { checkTryWriteNakedPtrErrorEvent = true; });
handle->try_write(nullptr, 0);
loop->run();

View File

@ -47,7 +47,7 @@ TEST(UDP, ReadTrySend) {
server->on<uvw::error_event>([](const auto &, auto &) { FAIL(); });
client->on<uvw::error_event>([](const auto &, auto &) { FAIL(); });
server->once<uvw::udp_data_event>([&client](const uvw::udp_data_event &, uvw::udp_handle &handle) {
server->on<uvw::udp_data_event>([&client](const uvw::udp_data_event &, uvw::udp_handle &handle) {
client->close();
handle.close();
});
@ -77,11 +77,11 @@ TEST(UDP, ReadSend) {
server->on<uvw::error_event>([](const auto &, auto &) { FAIL(); });
client->on<uvw::error_event>([](const auto &, auto &) { FAIL(); });
server->once<uvw::udp_data_event>([](const uvw::udp_data_event &, uvw::udp_handle &handle) {
server->on<uvw::udp_data_event>([](const uvw::udp_data_event &, uvw::udp_handle &handle) {
handle.close();
});
client->once<uvw::send_event>([](const uvw::send_event &, uvw::udp_handle &handle) {
client->on<uvw::send_event>([](const uvw::send_event &, uvw::udp_handle &handle) {
handle.close();
});