commit
f9c5cb4df5
@ -116,7 +116,12 @@ The first thing to do to use `uvw` is to create a loop. In case the default one
|
||||
auto loop = uvw::Loop::getDefault();
|
||||
|
||||
Note that loop objects don't require to be closed explicitly, even if they offer the `close` member method in case an user wants to do that.
|
||||
Loops can be run using the `run`, `runOnce` and `runWait` member methods. Please refer to the documentation of *libuv* for further details.
|
||||
Loops can be started using the `run` member method. The two calls below are equivalent:
|
||||
|
||||
loop->run();
|
||||
loop->run<uvw::Loop::Mode::DEFAULT>
|
||||
|
||||
Available modes are: `DEFAULT`, `ONCE`, `NOWAIT`. Please refer to the documentation of *libuv* for further details.
|
||||
|
||||
In order to create a resource and to bind it to the given loop, just do the following:
|
||||
|
||||
|
||||
@ -22,6 +22,13 @@ enum class UVLoopOption: std::underlying_type_t<uv_loop_option> {
|
||||
};
|
||||
|
||||
|
||||
enum class UVRunMode: std::underlying_type_t<uv_run_mode> {
|
||||
DEFAULT = UV_RUN_DEFAULT,
|
||||
ONCE = UV_RUN_ONCE,
|
||||
NOWAIT = UV_RUN_NOWAIT
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -49,6 +56,7 @@ class Loop final: public Emitter<Loop>, public std::enable_shared_from_this<Loop
|
||||
public:
|
||||
using Time = std::chrono::milliseconds;
|
||||
using Configure = details::UVLoopOption;
|
||||
using Mode = details::UVRunMode;
|
||||
|
||||
static std::shared_ptr<Loop> create() {
|
||||
auto ptr = std::unique_ptr<uv_loop_t, Deleter>{new uv_loop_t, [](uv_loop_t *l){ delete l; }};
|
||||
@ -117,16 +125,11 @@ public:
|
||||
if(err) { publish(ErrorEvent{err}); }
|
||||
}
|
||||
|
||||
template<Mode mode = Mode::DEFAULT>
|
||||
bool run() noexcept {
|
||||
return (uv_run(loop.get(), UV_RUN_DEFAULT) == 0);
|
||||
}
|
||||
|
||||
bool runOnce() noexcept {
|
||||
return (uv_run(loop.get(), UV_RUN_ONCE) == 0);
|
||||
}
|
||||
|
||||
bool runWait() noexcept {
|
||||
return (uv_run(loop.get(), UV_RUN_NOWAIT) == 0);
|
||||
auto utm = static_cast<std::underlying_type_t<Mode>>(mode);
|
||||
auto uvrm = static_cast<uv_run_mode>(utm);
|
||||
return (uv_run(loop.get(), uvrm) == 0);
|
||||
}
|
||||
|
||||
bool alive() const noexcept {
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
@ -11,6 +12,16 @@
|
||||
namespace uvw {
|
||||
|
||||
|
||||
class Thread;
|
||||
class ThreadLocalStorage;
|
||||
class Once;
|
||||
class Mutex;
|
||||
class RWLock;
|
||||
class Semaphore;
|
||||
class Condition;
|
||||
class Barrier;
|
||||
|
||||
|
||||
class Thread final {
|
||||
using InternalTask = std::function<void(std::shared_ptr<void>)>;
|
||||
|
||||
@ -23,8 +34,7 @@ class Thread final {
|
||||
: pLoop{std::move(ref)},
|
||||
data{std::move(d)},
|
||||
thread{},
|
||||
task{std::move(t)},
|
||||
err{0}
|
||||
task{std::move(t)}
|
||||
{ }
|
||||
|
||||
public:
|
||||
@ -44,24 +54,18 @@ public:
|
||||
return !(0 == uv_thread_equal(&tl.thread, &tr.thread));
|
||||
}
|
||||
|
||||
~Thread() {
|
||||
~Thread() noexcept {
|
||||
uv_thread_join(&thread);
|
||||
}
|
||||
|
||||
bool run() noexcept {
|
||||
err = uv_thread_create(&thread, &createCallback, this);
|
||||
return static_cast<bool>(*this);
|
||||
return (0 == uv_thread_create(&thread, &createCallback, this));
|
||||
}
|
||||
|
||||
bool join() noexcept {
|
||||
err = uv_thread_join(&thread);
|
||||
return static_cast<bool>(*this);
|
||||
return (0 == uv_thread_join(&thread));
|
||||
}
|
||||
|
||||
explicit operator bool() const noexcept { return (0 == err); }
|
||||
|
||||
int error() const noexcept { return err; }
|
||||
|
||||
Loop& loop() const noexcept { return *pLoop; }
|
||||
|
||||
private:
|
||||
@ -69,17 +73,266 @@ private:
|
||||
std::shared_ptr<void> data;
|
||||
uv_thread_t thread;
|
||||
Task task;
|
||||
int err;
|
||||
};
|
||||
|
||||
|
||||
// TODO Thread-local storage
|
||||
// TODO Once-only initialization
|
||||
// TODO Mutex locks
|
||||
// TODO Read-write locks
|
||||
// TODO Semaphores
|
||||
// TODO Conditions
|
||||
// TODO Barriers
|
||||
class ThreadLocalStorage final {
|
||||
explicit ThreadLocalStorage(std::shared_ptr<Loop> ref) noexcept
|
||||
: pLoop{std::move(ref)}
|
||||
{
|
||||
uv_key_create(&key);
|
||||
}
|
||||
|
||||
public:
|
||||
template<typename... Args>
|
||||
static std::shared_ptr<ThreadLocalStorage> create(Args&&... args) {
|
||||
return std::shared_ptr<ThreadLocalStorage>{new ThreadLocalStorage{std::forward<Args>(args)...}};
|
||||
}
|
||||
|
||||
~ThreadLocalStorage() noexcept {
|
||||
uv_key_delete(&key);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T* get() noexcept {
|
||||
return static_cast<T*>(uv_key_get(&key));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void set(T *value) noexcept {
|
||||
return uv_key_set(&key, value);
|
||||
}
|
||||
|
||||
Loop& loop() const noexcept { return *pLoop; }
|
||||
|
||||
private:
|
||||
std::shared_ptr<Loop> pLoop;
|
||||
uv_key_t key;
|
||||
};
|
||||
|
||||
|
||||
class Once final {
|
||||
explicit Once(std::shared_ptr<Loop> ref) noexcept
|
||||
: pLoop{std::move(ref)}
|
||||
{ }
|
||||
|
||||
public:
|
||||
template<typename... Args>
|
||||
static std::shared_ptr<Once> create(Args&&... args) {
|
||||
return std::shared_ptr<Once>{new Once{std::forward<Args>(args)...}};
|
||||
}
|
||||
|
||||
template<typename F>
|
||||
static void once(F &&f) noexcept {
|
||||
using CallbackType = void (*)(void);
|
||||
static_assert(std::is_convertible<F, CallbackType>::value, "!");
|
||||
CallbackType cb = f;
|
||||
uv_once(&guard, cb);
|
||||
}
|
||||
|
||||
Loop& loop() const noexcept { return *pLoop; }
|
||||
|
||||
private:
|
||||
std::shared_ptr<Loop> pLoop;
|
||||
static uv_once_t guard;
|
||||
};
|
||||
|
||||
uv_once_t Once::guard = UV_ONCE_INIT;
|
||||
|
||||
|
||||
class Mutex final {
|
||||
friend class Condition;
|
||||
|
||||
explicit Mutex(std::shared_ptr<Loop> ref) noexcept
|
||||
: pLoop{std::move(ref)}
|
||||
{
|
||||
uv_mutex_init(&mutex);
|
||||
}
|
||||
|
||||
public:
|
||||
template<typename... Args>
|
||||
static std::shared_ptr<Mutex> create(Args&&... args) {
|
||||
return std::shared_ptr<Mutex>{new Mutex{std::forward<Args>(args)...}};
|
||||
}
|
||||
|
||||
~Mutex() noexcept {
|
||||
uv_mutex_destroy(&mutex);
|
||||
}
|
||||
|
||||
void lock() noexcept {
|
||||
uv_mutex_lock(&mutex);
|
||||
}
|
||||
|
||||
bool tryLock() noexcept {
|
||||
return (0 == uv_mutex_trylock(&mutex));
|
||||
}
|
||||
|
||||
void unlock() noexcept {
|
||||
uv_mutex_unlock(&mutex);
|
||||
}
|
||||
|
||||
Loop& loop() const noexcept { return *pLoop; }
|
||||
|
||||
private:
|
||||
std::shared_ptr<Loop> pLoop;
|
||||
uv_mutex_t mutex;
|
||||
};
|
||||
|
||||
|
||||
class RWLock final {
|
||||
explicit RWLock(std::shared_ptr<Loop> ref) noexcept
|
||||
: pLoop{std::move(ref)}
|
||||
{
|
||||
uv_rwlock_init(&rwlock);
|
||||
}
|
||||
|
||||
public:
|
||||
template<typename... Args>
|
||||
static std::shared_ptr<RWLock> create(Args&&... args) {
|
||||
return std::shared_ptr<RWLock>{new RWLock{std::forward<Args>(args)...}};
|
||||
}
|
||||
|
||||
~RWLock() noexcept {
|
||||
uv_rwlock_destroy(&rwlock);
|
||||
}
|
||||
|
||||
void rdLock() noexcept {
|
||||
uv_rwlock_rdlock(&rwlock);
|
||||
}
|
||||
|
||||
bool tryRdLock() noexcept {
|
||||
return (0 == uv_rwlock_tryrdlock(&rwlock));
|
||||
}
|
||||
|
||||
void rdUnlock() noexcept {
|
||||
uv_rwlock_rdunlock(&rwlock);
|
||||
}
|
||||
|
||||
void wrLock() noexcept {
|
||||
uv_rwlock_wrlock(&rwlock);
|
||||
}
|
||||
|
||||
bool tryWrLock() noexcept {
|
||||
return (0 == uv_rwlock_trywrlock(&rwlock));
|
||||
}
|
||||
|
||||
void wrUnlock() noexcept {
|
||||
uv_rwlock_wrunlock(&rwlock);
|
||||
}
|
||||
|
||||
Loop& loop() const noexcept { return *pLoop; }
|
||||
|
||||
private:
|
||||
std::shared_ptr<Loop> pLoop;
|
||||
uv_rwlock_t rwlock;
|
||||
};
|
||||
|
||||
|
||||
class Semaphore final {
|
||||
explicit Semaphore(std::shared_ptr<Loop> ref, unsigned int value) noexcept
|
||||
: pLoop{std::move(ref)}
|
||||
{
|
||||
uv_sem_init(&sem, value);
|
||||
}
|
||||
|
||||
public:
|
||||
template<typename... Args>
|
||||
static std::shared_ptr<Semaphore> create(Args&&... args) {
|
||||
return std::shared_ptr<Semaphore>{new Semaphore{std::forward<Args>(args)...}};
|
||||
}
|
||||
|
||||
~Semaphore() noexcept {
|
||||
uv_sem_destroy(&sem);
|
||||
}
|
||||
|
||||
void post() noexcept {
|
||||
uv_sem_post(&sem);
|
||||
}
|
||||
|
||||
void wait() noexcept {
|
||||
uv_sem_wait(&sem);
|
||||
}
|
||||
|
||||
bool tryWait() noexcept {
|
||||
return (0 == uv_sem_trywait(&sem));
|
||||
}
|
||||
|
||||
Loop& loop() const noexcept { return *pLoop; }
|
||||
|
||||
private:
|
||||
std::shared_ptr<Loop> pLoop;
|
||||
uv_sem_t sem;
|
||||
};
|
||||
|
||||
|
||||
class Condition final {
|
||||
explicit Condition(std::shared_ptr<Loop> ref) noexcept
|
||||
: pLoop{std::move(ref)}
|
||||
{
|
||||
uv_cond_init(&cond);
|
||||
}
|
||||
|
||||
public:
|
||||
template<typename... Args>
|
||||
static std::shared_ptr<Condition> create(Args&&... args) {
|
||||
return std::shared_ptr<Condition>{new Condition{std::forward<Args>(args)...}};
|
||||
}
|
||||
|
||||
~Condition() noexcept {
|
||||
uv_cond_destroy(&cond);
|
||||
}
|
||||
|
||||
void signal() noexcept {
|
||||
uv_cond_signal(&cond);
|
||||
}
|
||||
|
||||
void broadcast() noexcept {
|
||||
uv_cond_broadcast(&cond);
|
||||
}
|
||||
|
||||
void wait(Mutex &mutex) noexcept {
|
||||
uv_cond_wait(&cond, &mutex.mutex);
|
||||
}
|
||||
|
||||
bool timedWait(Mutex &mutex, uint64_t timeout) noexcept {
|
||||
return (0 == uv_cond_timedwait(&cond, &mutex.mutex, timeout));
|
||||
}
|
||||
|
||||
Loop& loop() const noexcept { return *pLoop; }
|
||||
|
||||
private:
|
||||
std::shared_ptr<Loop> pLoop;
|
||||
uv_cond_t cond;
|
||||
};
|
||||
|
||||
|
||||
class Barrier final {
|
||||
explicit Barrier(std::shared_ptr<Loop> ref, unsigned int count) noexcept
|
||||
: pLoop{std::move(ref)}
|
||||
{
|
||||
uv_barrier_init(&barrier, count);
|
||||
}
|
||||
|
||||
public:
|
||||
template<typename... Args>
|
||||
static std::shared_ptr<Barrier> create(Args&&... args) {
|
||||
return std::shared_ptr<Barrier>{new Barrier{std::forward<Args>(args)...}};
|
||||
}
|
||||
|
||||
~Barrier() noexcept {
|
||||
uv_barrier_destroy(&barrier);
|
||||
}
|
||||
|
||||
bool wait() noexcept {
|
||||
return (0 == uv_barrier_wait(&barrier));
|
||||
}
|
||||
|
||||
Loop& loop() const noexcept { return *pLoop; }
|
||||
|
||||
private:
|
||||
std::shared_ptr<Loop> pLoop;
|
||||
uv_barrier_t barrier;
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
@ -22,7 +22,11 @@ set(
|
||||
|
||||
set(TARGET_MAIN main)
|
||||
set(TARGET_ASYNC async)
|
||||
set(TARGET_CHECK check)
|
||||
set(TARGET_IDLE idle)
|
||||
set(TARGET_LOOP loop)
|
||||
set(TARGET_PREPARE prepare)
|
||||
set(TARGET_SELF self)
|
||||
set(TARGET_WORK work)
|
||||
|
||||
# Test TARGET_MAIN
|
||||
@ -41,6 +45,22 @@ target_include_directories(${TARGET_ASYNC} PRIVATE ${COMMON_INCLUDE_DIRS})
|
||||
target_link_libraries(${TARGET_ASYNC} PRIVATE ${COMMON_LINK_LIBS})
|
||||
add_test(NAME ${TARGET_ASYNC} COMMAND ${TARGET_ASYNC})
|
||||
|
||||
# Test TARGET_CHECK
|
||||
|
||||
set(TARGET_CHECK_SOURCES uvw/check.cpp)
|
||||
add_executable(${TARGET_CHECK} ${TARGET_CHECK_SOURCES})
|
||||
target_include_directories(${TARGET_CHECK} PRIVATE ${COMMON_INCLUDE_DIRS})
|
||||
target_link_libraries(${TARGET_CHECK} PRIVATE ${COMMON_LINK_LIBS})
|
||||
add_test(NAME ${TARGET_CHECK} COMMAND ${TARGET_CHECK})
|
||||
|
||||
# Test TARGET_IDLE
|
||||
|
||||
set(TARGET_IDLE_SOURCES uvw/idle.cpp)
|
||||
add_executable(${TARGET_IDLE} ${TARGET_IDLE_SOURCES})
|
||||
target_include_directories(${TARGET_IDLE} PRIVATE ${COMMON_INCLUDE_DIRS})
|
||||
target_link_libraries(${TARGET_IDLE} PRIVATE ${COMMON_LINK_LIBS})
|
||||
add_test(NAME ${TARGET_IDLE} COMMAND ${TARGET_IDLE})
|
||||
|
||||
# Test TARGET_LOOP
|
||||
|
||||
set(TARGET_LOOP_SOURCES uvw/loop.cpp)
|
||||
@ -49,6 +69,22 @@ target_include_directories(${TARGET_LOOP} PRIVATE ${COMMON_INCLUDE_DIRS})
|
||||
target_link_libraries(${TARGET_LOOP} PRIVATE ${COMMON_LINK_LIBS})
|
||||
add_test(NAME ${TARGET_LOOP} COMMAND ${TARGET_LOOP})
|
||||
|
||||
# Test TARGET_PREPARE
|
||||
|
||||
set(TARGET_PREPARE_SOURCES uvw/prepare.cpp)
|
||||
add_executable(${TARGET_PREPARE} ${TARGET_PREPARE_SOURCES})
|
||||
target_include_directories(${TARGET_PREPARE} PRIVATE ${COMMON_INCLUDE_DIRS})
|
||||
target_link_libraries(${TARGET_PREPARE} PRIVATE ${COMMON_LINK_LIBS})
|
||||
add_test(NAME ${TARGET_PREPARE} COMMAND ${TARGET_PREPARE})
|
||||
|
||||
# Test TARGET_SELF
|
||||
|
||||
set(TARGET_SELF_SOURCES uvw/self.cpp)
|
||||
add_executable(${TARGET_SELF} ${TARGET_SELF_SOURCES})
|
||||
target_include_directories(${TARGET_SELF} PRIVATE ${COMMON_INCLUDE_DIRS})
|
||||
target_link_libraries(${TARGET_SELF} PRIVATE ${COMMON_LINK_LIBS})
|
||||
add_test(NAME ${TARGET_SELF} COMMAND ${TARGET_SELF})
|
||||
|
||||
# Test TARGET_WORK
|
||||
|
||||
set(TARGET_WORK_SOURCES uvw/work.cpp)
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
#include <gtest/gtest.h>
|
||||
#include <uvw.hpp>
|
||||
|
||||
|
||||
TEST(Async, Send) {
|
||||
auto loop = uvw::Loop::getDefault();
|
||||
auto handle = loop->resource<uvw::AsyncHandle>();
|
||||
@ -8,12 +9,12 @@ TEST(Async, Send) {
|
||||
bool checkErrorEvent = false;
|
||||
bool checkAsyncEvent = false;
|
||||
|
||||
handle->on<uvw::ErrorEvent>([&checkErrorEvent](const uvw::ErrorEvent &, uvw::AsyncHandle &){
|
||||
handle->on<uvw::ErrorEvent>([&checkErrorEvent](const auto &, auto &){
|
||||
ASSERT_FALSE(checkErrorEvent);
|
||||
checkErrorEvent = true;
|
||||
});
|
||||
|
||||
handle->on<uvw::AsyncEvent>([&checkAsyncEvent](const uvw::AsyncEvent &, uvw::AsyncHandle &handle){
|
||||
handle->on<uvw::AsyncEvent>([&checkAsyncEvent](const auto &, auto &handle){
|
||||
ASSERT_FALSE(checkAsyncEvent);
|
||||
checkAsyncEvent = true;
|
||||
handle.close();
|
||||
@ -30,3 +31,21 @@ TEST(Async, Send) {
|
||||
ASSERT_FALSE(checkErrorEvent);
|
||||
ASSERT_TRUE(checkAsyncEvent);
|
||||
}
|
||||
|
||||
|
||||
TEST(Async, Fake) {
|
||||
auto loop = uvw::Loop::getDefault();
|
||||
auto handle = loop->resource<uvw::AsyncHandle>();
|
||||
|
||||
auto l = [](const auto &, auto &){ ASSERT_FALSE(true); };
|
||||
handle->on<uvw::ErrorEvent>(l);
|
||||
handle->on<uvw::AsyncEvent>(l);
|
||||
|
||||
handle->send();
|
||||
handle->close();
|
||||
|
||||
ASSERT_FALSE(handle->active());
|
||||
ASSERT_TRUE(handle->closing());
|
||||
|
||||
loop->run();
|
||||
}
|
||||
|
||||
52
test/uvw/check.cpp
Normal file
52
test/uvw/check.cpp
Normal file
@ -0,0 +1,52 @@
|
||||
#include <gtest/gtest.h>
|
||||
#include <uvw.hpp>
|
||||
|
||||
|
||||
TEST(Check, StartAndStop) {
|
||||
auto loop = uvw::Loop::getDefault();
|
||||
auto handle = loop->resource<uvw::CheckHandle>();
|
||||
|
||||
bool checkErrorEvent = false;
|
||||
bool checkCheckEvent = false;
|
||||
|
||||
handle->on<uvw::ErrorEvent>([&checkErrorEvent](const auto &, auto &){
|
||||
ASSERT_FALSE(checkErrorEvent);
|
||||
checkErrorEvent = true;
|
||||
});
|
||||
|
||||
handle->on<uvw::CheckEvent>([&checkCheckEvent](const auto &, auto &handle){
|
||||
ASSERT_FALSE(checkCheckEvent);
|
||||
checkCheckEvent = true;
|
||||
handle.stop();
|
||||
handle.close();
|
||||
ASSERT_TRUE(handle.closing());
|
||||
});
|
||||
|
||||
handle->start();
|
||||
|
||||
ASSERT_TRUE(handle->active());
|
||||
ASSERT_FALSE(handle->closing());
|
||||
|
||||
loop->run<uvw::Loop::Mode::NOWAIT>();
|
||||
|
||||
ASSERT_FALSE(checkErrorEvent);
|
||||
ASSERT_TRUE(checkCheckEvent);
|
||||
}
|
||||
|
||||
|
||||
TEST(Check, Fake) {
|
||||
auto loop = uvw::Loop::getDefault();
|
||||
auto handle = loop->resource<uvw::CheckHandle>();
|
||||
|
||||
auto l = [](const auto &, auto &){ ASSERT_FALSE(true); };
|
||||
handle->on<uvw::ErrorEvent>(l);
|
||||
handle->on<uvw::CheckEvent>(l);
|
||||
|
||||
handle->start();
|
||||
handle->close();
|
||||
|
||||
ASSERT_FALSE(handle->active());
|
||||
ASSERT_TRUE(handle->closing());
|
||||
|
||||
loop->run();
|
||||
}
|
||||
52
test/uvw/idle.cpp
Normal file
52
test/uvw/idle.cpp
Normal file
@ -0,0 +1,52 @@
|
||||
#include <gtest/gtest.h>
|
||||
#include <uvw.hpp>
|
||||
|
||||
|
||||
TEST(Idle, StartAndStop) {
|
||||
auto loop = uvw::Loop::getDefault();
|
||||
auto handle = loop->resource<uvw::IdleHandle>();
|
||||
|
||||
bool checkErrorEvent = false;
|
||||
bool checkIdleEvent = false;
|
||||
|
||||
handle->on<uvw::ErrorEvent>([&checkErrorEvent](const auto &, auto &){
|
||||
ASSERT_FALSE(checkErrorEvent);
|
||||
checkErrorEvent = true;
|
||||
});
|
||||
|
||||
handle->on<uvw::IdleEvent>([&checkIdleEvent](const auto &, auto &handle){
|
||||
ASSERT_FALSE(checkIdleEvent);
|
||||
checkIdleEvent = true;
|
||||
handle.stop();
|
||||
handle.close();
|
||||
ASSERT_TRUE(handle.closing());
|
||||
});
|
||||
|
||||
handle->start();
|
||||
|
||||
ASSERT_TRUE(handle->active());
|
||||
ASSERT_FALSE(handle->closing());
|
||||
|
||||
loop->run<uvw::Loop::Mode::NOWAIT>();
|
||||
|
||||
ASSERT_FALSE(checkErrorEvent);
|
||||
ASSERT_TRUE(checkIdleEvent);
|
||||
}
|
||||
|
||||
|
||||
TEST(Idle, Fake) {
|
||||
auto loop = uvw::Loop::getDefault();
|
||||
auto handle = loop->resource<uvw::IdleHandle>();
|
||||
|
||||
auto l = [](const auto &, auto &){ ASSERT_FALSE(true); };
|
||||
handle->on<uvw::ErrorEvent>(l);
|
||||
handle->on<uvw::IdleEvent>(l);
|
||||
|
||||
handle->start();
|
||||
handle->close();
|
||||
|
||||
ASSERT_FALSE(handle->active());
|
||||
ASSERT_TRUE(handle->closing());
|
||||
|
||||
loop->run();
|
||||
}
|
||||
@ -15,7 +15,7 @@ TEST(Loop, PartiallyDone) {
|
||||
auto handle = loop->resource<uvw::PrepareHandle>();
|
||||
auto req = loop->resource<uvw::WorkReq>([](){});
|
||||
|
||||
auto err = [](uvw::ErrorEvent, auto &) { ASSERT_TRUE(false); };
|
||||
auto err = [](const auto &, auto &) { ASSERT_TRUE(false); };
|
||||
|
||||
loop->on<uvw::ErrorEvent>(err);
|
||||
req->on<uvw::ErrorEvent>(err);
|
||||
@ -27,7 +27,7 @@ TEST(Loop, PartiallyDone) {
|
||||
ASSERT_FALSE(loop->alive());
|
||||
|
||||
handle->start();
|
||||
handle->on<uvw::PrepareEvent>([](uvw::PrepareEvent, uvw::PrepareHandle &handle) {
|
||||
handle->on<uvw::PrepareEvent>([](const auto &, auto &handle) {
|
||||
handle.loop().walk([](uvw::BaseHandle &) {
|
||||
static bool trigger = true;
|
||||
ASSERT_TRUE(trigger);
|
||||
@ -42,8 +42,8 @@ TEST(Loop, PartiallyDone) {
|
||||
|
||||
loop->walk([](uvw::BaseHandle &) { ASSERT_TRUE(false); });
|
||||
|
||||
ASSERT_NO_THROW(loop->runOnce());
|
||||
ASSERT_NO_THROW(loop->runWait());
|
||||
ASSERT_NO_THROW(loop->run<uvw::Loop::Mode::ONCE>());
|
||||
ASSERT_NO_THROW(loop->run<uvw::Loop::Mode::NOWAIT>());
|
||||
|
||||
ASSERT_FALSE(loop->alive());
|
||||
}
|
||||
|
||||
52
test/uvw/prepare.cpp
Normal file
52
test/uvw/prepare.cpp
Normal file
@ -0,0 +1,52 @@
|
||||
#include <gtest/gtest.h>
|
||||
#include <uvw.hpp>
|
||||
|
||||
|
||||
TEST(Prepare, StartAndStop) {
|
||||
auto loop = uvw::Loop::getDefault();
|
||||
auto handle = loop->resource<uvw::PrepareHandle>();
|
||||
|
||||
bool checkErrorEvent = false;
|
||||
bool checkPrepareEvent = false;
|
||||
|
||||
handle->on<uvw::ErrorEvent>([&checkErrorEvent](const auto &, auto &){
|
||||
ASSERT_FALSE(checkErrorEvent);
|
||||
checkErrorEvent = true;
|
||||
});
|
||||
|
||||
handle->on<uvw::PrepareEvent>([&checkPrepareEvent](const auto &, auto &handle){
|
||||
ASSERT_FALSE(checkPrepareEvent);
|
||||
checkPrepareEvent = true;
|
||||
handle.stop();
|
||||
handle.close();
|
||||
ASSERT_TRUE(handle.closing());
|
||||
});
|
||||
|
||||
handle->start();
|
||||
|
||||
ASSERT_TRUE(handle->active());
|
||||
ASSERT_FALSE(handle->closing());
|
||||
|
||||
loop->run<uvw::Loop::Mode::NOWAIT>();
|
||||
|
||||
ASSERT_FALSE(checkErrorEvent);
|
||||
ASSERT_TRUE(checkPrepareEvent);
|
||||
}
|
||||
|
||||
|
||||
TEST(Prepare, Fake) {
|
||||
auto loop = uvw::Loop::getDefault();
|
||||
auto handle = loop->resource<uvw::PrepareHandle>();
|
||||
|
||||
auto l = [](const auto &, auto &){ ASSERT_FALSE(true); };
|
||||
handle->on<uvw::ErrorEvent>(l);
|
||||
handle->on<uvw::PrepareEvent>(l);
|
||||
|
||||
handle->start();
|
||||
handle->close();
|
||||
|
||||
ASSERT_FALSE(handle->active());
|
||||
ASSERT_TRUE(handle->closing());
|
||||
|
||||
loop->run();
|
||||
}
|
||||
23
test/uvw/self.cpp
Normal file
23
test/uvw/self.cpp
Normal file
@ -0,0 +1,23 @@
|
||||
#include <gtest/gtest.h>
|
||||
#include <uvw.hpp>
|
||||
|
||||
|
||||
struct S: uvw::Self<S> { };
|
||||
|
||||
|
||||
TEST(Self, Basics) {
|
||||
std::shared_ptr<S> self = std::make_shared<S>();
|
||||
|
||||
ASSERT_TRUE(self.unique());
|
||||
ASSERT_FALSE(self->self());
|
||||
|
||||
self->leak();
|
||||
|
||||
ASSERT_FALSE(self.unique());
|
||||
ASSERT_TRUE(self->self());
|
||||
|
||||
self->reset();
|
||||
|
||||
ASSERT_TRUE(self.unique());
|
||||
ASSERT_FALSE(self->self());
|
||||
}
|
||||
@ -14,12 +14,12 @@ TEST(Work, RunTask) {
|
||||
checkTask = true;
|
||||
});
|
||||
|
||||
req->on<uvw::WorkEvent>([&checkWorkEvent](const uvw::WorkEvent &, uvw::WorkReq &){
|
||||
req->on<uvw::WorkEvent>([&checkWorkEvent](const auto &, auto &){
|
||||
ASSERT_FALSE(checkWorkEvent);
|
||||
checkWorkEvent = true;
|
||||
});
|
||||
|
||||
req->on<uvw::ErrorEvent>([&checkErrorEvent](const uvw::ErrorEvent &, uvw::WorkReq &){
|
||||
req->on<uvw::ErrorEvent>([&checkErrorEvent](const auto &, auto &){
|
||||
ASSERT_FALSE(checkErrorEvent);
|
||||
checkErrorEvent = true;
|
||||
});
|
||||
@ -44,12 +44,12 @@ TEST(Work, Cancellation) {
|
||||
checkTask = true;
|
||||
});
|
||||
|
||||
req->on<uvw::WorkEvent>([&checkWorkEvent](const uvw::WorkEvent &, uvw::WorkReq &){
|
||||
req->on<uvw::WorkEvent>([&checkWorkEvent](const auto &, auto &){
|
||||
ASSERT_FALSE(checkWorkEvent);
|
||||
checkWorkEvent = true;
|
||||
});
|
||||
|
||||
req->on<uvw::ErrorEvent>([&checkErrorEvent](const uvw::ErrorEvent &, uvw::WorkReq &){
|
||||
req->on<uvw::ErrorEvent>([&checkErrorEvent](const auto &, auto &){
|
||||
ASSERT_FALSE(checkErrorEvent);
|
||||
checkErrorEvent = true;
|
||||
});
|
||||
|
||||
Loading…
Reference in New Issue
Block a user