[TBD] add test-case; fix some bugs

This commit is contained in:
mutouyun 2019-01-28 10:38:09 +08:00
parent 018bea223e
commit 60276495b5
5 changed files with 89 additions and 143 deletions

View File

@ -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

View File

@ -18,12 +18,12 @@ namespace ipc {
namespace mem {
template <std::size_t Size>
using sync_fixed_alloc = synchronized<page_fixed_alloc<Size>>;
using sync_fixed_alloc = mem::synchronized<page_fixed_alloc<Size>>;
template <std::size_t Size>
using sync_fixed = mem::detail::fixed<Size, sync_fixed_alloc>;
using sync_pool_alloc = detail::pool_alloc<sync_fixed>;
using sync_pool_alloc = mem::detail::pool_alloc<sync_fixed>;
template <typename T>
using allocator = allocator_wrapper<T, sync_pool_alloc>;

View File

@ -199,5 +199,32 @@ public:
}
};
////////////////////////////////////////////////////////////////
/// Static allocation wrapper
////////////////////////////////////////////////////////////////
template <typename AllocP>
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

View File

@ -1,6 +1,5 @@
#pragma once
#include <pthread.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <semaphore.h>
@ -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<std::size_t>* 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<uint_t<16>>(id)) {
auto n = name();
cnt_ = static_cast<std::atomic<std::size_t>*>(
shm::acquire(n.c_str(), sizeof(std::atomic<std::size_t>)));
@ -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<std::size_t>));
}
public:
event(std::size_t id)
: wait_id_(static_cast<uint_t<16>>(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<std::size_t>));
}
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_id_t*>(evt_ids_.at(id)) };
evt.notify();
return false; // return first
return !evt.notify(); // return if succ
});
}

46
test/test_waiter.cpp Normal file
View File

@ -0,0 +1,46 @@
#include <thread>
#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