mirror of
https://github.com/mutouyun/cpp-ipc.git
synced 2025-12-07 01:06:45 +08:00
add error log (TBD); use pthread api for waiter
This commit is contained in:
parent
3c6ba58b41
commit
99926581d1
@ -32,7 +32,8 @@ HEADERS += \
|
|||||||
../src/circ/elem_array.h \
|
../src/circ/elem_array.h \
|
||||||
../src/prod_cons.h \
|
../src/prod_cons.h \
|
||||||
../src/policy.h \
|
../src/policy.h \
|
||||||
../src/queue.h
|
../src/queue.h \
|
||||||
|
../src/log.h
|
||||||
|
|
||||||
SOURCES += \
|
SOURCES += \
|
||||||
../src/shm.cpp \
|
../src/shm.cpp \
|
||||||
|
|||||||
@ -131,7 +131,7 @@ public:
|
|||||||
|
|
||||||
void lock() noexcept {
|
void lock() noexcept {
|
||||||
for (unsigned k = 0;;) {
|
for (unsigned k = 0;;) {
|
||||||
auto old = lc_.fetch_or(w_flag, std::memory_order_acquire);
|
auto old = lc_.fetch_or(w_flag, std::memory_order_acq_rel);
|
||||||
if (!old) return; // got w-lock
|
if (!old) return; // got w-lock
|
||||||
if (!(old & w_flag)) break; // other thread having r-lock
|
if (!(old & w_flag)) break; // other thread having r-lock
|
||||||
yield(k); // other thread having w-lock
|
yield(k); // other thread having w-lock
|
||||||
@ -147,7 +147,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
void lock_shared() noexcept {
|
void lock_shared() noexcept {
|
||||||
auto old = lc_.load(std::memory_order_relaxed);
|
auto old = lc_.load(std::memory_order_acquire);
|
||||||
for (unsigned k = 0;;) {
|
for (unsigned k = 0;;) {
|
||||||
// if w_flag set, just continue
|
// if w_flag set, just continue
|
||||||
if (old & w_flag) {
|
if (old & w_flag) {
|
||||||
@ -155,7 +155,7 @@ public:
|
|||||||
old = lc_.load(std::memory_order_acquire);
|
old = lc_.load(std::memory_order_acquire);
|
||||||
}
|
}
|
||||||
// otherwise try cas lc + 1 (set r-lock)
|
// otherwise try cas lc + 1 (set r-lock)
|
||||||
else if (lc_.compare_exchange_weak(old, old + 1, std::memory_order_acquire)) {
|
else if (lc_.compare_exchange_weak(old, old + 1, std::memory_order_release)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// set r-lock failed, old has been updated
|
// set r-lock failed, old has been updated
|
||||||
|
|||||||
@ -55,7 +55,6 @@ public:
|
|||||||
if (!constructed_.load(std::memory_order_relaxed)) {
|
if (!constructed_.load(std::memory_order_relaxed)) {
|
||||||
::new (this) conn_head;
|
::new (this) conn_head;
|
||||||
constructed_.store(true, std::memory_order_release);
|
constructed_.store(true, std::memory_order_release);
|
||||||
::printf("init...\n");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
13
src/log.h
Normal file
13
src/log.h
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstdio>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
namespace ipc {
|
||||||
|
|
||||||
|
template <typename... P>
|
||||||
|
void log(char const * fmt, P&&... params) {
|
||||||
|
std::fprintf(stderr, fmt, std::forward<P>(params)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace ipc
|
||||||
@ -163,7 +163,7 @@ public:
|
|||||||
if (p == nullptr) return;
|
if (p == nullptr) return;
|
||||||
while (1) {
|
while (1) {
|
||||||
next(p) = cursor_.load(std::memory_order_acquire);
|
next(p) = cursor_.load(std::memory_order_acquire);
|
||||||
if (cursor_.compare_exchange_weak(next(p), p, std::memory_order_relaxed)) {
|
if (cursor_.compare_exchange_weak(next(p), p, std::memory_order_release)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
std::this_thread::yield();
|
std::this_thread::yield();
|
||||||
@ -242,7 +242,7 @@ public:
|
|||||||
void* p;
|
void* p;
|
||||||
while (1) {
|
while (1) {
|
||||||
p = expand();
|
p = expand();
|
||||||
if (this->cursor_.compare_exchange_weak(p, this->next(p), std::memory_order_relaxed)) {
|
if (this->cursor_.compare_exchange_weak(p, this->next(p), std::memory_order_release)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
std::this_thread::yield();
|
std::this_thread::yield();
|
||||||
|
|||||||
@ -5,6 +5,7 @@
|
|||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
#include <string>
|
#include <string>
|
||||||
@ -12,6 +13,7 @@
|
|||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
|
||||||
#include "def.h"
|
#include "def.h"
|
||||||
|
#include "log.h"
|
||||||
#include "memory/resource.h"
|
#include "memory/resource.h"
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
@ -49,10 +51,12 @@ void* acquire(char const * name, std::size_t size) {
|
|||||||
S_IRGRP | S_IWGRP |
|
S_IRGRP | S_IWGRP |
|
||||||
S_IROTH | S_IWOTH);
|
S_IROTH | S_IWOTH);
|
||||||
if (fd == -1) {
|
if (fd == -1) {
|
||||||
|
ipc::log("fail shm_open[%d]: %s\n", errno, name);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
size += sizeof(acc_t);
|
size += sizeof(acc_t);
|
||||||
if (::ftruncate(fd, static_cast<off_t>(size)) != 0) {
|
if (::ftruncate(fd, static_cast<off_t>(size)) != 0) {
|
||||||
|
ipc::log("fail ftruncate[%d]: %s\n", errno, name);
|
||||||
::close(fd);
|
::close(fd);
|
||||||
::shm_unlink(op_name.c_str());
|
::shm_unlink(op_name.c_str());
|
||||||
return nullptr;
|
return nullptr;
|
||||||
@ -60,6 +64,7 @@ void* acquire(char const * name, std::size_t size) {
|
|||||||
void* mem = ::mmap(nullptr, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
|
void* mem = ::mmap(nullptr, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
|
||||||
::close(fd);
|
::close(fd);
|
||||||
if (mem == MAP_FAILED) {
|
if (mem == MAP_FAILED) {
|
||||||
|
ipc::log("fail mmap[%d]: %s\n", errno, name);
|
||||||
::shm_unlink(op_name.c_str());
|
::shm_unlink(op_name.c_str());
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -7,7 +7,7 @@
|
|||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
|
||||||
#include "def.h"
|
#include "def.h"
|
||||||
|
#include "log.h"
|
||||||
#include "memory/resource.h"
|
#include "memory/resource.h"
|
||||||
#include "platform/to_tchar.h"
|
#include "platform/to_tchar.h"
|
||||||
|
|
||||||
@ -35,10 +35,12 @@ void* acquire(char const * name, std::size_t size) {
|
|||||||
0, static_cast<DWORD>(size),
|
0, static_cast<DWORD>(size),
|
||||||
ipc::detail::to_tchar(std::string{"__IPC_SHM__"} + name).c_str());
|
ipc::detail::to_tchar(std::string{"__IPC_SHM__"} + name).c_str());
|
||||||
if (h == NULL) {
|
if (h == NULL) {
|
||||||
|
ipc::log("fail CreateFileMapping[%d]: %s\n", static_cast<int>(::GetLastError()), name);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
LPVOID mem = ::MapViewOfFile(h, FILE_MAP_ALL_ACCESS, 0, 0, 0);
|
LPVOID mem = ::MapViewOfFile(h, FILE_MAP_ALL_ACCESS, 0, 0, 0);
|
||||||
if (mem == NULL) {
|
if (mem == NULL) {
|
||||||
|
ipc::log("fail MapViewOfFile[%d]: %s\n", static_cast<int>(::GetLastError()), name);
|
||||||
::CloseHandle(h);
|
::CloseHandle(h);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,85 +1,109 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <fcntl.h>
|
#include <pthread.h>
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <semaphore.h>
|
|
||||||
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
|
|
||||||
#include "def.h"
|
#include "def.h"
|
||||||
#include "rw_lock.h"
|
#include "log.h"
|
||||||
|
|
||||||
#include "platform/detail.h"
|
#include "platform/detail.h"
|
||||||
|
|
||||||
namespace ipc {
|
namespace ipc {
|
||||||
namespace detail {
|
namespace detail {
|
||||||
|
|
||||||
class waiter {
|
class waiter {
|
||||||
std::atomic<unsigned> rc_ { 0 };
|
pthread_mutex_t mutex_ = PTHREAD_MUTEX_INITIALIZER;
|
||||||
|
pthread_cond_t cond_ = PTHREAD_COND_INITIALIZER;
|
||||||
std::atomic<unsigned> counter_ { 0 };
|
std::atomic<unsigned> counter_ { 0 };
|
||||||
|
|
||||||
spin_lock lc_;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
using handle_t = sem_t*;
|
using handle_t = bool;
|
||||||
|
|
||||||
private:
|
|
||||||
bool post(handle_t h) {
|
|
||||||
for (unsigned k = 0;;) {
|
|
||||||
auto c = counter_.load(std::memory_order_acquire);
|
|
||||||
if (c == 0) return false;
|
|
||||||
if (counter_.compare_exchange_weak(c, c - 1, std::memory_order_relaxed)) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
ipc::yield(k);
|
|
||||||
}
|
|
||||||
return ::sem_post(h) == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
constexpr static handle_t invalid() {
|
constexpr static handle_t invalid() {
|
||||||
return SEM_FAILED;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
handle_t open(char const * name) {
|
handle_t open(char const * name) {
|
||||||
if (name == nullptr || name[0] == '\0') return invalid();
|
if (name == nullptr || name[0] == '\0') return invalid();
|
||||||
rc_.fetch_add(1, std::memory_order_relaxed);
|
if (counter_.fetch_add(1, std::memory_order_acq_rel) == 0) {
|
||||||
std::atomic_thread_fence(std::memory_order_release);
|
int eno;
|
||||||
return ::sem_open(name, O_CREAT | O_RDWR,
|
// init mutex
|
||||||
S_IRUSR | S_IWUSR |
|
pthread_mutexattr_t mutex_attr;
|
||||||
S_IRGRP | S_IWGRP |
|
if ((eno = ::pthread_mutexattr_init(&mutex_attr)) != 0) {
|
||||||
S_IROTH | S_IWOTH, 0);
|
ipc::log("fail pthread_mutexattr_init[%d]: %s\n", eno, name);
|
||||||
|
return invalid();
|
||||||
|
}
|
||||||
|
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::log("fail pthread_mutexattr_setpshared[%d]: %s\n", eno, name);
|
||||||
|
return invalid();
|
||||||
|
}
|
||||||
|
if ((eno = ::pthread_mutex_init(&mutex_, &mutex_attr)) != 0) {
|
||||||
|
ipc::log("fail pthread_mutex_init[%d]: %s\n", eno, name);
|
||||||
|
return invalid();
|
||||||
|
}
|
||||||
|
auto guard_mutex = unique_ptr(&mutex_, ::pthread_mutex_destroy);
|
||||||
|
// init condition
|
||||||
|
pthread_condattr_t cond_attr;
|
||||||
|
if ((eno = ::pthread_condattr_init(&cond_attr)) != 0) {
|
||||||
|
ipc::log("fail pthread_condattr_init[%d]: %s\n", eno, name);
|
||||||
|
return invalid();
|
||||||
|
}
|
||||||
|
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::log("fail pthread_condattr_setpshared[%d]: %s\n", eno, name);
|
||||||
|
return invalid();
|
||||||
|
}
|
||||||
|
if ((eno = ::pthread_cond_init(&cond_, &cond_attr)) != 0) {
|
||||||
|
ipc::log("fail pthread_cond_init[%d]: %s\n", eno, name);
|
||||||
|
return invalid();
|
||||||
|
}
|
||||||
|
// no need to guard condition
|
||||||
|
// release guards
|
||||||
|
guard_mutex.release();
|
||||||
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void close(handle_t h, char const * name) {
|
void close(handle_t h) {
|
||||||
if (h == invalid()) return;
|
if (h == invalid()) return;
|
||||||
if (name == nullptr || name[0] == '\0') return;
|
if (counter_.fetch_sub(1, std::memory_order_acq_rel) == 1) {
|
||||||
::sem_close(h);
|
::pthread_cond_destroy(&cond_);
|
||||||
if (rc_.fetch_sub(1, std::memory_order_acquire) == 1) {
|
::pthread_mutex_destroy(&mutex_);
|
||||||
::sem_unlink(name);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool wait(handle_t h) {
|
bool wait(handle_t h) {
|
||||||
if (h == invalid()) return false;
|
if (h == invalid()) return false;
|
||||||
{
|
int eno;
|
||||||
IPC_UNUSED_ auto guard = ipc::detail::unique_lock(lc_);
|
if ((eno = ::pthread_mutex_lock(&mutex_)) != 0) {
|
||||||
counter_.fetch_add(1, std::memory_order_relaxed);
|
ipc::log("fail pthread_mutex_lock[%d]\n", eno);
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
bool ret = (::sem_wait(h) == 0);
|
IPC_UNUSED_ auto guard = unique_ptr(&mutex_, ::pthread_mutex_unlock);
|
||||||
return ret;
|
if ((eno = ::pthread_cond_wait(&cond_, &mutex_)) != 0) {
|
||||||
|
ipc::log("fail pthread_cond_wait[%d]\n", eno);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void notify(handle_t h) {
|
void notify(handle_t h) {
|
||||||
if (h == invalid()) return;
|
if (h == invalid()) return;
|
||||||
post(h);
|
int eno;
|
||||||
|
if ((eno = ::pthread_cond_signal(&cond_)) != 0) {
|
||||||
|
ipc::log("fail pthread_cond_signal[%d]\n", eno);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void broadcast(handle_t h) {
|
void broadcast(handle_t h) {
|
||||||
if (h == invalid()) return;
|
if (h == invalid()) return;
|
||||||
IPC_UNUSED_ auto guard = ipc::detail::unique_lock(lc_);
|
int eno;
|
||||||
while (post(h)) ;
|
if ((eno = ::pthread_cond_broadcast(&cond_)) != 0) {
|
||||||
|
ipc::log("fail pthread_cond_broadcast[%d]\n", eno);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -27,7 +27,7 @@ public:
|
|||||||
return ::CreateSemaphore(NULL, 0, LONG_MAX, ipc::detail::to_tchar(name).c_str());
|
return ::CreateSemaphore(NULL, 0, LONG_MAX, ipc::detail::to_tchar(name).c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
void close(handle_t h, char const * /*name*/) {
|
void close(handle_t h) {
|
||||||
if (h == invalid()) return;
|
if (h == invalid()) return;
|
||||||
::CloseHandle(h);
|
::CloseHandle(h);
|
||||||
}
|
}
|
||||||
@ -44,7 +44,7 @@ public:
|
|||||||
for (unsigned k = 0;;) {
|
for (unsigned k = 0;;) {
|
||||||
auto c = counter_.load(std::memory_order_acquire);
|
auto c = counter_.load(std::memory_order_acquire);
|
||||||
if (c == 0) return;
|
if (c == 0) return;
|
||||||
if (counter_.compare_exchange_weak(c, c - 1, std::memory_order_relaxed)) {
|
if (counter_.compare_exchange_weak(c, c - 1, std::memory_order_release)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
ipc::yield(k);
|
ipc::yield(k);
|
||||||
|
|||||||
@ -20,7 +20,6 @@ public:
|
|||||||
private:
|
private:
|
||||||
waiter_t* w_ = nullptr;
|
waiter_t* w_ = nullptr;
|
||||||
waiter_t::handle_t h_ = waiter_t::invalid();
|
waiter_t::handle_t h_ = waiter_t::invalid();
|
||||||
std::string n_;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
waiter_wrapper() = default;
|
waiter_wrapper() = default;
|
||||||
@ -44,15 +43,13 @@ public:
|
|||||||
bool open(char const * name) {
|
bool open(char const * name) {
|
||||||
if (w_ == nullptr) return false;
|
if (w_ == nullptr) return false;
|
||||||
close();
|
close();
|
||||||
h_ = w_->open((n_ = name).c_str());
|
h_ = w_->open(name);
|
||||||
::printf("%s: %p\n", name, h_);
|
|
||||||
return valid();
|
return valid();
|
||||||
}
|
}
|
||||||
|
|
||||||
void close() {
|
void close() {
|
||||||
if (!valid()) return;
|
if (!valid()) return;
|
||||||
::printf("close %s: %p\n", n_.c_str(), h_);
|
w_->close(h_);
|
||||||
w_->close(h_, n_.c_str());
|
|
||||||
h_ = waiter_t::invalid();
|
h_ = waiter_t::invalid();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -41,8 +41,8 @@ struct prod_cons_impl<prod_cons<relat::single, relat::single, trans::unicast>> {
|
|||||||
|
|
||||||
template <typename E, typename F, typename EB>
|
template <typename E, typename F, typename EB>
|
||||||
bool push(E* /*elems*/, F&& f, EB* elem_start) {
|
bool push(E* /*elems*/, F&& f, EB* elem_start) {
|
||||||
auto cur_wt = circ::index_of(wt_.load(std::memory_order_acquire));
|
auto cur_wt = circ::index_of(wt_.load(std::memory_order_relaxed));
|
||||||
if (cur_wt == circ::index_of(rd_.load(std::memory_order_relaxed) - 1)) {
|
if (cur_wt == circ::index_of(rd_.load(std::memory_order_acquire) - 1)) {
|
||||||
return false; // full
|
return false; // full
|
||||||
}
|
}
|
||||||
std::forward<F>(f)(elem_start + cur_wt);
|
std::forward<F>(f)(elem_start + cur_wt);
|
||||||
@ -52,8 +52,8 @@ struct prod_cons_impl<prod_cons<relat::single, relat::single, trans::unicast>> {
|
|||||||
|
|
||||||
template <typename E, typename F, typename EB>
|
template <typename E, typename F, typename EB>
|
||||||
bool pop(E* /*elems*/, circ::u2_t& /*cur*/, F&& f, EB* elem_start) {
|
bool pop(E* /*elems*/, circ::u2_t& /*cur*/, F&& f, EB* elem_start) {
|
||||||
auto cur_rd = circ::index_of(rd_.load(std::memory_order_acquire));
|
auto cur_rd = circ::index_of(rd_.load(std::memory_order_relaxed));
|
||||||
if (cur_rd == circ::index_of(wt_.load(std::memory_order_relaxed))) {
|
if (cur_rd == circ::index_of(wt_.load(std::memory_order_acquire))) {
|
||||||
return false; // empty
|
return false; // empty
|
||||||
}
|
}
|
||||||
std::forward<F>(f)(elem_start + cur_rd);
|
std::forward<F>(f)(elem_start + cur_rd);
|
||||||
@ -70,9 +70,9 @@ struct prod_cons_impl<prod_cons<relat::single, relat::multi , trans::unicast>>
|
|||||||
bool pop(E* /*elems*/, circ::u2_t& /*cur*/, F&& f, EB* elem_start) {
|
bool pop(E* /*elems*/, circ::u2_t& /*cur*/, F&& f, EB* elem_start) {
|
||||||
byte_t buff[sizeof(E)];
|
byte_t buff[sizeof(E)];
|
||||||
for (unsigned k = 0;;) {
|
for (unsigned k = 0;;) {
|
||||||
auto cur_rd = rd_.load(std::memory_order_acquire);
|
auto cur_rd = rd_.load(std::memory_order_relaxed);
|
||||||
if (circ::index_of(cur_rd) ==
|
if (circ::index_of(cur_rd) ==
|
||||||
circ::index_of(wt_.load(std::memory_order_relaxed))) {
|
circ::index_of(wt_.load(std::memory_order_acquire))) {
|
||||||
return false; // empty
|
return false; // empty
|
||||||
}
|
}
|
||||||
std::memcpy(buff, elem_start + circ::index_of(cur_rd), sizeof(buff));
|
std::memcpy(buff, elem_start + circ::index_of(cur_rd), sizeof(buff));
|
||||||
@ -95,12 +95,12 @@ struct prod_cons_impl<prod_cons<relat::multi , relat::multi, trans::unicast>>
|
|||||||
bool push(E* /*elems*/, F&& f, EB* elem_start) {
|
bool push(E* /*elems*/, F&& f, EB* elem_start) {
|
||||||
circ::u2_t cur_ct, nxt_ct;
|
circ::u2_t cur_ct, nxt_ct;
|
||||||
while(1) {
|
while(1) {
|
||||||
cur_ct = ct_.load(std::memory_order_acquire);
|
cur_ct = ct_.load(std::memory_order_relaxed);
|
||||||
if (circ::index_of(nxt_ct = cur_ct + 1) ==
|
if (circ::index_of(nxt_ct = cur_ct + 1) ==
|
||||||
circ::index_of(rd_.load(std::memory_order_relaxed))) {
|
circ::index_of(rd_.load(std::memory_order_acquire))) {
|
||||||
return false; // full
|
return false; // full
|
||||||
}
|
}
|
||||||
if (ct_.compare_exchange_weak(cur_ct, nxt_ct, std::memory_order_relaxed)) {
|
if (ct_.compare_exchange_weak(cur_ct, nxt_ct, std::memory_order_release)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
std::this_thread::yield();
|
std::this_thread::yield();
|
||||||
@ -141,14 +141,14 @@ struct prod_cons_impl<prod_cons<relat::single, relat::multi, trans::broadcast>>
|
|||||||
|
|
||||||
template <typename E, typename F, typename EB>
|
template <typename E, typename F, typename EB>
|
||||||
bool push(E* elems, F&& f, EB* elem_start) {
|
bool push(E* elems, F&& f, EB* elem_start) {
|
||||||
auto conn_cnt = elems->conn_count(); // acquire
|
auto conn_cnt = elems->conn_count(std::memory_order_relaxed);
|
||||||
if (conn_cnt == 0) return false;
|
if (conn_cnt == 0) return false;
|
||||||
auto el = elem_start + circ::index_of(wt_.load(std::memory_order_relaxed));
|
auto el = elem_start + circ::index_of(wt_.load(std::memory_order_acquire));
|
||||||
// check all consumers have finished reading this element
|
// check all consumers have finished reading this element
|
||||||
while(1) {
|
while(1) {
|
||||||
rc_t expected = 0;
|
rc_t expected = 0;
|
||||||
if (el->head_.rc_.compare_exchange_weak(
|
if (el->head_.rc_.compare_exchange_weak(
|
||||||
expected, static_cast<rc_t>(conn_cnt), std::memory_order_relaxed)) {
|
expected, static_cast<rc_t>(conn_cnt), std::memory_order_release)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
std::this_thread::yield();
|
std::this_thread::yield();
|
||||||
@ -187,16 +187,16 @@ struct prod_cons_impl<prod_cons<relat::multi , relat::multi, trans::broadcast>>
|
|||||||
|
|
||||||
template <typename E, typename F, typename EB>
|
template <typename E, typename F, typename EB>
|
||||||
bool push(E* elems, F&& f, EB* elem_start) {
|
bool push(E* elems, F&& f, EB* elem_start) {
|
||||||
auto conn_cnt = elems->conn_count(); // acquire
|
auto conn_cnt = elems->conn_count(std::memory_order_relaxed);
|
||||||
if (conn_cnt == 0) return false;
|
if (conn_cnt == 0) return false;
|
||||||
circ::u2_t cur_ct = ct_.fetch_add(1, std::memory_order_relaxed),
|
circ::u2_t cur_ct = ct_.fetch_add(1, std::memory_order_acquire),
|
||||||
nxt_ct = cur_ct + 1;
|
nxt_ct = cur_ct + 1;
|
||||||
auto el = elem_start + circ::index_of(cur_ct);
|
auto el = elem_start + circ::index_of(cur_ct);
|
||||||
// check all consumers have finished reading this element
|
// check all consumers have finished reading this element
|
||||||
while(1) {
|
while(1) {
|
||||||
rc_t expected = 0;
|
rc_t expected = 0;
|
||||||
if (el->head_.rc_.compare_exchange_weak(
|
if (el->head_.rc_.compare_exchange_weak(
|
||||||
expected, static_cast<rc_t>(conn_cnt), std::memory_order_relaxed)) {
|
expected, static_cast<rc_t>(conn_cnt), std::memory_order_release)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
std::this_thread::yield();
|
std::this_thread::yield();
|
||||||
|
|||||||
@ -311,10 +311,10 @@ void test_lock_performance() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Unit::test_rw_lock() {
|
void Unit::test_rw_lock() {
|
||||||
test_lock_performance<1, 1>();
|
// test_lock_performance<1, 1>();
|
||||||
test_lock_performance<4, 4>();
|
// test_lock_performance<4, 4>();
|
||||||
test_lock_performance<1, 8>();
|
// test_lock_performance<1, 8>();
|
||||||
test_lock_performance<8, 1>();
|
// test_lock_performance<8, 1>();
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T, int N, int M, bool V = true, int Loops = LoopCount>
|
template <typename T, int N, int M, bool V = true, int Loops = LoopCount>
|
||||||
@ -338,6 +338,7 @@ void Unit::test_route() {
|
|||||||
ipc::route cc { "my-ipc-route" };
|
ipc::route cc { "my-ipc-route" };
|
||||||
for (std::size_t i = 0; i < datas.size(); ++i) {
|
for (std::size_t i = 0; i < datas.size(); ++i) {
|
||||||
ipc::buff_t dd = cc.recv();
|
ipc::buff_t dd = cc.recv();
|
||||||
|
std::cout << "recv: " << (char*)dd.data() << std::endl;
|
||||||
QCOMPARE(dd.size(), std::strlen(datas[i]) + 1);
|
QCOMPARE(dd.size(), std::strlen(datas[i]) + 1);
|
||||||
QVERIFY(std::memcmp(dd.data(), datas[i], dd.size()) == 0);
|
QVERIFY(std::memcmp(dd.data(), datas[i], dd.size()) == 0);
|
||||||
}
|
}
|
||||||
@ -356,8 +357,6 @@ void Unit::test_route() {
|
|||||||
|
|
||||||
t1.join();
|
t1.join();
|
||||||
t2.join();
|
t2.join();
|
||||||
|
|
||||||
test_prod_cons<ipc::route, 1, 1>();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Unit::test_route_rtt() {
|
void Unit::test_route_rtt() {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user