diff --git a/build/test.pro b/build/test.pro index d74222d..51b65b6 100644 --- a/build/test.pro +++ b/build/test.pro @@ -27,9 +27,10 @@ HEADERS += \ SOURCES += \ ../test/main.cpp \ ../test/test_shm.cpp \ + ../test/test_mem.cpp \ ../test/test_circ.cpp \ - ../test/test_ipc.cpp \ - ../test/test_mem.cpp + ../test/test_waiter.cpp \ + ../test/test_ipc.cpp LIBS += \ -L$${DESTDIR} -lipc diff --git a/src/memory/resource.h b/src/memory/resource.h index f69d174..dfeacfb 100644 --- a/src/memory/resource.h +++ b/src/memory/resource.h @@ -18,12 +18,12 @@ namespace ipc { namespace mem { template -using sync_fixed_alloc = synchronized>; +using sync_fixed_alloc = mem::synchronized>; template using sync_fixed = mem::detail::fixed; -using sync_pool_alloc = detail::pool_alloc; +using sync_pool_alloc = mem::detail::pool_alloc; template using allocator = allocator_wrapper; diff --git a/src/memory/wrapper.h b/src/memory/wrapper.h index 5acfca5..1d5b61c 100644 --- a/src/memory/wrapper.h +++ b/src/memory/wrapper.h @@ -199,5 +199,32 @@ public: } }; +//////////////////////////////////////////////////////////////// +/// Static allocation wrapper +//////////////////////////////////////////////////////////////// + +template +class statical { +public: + using alloc_policy = AllocP; + + static alloc_policy& instance() { + static alloc_policy alloc; + return alloc; + } + + static void clear() { + instance().clear(); + } + + static void* alloc(std::size_t size) { + return instance().alloc(size); + } + + static void free(void* p, std::size_t size) { + instance().free(p, size); + } +}; + } // namespace mem } // namespace ipc diff --git a/src/platform/waiter_linux.h b/src/platform/waiter_linux.h index e7987ab..effe1f7 100644 --- a/src/platform/waiter_linux.h +++ b/src/platform/waiter_linux.h @@ -1,6 +1,5 @@ #pragma once -#include #include #include #include @@ -72,123 +71,6 @@ public: #pragma pop_macro("IPC_SEMAPHORE_FUNC_") }; -class mutex { - pthread_mutex_t mutex_ = PTHREAD_MUTEX_INITIALIZER; - -public: - pthread_mutex_t& native() { - return mutex_; - } - - bool open() { - int eno; - // init mutex - pthread_mutexattr_t mutex_attr; - if ((eno = ::pthread_mutexattr_init(&mutex_attr)) != 0) { - ipc::error("fail pthread_mutexattr_init[%d]\n", eno); - return false; - } - IPC_UNUSED_ auto guard_mutex_attr = unique_ptr(&mutex_attr, ::pthread_mutexattr_destroy); - if ((eno = ::pthread_mutexattr_setpshared(&mutex_attr, PTHREAD_PROCESS_SHARED)) != 0) { - ipc::error("fail pthread_mutexattr_setpshared[%d]\n", eno); - return false; - } - if ((eno = ::pthread_mutex_init(&mutex_, &mutex_attr)) != 0) { - ipc::error("fail pthread_mutex_init[%d]\n", eno); - return false; - } - return true; - } - - bool close() { - int eno; - if ((eno = ::pthread_mutex_destroy(&mutex_)) != 0) { - ipc::error("fail pthread_mutex_destroy[%d]\n", eno); - return false; - } - return true; - } - - bool lock() { - int eno; - if ((eno = ::pthread_mutex_lock(&mutex_)) != 0) { - ipc::error("fail pthread_mutex_lock[%d]\n", eno); - return false; - } - return true; - } - - bool unlock() { - int eno; - if ((eno = ::pthread_mutex_unlock(&mutex_)) != 0) { - ipc::error("fail pthread_mutex_unlock[%d]\n", eno); - return false; - } - return true; - } -}; - -class condition { - pthread_cond_t cond_ = PTHREAD_COND_INITIALIZER; - -public: - bool open() { - int eno; - // init condition - pthread_condattr_t cond_attr; - if ((eno = ::pthread_condattr_init(&cond_attr)) != 0) { - ipc::error("fail pthread_condattr_init[%d]\n", eno); - return false; - } - IPC_UNUSED_ auto guard_cond_attr = unique_ptr(&cond_attr, ::pthread_condattr_destroy); - if ((eno = ::pthread_condattr_setpshared(&cond_attr, PTHREAD_PROCESS_SHARED)) != 0) { - ipc::error("fail pthread_condattr_setpshared[%d]\n", eno); - return false; - } - if ((eno = ::pthread_cond_init(&cond_, &cond_attr)) != 0) { - ipc::error("fail pthread_cond_init[%d]\n", eno); - return false; - } - return true; - } - - bool close() { - int eno; - if ((eno = ::pthread_cond_destroy(&cond_)) != 0) { - ipc::error("fail pthread_cond_destroy[%d]\n", eno); - return false; - } - return true; - } - - bool wait(mutex& mtx) { - int eno; - if ((eno = ::pthread_cond_wait(&cond_, &mtx.native())) != 0) { - ipc::error("fail pthread_cond_wait[%d]\n", eno); - return false; - } - return true; - } - - bool notify() { - int eno; - if ((eno = ::pthread_cond_signal(&cond_)) != 0) { - ipc::error("fail pthread_cond_signal[%d]\n", eno); - return false; - } - return true; - } - - bool broadcast() { - int eno; - if ((eno = ::pthread_cond_broadcast(&cond_)) != 0) { - ipc::error("fail pthread_cond_broadcast[%d]\n", eno); - return false; - } - return true; - } -}; - class event { std::atomic* cnt_ = nullptr; semaphore::handle_t sem_ = semaphore::invalid(); @@ -198,7 +80,9 @@ class event { return "__IPC_WAIT__" + std::to_string(wait_id_); } - void open() { +public: + event(std::size_t id) + : wait_id_(static_cast>(id)) { auto n = name(); cnt_ = static_cast*>( shm::acquire(n.c_str(), sizeof(std::atomic))); @@ -206,27 +90,16 @@ class event { ipc::error("fail shm::acquire: %s\n", n.c_str()); return; } - if (cnt_->fetch_add(1, std::memory_order_acq_rel) == 0) { - sem_ = semaphore::open(n.c_str()); - } - } - - void close() { - semaphore::close(sem_); - if (cnt_->fetch_sub(1, std::memory_order_acq_rel) == 1) { - semaphore::destroy(name().c_str()); - } - shm::release(cnt_, sizeof(std::atomic)); - } - -public: - event(std::size_t id) - : wait_id_(static_cast>(id)) { - open(); + cnt_->fetch_add(1, std::memory_order_acquire); + sem_ = semaphore::open(n.c_str()); } ~event() { - close(); + semaphore::close(sem_); + if (cnt_->fetch_sub(1, std::memory_order_release) == 1) { + semaphore::destroy(name().c_str()); + } + shm::release(cnt_, sizeof(std::atomic)); } auto get_id() const noexcept { @@ -321,8 +194,7 @@ public: IPC_UNUSED_ auto guard = ipc::detail::unique_lock(evt_lc_); evt_ids_.for_acquired([this](auto id) { event evt { *static_cast(evt_ids_.at(id)) }; - evt.notify(); - return false; // return first + return !evt.notify(); // return if succ }); } diff --git a/test/test_waiter.cpp b/test/test_waiter.cpp new file mode 100644 index 0000000..5376c02 --- /dev/null +++ b/test/test_waiter.cpp @@ -0,0 +1,46 @@ +#include + +#include "platform/waiter_wrapper.h" +#include "test.h" + +namespace { + +class Unit : public TestSuite { + Q_OBJECT + + const char* name() const { + return "test_waiter"; + } + +private slots: + void test_wakeup(); +} unit__; + +#include "test_waiter.moc" + +void Unit::test_wakeup() { + ipc::detail::waiter w; + + std::thread t1 {[&w] { + ipc::detail::waiter_wrapper wp { &w }; + QVERIFY(wp.open("test-ipc-waiter")); + QVERIFY(wp.wait()); + }}; + + std::thread t2 {[&w] { + ipc::detail::waiter_wrapper wp { &w }; + QVERIFY(wp.open("test-ipc-waiter")); + QVERIFY(wp.wait()); + }}; + + ipc::detail::waiter_wrapper wp { &w }; + QVERIFY(wp.open("test-ipc-waiter")); + + std::this_thread::sleep_for(std::chrono::seconds(1)); + QVERIFY(wp.broadcast()); + + t1.join(); + t2.join(); +} + +} // internal-linkage