fix tls bugs (win); modify data structure

This commit is contained in:
zhangyi 2019-07-04 16:37:00 +08:00
parent 9bc6604faa
commit 6b7c561496
39 changed files with 6296 additions and 6211 deletions

View File

@ -27,21 +27,21 @@ IPC_EXPORT void* get(key_t key);
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////
/* /*
<Remarks> * <Remarks>
*
1. In Windows, if you do not compile thread_local_ptr.cpp, * 1. In Windows, if you do not compile thread_local_ptr.cpp,
use thread_local_ptr will cause memory leaks. * use thread_local_ptr will cause memory leaks.
*
2. You need to set the thread_local_ptr's storage manually: * 2. You need to set the thread_local_ptr's storage manually:
``` * ```
thread_local_ptr<int> p; * tls::pointer<int> p;
if (!p) p = new int(123); * if (!p) p = new int(123);
``` * ```
Just like an ordinary pointer. Or you could just call create: * Just like an ordinary pointer. Or you could just call create:
``` * ```
thread_local_ptr<int> p; * tls::pointer<int> p;
p.create(123); * p.create(123);
``` * ```
*/ */
template <typename T> template <typename T>
@ -51,8 +51,8 @@ class pointer {
public: public:
using value_type = T; using value_type = T;
pointer() { pointer()
key_ = tls::create([](void* p) { delete static_cast<T*>(p); }); : key_(tls::create([](void* p) { delete static_cast<T*>(p); })) {
} }
~pointer() { ~pointer() {
@ -61,9 +61,13 @@ public:
template <typename... P> template <typename... P>
T* create(P&&... params) { T* create(P&&... params) {
thread_local auto ptr = static_cast<T*>(*this); thread_local auto ptr = static_cast<T*>(get(key_));
if (ptr == nullptr) { if (ptr == nullptr) {
return ptr = (*this) = new T(std::forward<P>(params)...); ptr = new T(std::forward<P>(params)...);
if (!set(key_, ptr)) {
delete ptr;
return nullptr;
}
} }
return ptr; return ptr;
} }

View File

@ -20,7 +20,7 @@ constexpr u1_t index_of(u2_t c) noexcept {
} }
class conn_head { class conn_head {
std::atomic<std::size_t> cc_ { 0 }; // connection counter std::atomic<u2_t> cc_ { 0 }; // connection counter
ipc::spin_lock lc_; ipc::spin_lock lc_;
std::atomic<bool> constructed_; std::atomic<bool> constructed_;

View File

@ -28,17 +28,17 @@
namespace { namespace {
using namespace ipc; using namespace ipc;
using msg_id_t = std::size_t; using msg_id_t = std::uint32_t;
template <std::size_t DataSize, std::size_t AlignSize> template <std::size_t DataSize, std::size_t AlignSize>
struct msg_t; struct msg_t;
template <std::size_t AlignSize> template <std::size_t AlignSize>
struct msg_t<0, AlignSize> { struct msg_t<0, AlignSize> {
msg_id_t conn_; msg_id_t conn_;
msg_id_t id_; msg_id_t id_;
int remain_; std::int32_t remain_;
bool storage_; bool storage_;
}; };
template <std::size_t DataSize, std::size_t AlignSize> template <std::size_t DataSize, std::size_t AlignSize>
@ -46,7 +46,7 @@ struct msg_t : msg_t<0, AlignSize> {
std::aligned_storage_t<DataSize, AlignSize> data_ {}; std::aligned_storage_t<DataSize, AlignSize> data_ {};
msg_t() = default; msg_t() = default;
msg_t(msg_id_t c, msg_id_t i, int r, void const * d, std::size_t s) msg_t(msg_id_t c, msg_id_t i, std::int32_t r, void const * d, std::size_t s)
: msg_t<0, AlignSize> { c, i, r, (d == nullptr) || (s == 0) } { : msg_t<0, AlignSize> { c, i, r, (d == nullptr) || (s == 0) } {
if (!this->storage_) { if (!this->storage_) {
std::memcpy(&data_, d, s); std::memcpy(&data_, d, s);
@ -367,7 +367,7 @@ static buff_t recv(ipc::handle_t h, std::size_t tm) {
continue; // ignore message to self continue; // ignore message to self
} }
// msg.remain_ may minus & abs(msg.remain_) < data_length // msg.remain_ may minus & abs(msg.remain_) < data_length
auto remain = static_cast<std::size_t>(static_cast<int>(data_length) + msg.remain_); auto remain = static_cast<std::size_t>(static_cast<std::int32_t>(data_length) + msg.remain_);
// find cache with msg.id_ // find cache with msg.id_
auto cac_it = rc.find(msg.id_); auto cac_it = rc.find(msg.id_);
if (cac_it == rc.end()) { if (cac_it == rc.end()) {

View File

@ -104,8 +104,8 @@ private:
public: public:
scope_alloc() = default; scope_alloc() = default;
scope_alloc(scope_alloc&& rhs) { swap(rhs); } scope_alloc(scope_alloc&& rhs) { swap(rhs); }
scope_alloc& operator=(scope_alloc&& rhs) { swap(rhs); return (*this); } scope_alloc& operator=(scope_alloc rhs) { swap(rhs); return (*this); }
~scope_alloc() { free_all(); } ~scope_alloc() { free_all(); }
@ -211,32 +211,33 @@ public:
} }
}; };
} // namespace detail
struct fixed_expand_policy { struct fixed_expand_policy {
enum : std::size_t { enum : std::size_t {
base_size = sizeof(void*) * 1024 / 2 base_size = sizeof(void*) * 1024
}; };
static std::size_t prev(std::size_t& e) { constexpr static std::size_t prev(std::size_t e) noexcept {
if ((e /= 2) == 0) e = 1; return ((e / 2) == 0) ? 1 : (e / 2);
return e;
} }
static std::size_t next(std::size_t& e) { constexpr static std::size_t next(std::size_t e) noexcept {
return e *= 2; return e * 2;
} }
template <std::size_t BlockSize> template <std::size_t BlockSize>
static std::size_t next(std::size_t & e) { static std::size_t next(std::size_t & e) {
return ipc::detail::max<std::size_t>(BlockSize, base_size) * next(e); auto n = ipc::detail::max<std::size_t>(BlockSize, base_size) * e;
e = next(e);
return n;
} }
}; };
} // namespace detail
template <std::size_t BlockSize, template <std::size_t BlockSize,
typename AllocP = scope_alloc<>, typename AllocP = scope_alloc<>,
typename ExpandP = detail::fixed_expand_policy> typename ExpandP = fixed_expand_policy>
class fixed_alloc : public detail::fixed_alloc_base { class fixed_alloc : public detail::fixed_alloc_base {
public: public:
using base_t = detail::fixed_alloc_base; using base_t = detail::fixed_alloc_base;
@ -266,7 +267,7 @@ public:
} }
fixed_alloc(fixed_alloc&& rhs) : fixed_alloc() { swap(rhs); } fixed_alloc(fixed_alloc&& rhs) : fixed_alloc() { swap(rhs); }
fixed_alloc& operator=(fixed_alloc&& rhs) { swap(rhs); return (*this); } fixed_alloc& operator=(fixed_alloc rhs) { swap(rhs); return (*this); }
template <typename A> template <typename A>
void set_allocator(A && alc) { void set_allocator(A && alc) {
@ -290,7 +291,7 @@ public:
} }
void clear() { void clear() {
ExpandP::prev(init_expand_); init_expand_ = ExpandP::prev(init_expand_);
cursor_ = nullptr; cursor_ = nullptr;
alloc_.~alloc_policy(); alloc_.~alloc_policy();
} }
@ -328,15 +329,15 @@ protected:
return reinterpret_cast<byte_t*>(p) + aligned_head_size + p->free_; return reinterpret_cast<byte_t*>(p) + aligned_head_size + p->free_;
} }
std::size_t remain() const noexcept {
return (head_ == nullptr) ? 0 : head_->free_;
}
public: public:
void swap(variable_alloc_base& rhs) { void swap(variable_alloc_base& rhs) {
std::swap(head_, rhs.head_); std::swap(head_, rhs.head_);
} }
std::size_t remain() const noexcept {
return (head_ == nullptr) ? 0 : head_->free_;
}
bool empty() const noexcept { bool empty() const noexcept {
return remain() == 0; return remain() == 0;
} }
@ -373,8 +374,8 @@ private:
public: public:
variable_alloc() = default; variable_alloc() = default;
variable_alloc(variable_alloc&& rhs) { swap(rhs); } variable_alloc(variable_alloc&& rhs) { swap(rhs); }
variable_alloc& operator=(variable_alloc&& rhs) { swap(rhs); return (*this); } variable_alloc& operator=(variable_alloc rhs) { swap(rhs); return (*this); }
template <typename A> template <typename A>
void set_allocator(A && alc) { void set_allocator(A && alc) {
@ -402,14 +403,14 @@ public:
} }
void* alloc(std::size_t size) { void* alloc(std::size_t size) {
if (size >= (ChunkSize - aligned_head_size)) { if (size >= ChunkSize) {
return alloc_.alloc(size); return alloc_.alloc(size);
} }
if (remain() < size) { if (remain() < size) {
auto it = reserves_.begin(); auto it = reserves_.begin();
if ((it == reserves_.end()) || (it->first < size)) { if ((it == reserves_.end()) || (it->first < size)) {
head_ = static_cast<head_t*>(alloc_.alloc(ChunkSize)); head_ = static_cast<head_t*>(alloc_.alloc(ChunkSize + aligned_head_size));
head_->free_ = ChunkSize - aligned_head_size - size; head_->free_ = ChunkSize - size;
} }
else { else {
auto temp = it->second; auto temp = it->second;

12
src/memory/resource.h Executable file → Normal file
View File

@ -17,12 +17,18 @@
namespace ipc { namespace ipc {
namespace mem { namespace mem {
using chunk_variable_alloc = variable_alloc<sizeof(void*) * 256 * 1024 /* 2MB(x64) */>; namespace detail {
using chunk_variable_alloc =
static_wrapper<async_wrapper<variable_alloc<
sizeof(void*) * 1024 * 256 /* 2MB(x64) */ >>>;
template <std::size_t Size> template <std::size_t Size>
using static_async_fixed = static_wrapper<async_wrapper<fixed_alloc<Size, chunk_variable_alloc>>>; using static_async_fixed =
static_wrapper<async_wrapper<fixed_alloc<
Size, chunk_variable_alloc >>>;
using async_pool_alloc = static_alloc/*variable_wrapper<static_async_fixed>*/; using async_pool_alloc = /*static_alloc*/variable_wrapper<static_async_fixed>;
template <typename T> template <typename T>
using allocator = allocator_wrapper<T, async_pool_alloc>; using allocator = allocator_wrapper<T, async_pool_alloc>;

View File

@ -131,7 +131,7 @@ constexpr bool operator!=(const allocator_wrapper<T, AllocP>&, const allocator_w
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////
template <typename AllocP> template <typename AllocP>
class default_alloc_recoverer { class default_alloc_recycler {
public: public:
using alloc_policy = AllocP; using alloc_policy = AllocP;
@ -139,8 +139,11 @@ private:
ipc::spin_lock master_lock_; ipc::spin_lock master_lock_;
std::vector<alloc_policy> master_allocs_; std::vector<alloc_policy> master_allocs_;
IPC_CONCEPT_(has_remain, remain());
IPC_CONCEPT_(has_empty , empty());
public: public:
void swap(default_alloc_recoverer& rhs) { void swap(default_alloc_recycler& rhs) {
IPC_UNUSED_ auto guard = ipc::detail::unique_lock(master_lock_); IPC_UNUSED_ auto guard = ipc::detail::unique_lock(master_lock_);
master_allocs_.swap(rhs.master_allocs_); master_allocs_.swap(rhs.master_allocs_);
} }
@ -159,7 +162,9 @@ public:
} }
template <typename A = AllocP> template <typename A = AllocP>
auto try_replenish(alloc_policy & alc) -> ipc::require<detail::has_take<A>::value> { auto try_replenish(alloc_policy & alc, std::size_t size)
-> ipc::require<detail::has_take<A>::value && has_remain<A>::value> {
if (alc.remain() >= size) return;
IPC_UNUSED_ auto guard = ipc::detail::unique_lock(master_lock_); IPC_UNUSED_ auto guard = ipc::detail::unique_lock(master_lock_);
if (!master_allocs_.empty()) { if (!master_allocs_.empty()) {
alc.take(std::move(master_allocs_.back())); alc.take(std::move(master_allocs_.back()));
@ -168,8 +173,19 @@ public:
} }
template <typename A = AllocP> template <typename A = AllocP>
constexpr auto try_replenish(alloc_policy & /*alc*/) noexcept auto try_replenish(alloc_policy & alc, std::size_t /*size*/)
-> ipc::require<!detail::has_take<A>::value> {} -> ipc::require<detail::has_take<A>::value && !has_remain<A>::value && has_empty<A>::value> {
if (!alc.empty()) return;
IPC_UNUSED_ auto guard = ipc::detail::unique_lock(master_lock_);
if (!master_allocs_.empty()) {
alc.take(std::move(master_allocs_.back()));
master_allocs_.pop_back();
}
}
template <typename A = AllocP>
constexpr auto try_replenish(alloc_policy & /*alc*/, std::size_t /*size*/) noexcept
-> ipc::require<!detail::has_take<A>::value || (!has_remain<A>::value && !has_empty<A>::value)> {}
void collect(alloc_policy && alc) { void collect(alloc_policy && alc) {
IPC_UNUSED_ auto guard = ipc::detail::unique_lock(master_lock_); IPC_UNUSED_ auto guard = ipc::detail::unique_lock(master_lock_);
@ -177,20 +193,30 @@ public:
} }
}; };
template <typename AllocP>
class empty_alloc_recycler {
public:
using alloc_policy = AllocP;
constexpr static void swap(empty_alloc_recycler&) noexcept {}
constexpr static void clear() noexcept {}
constexpr static void try_recover(alloc_policy&) noexcept {}
constexpr static auto try_replenish(alloc_policy&, std::size_t) noexcept {}
constexpr static void collect(alloc_policy&&) noexcept {}
};
template <typename AllocP, template <typename AllocP,
template <typename> class RecovererP = default_alloc_recoverer> template <typename> class RecyclerP = default_alloc_recycler>
class async_wrapper { class async_wrapper {
public: public:
using alloc_policy = AllocP; using alloc_policy = AllocP;
private: private:
RecovererP<alloc_policy> recoverer_; RecyclerP<alloc_policy> recycler_;
class alloc_proxy : public AllocP { class alloc_proxy : public AllocP {
async_wrapper * w_ = nullptr; async_wrapper * w_ = nullptr;
IPC_CONCEPT_(has_empty, empty());
public: public:
alloc_proxy(alloc_proxy && rhs) alloc_proxy(alloc_proxy && rhs)
: AllocP(std::move(rhs)) : AllocP(std::move(rhs))
@ -199,25 +225,18 @@ private:
alloc_proxy(async_wrapper* w) alloc_proxy(async_wrapper* w)
: AllocP(), w_(w) { : AllocP(), w_(w) {
if (w_ == nullptr) return; if (w_ == nullptr) return;
w_->recoverer_.try_recover(*this); w_->recycler_.try_recover(*this);
} }
~alloc_proxy() { ~alloc_proxy() {
if (w_ == nullptr) return; if (w_ == nullptr) return;
w_->recoverer_.collect(std::move(*this)); w_->recycler_.collect(std::move(*this));
} }
template <typename A = AllocP> auto alloc(std::size_t size) {
auto alloc(std::size_t size) -> ipc::require<has_empty<A>::value, void*> { if (w_ != nullptr) {
auto p = AllocP::alloc(size); w_->recycler_.try_replenish(*this, size);
if (AllocP::empty() && (w_ != nullptr)) {
w_->recoverer_.try_replenish(*this);
} }
return p;
}
template <typename A = AllocP>
auto alloc(std::size_t size) -> ipc::require<!has_empty<A>::value, void*> {
return AllocP::alloc(size); return AllocP::alloc(size);
} }
}; };
@ -231,11 +250,11 @@ private:
public: public:
void swap(async_wrapper& rhs) { void swap(async_wrapper& rhs) {
recoverer_.swap(rhs.recoverer_); recycler_.swap(rhs.recycler_);
} }
void clear() { void clear() {
recoverer_.clear(); recycler_.clear();
} }
void* alloc(std::size_t size) { void* alloc(std::size_t size) {
@ -326,10 +345,15 @@ struct default_mapping_policy {
static const std::size_t table[classes_size]; static const std::size_t table[classes_size];
constexpr static std::size_t classify(std::size_t size) { IPC_CONSTEXPR_ static std::size_t classify(std::size_t size) noexcept {
return (((size - 1) / base_size) < classes_size) ? auto index = (size - 1) / base_size;
return (index < classes_size) ?
// always uses default_mapping_policy<sizeof(void*)>::table // always uses default_mapping_policy<sizeof(void*)>::table
default_mapping_policy<>::table[((size - 1) / base_size)] : classes_size; default_mapping_policy<>::table[index] : classes_size;
}
constexpr static std::size_t block_size(std::size_t value) noexcept {
return (value + 1) * base_size;
} }
}; };
@ -350,7 +374,7 @@ class variable_wrapper {
template <typename F> template <typename F>
constexpr static auto choose(std::size_t size, F&& f) { constexpr static auto choose(std::size_t size, F&& f) {
return ipc::detail::static_switch<MappingP::classes_size>(MappingP::classify(size), [&f](auto index) { return ipc::detail::static_switch<MappingP::classes_size>(MappingP::classify(size), [&f](auto index) {
return f(Fixed<(decltype(index)::value + 1) * MappingP::base_size>{}); return f(Fixed<MappingP::block_size(decltype(index)::value)>{});
}, [&f] { }, [&f] {
return f(StaticAlloc{}); return f(StaticAlloc{});
}); });
@ -361,7 +385,7 @@ public:
static void clear() { static void clear() {
ipc::detail::static_for<MappingP::classes_size>([](auto index) { ipc::detail::static_for<MappingP::classes_size>([](auto index) {
Fixed<(decltype(index)::value + 1) * MappingP::base_size>::clear(); Fixed<MappingP::block_size(decltype(index)::value)>::clear();
}); });
StaticAlloc::clear(); StaticAlloc::clear();
} }

View File

@ -1,7 +1,9 @@
#include "tls_pointer.h" #include "tls_pointer.h"
#include "log.h"
#include <Windows.h> // ::Tls... #include <Windows.h> // ::Tls...
#include <unordered_map> // std::unordered_map #include <atomic>
#include <unordered_set> // std::unordered_set
namespace ipc { namespace ipc {
@ -23,77 +25,125 @@ namespace {
struct tls_data { struct tls_data {
using destructor_t = void(*)(void*); using destructor_t = void(*)(void*);
using map_t = std::unordered_map<tls::key_t, tls_data>;
static DWORD& key() { DWORD win_key_;
static DWORD rec_key = ::TlsAlloc(); destructor_t destructor_;
return rec_key;
}
static map_t* records(map_t* rec) { void destruct(void* data) {
::TlsSetValue(key(), static_cast<LPVOID>(rec)); if ((destructor_ != nullptr) && (data != nullptr)) {
return rec; destructor_(data);
} }
static map_t* records() {
return static_cast<map_t*>(::TlsGetValue(key()));
}
tls::key_t key_ = tls::invalid_value;
destructor_t destructor_ = nullptr;
tls_data() = default;
tls_data(tls::key_t key, destructor_t destructor)
: key_ (key)
, destructor_(destructor)
{}
tls_data(tls_data&& rhs) : tls_data() {
(*this) = std::move(rhs);
}
tls_data& operator=(tls_data&& rhs) {
key_ = rhs.key_;
destructor_ = rhs.destructor_;
rhs.key_ = 0;
rhs.destructor_ = nullptr;
return *this;
}
~tls_data() {
if (destructor_) destructor_(tls::get(key_));
} }
}; };
using rec_t = std::unordered_set<tls_data*>;
DWORD& record_key() {
struct key_gen {
DWORD rec_key_;
key_gen() : rec_key_(::TlsAlloc()) {
if (rec_key_ == TLS_OUT_OF_INDEXES) {
ipc::error("[record_key] TlsAlloc failed[%lu].\n", ::GetLastError());
}
}
~key_gen() { ::TlsFree(rec_key_); }
};
static key_gen gen;
return gen.rec_key_;
}
bool record(tls_data* tls) {
auto rec = static_cast<rec_t*>(::TlsGetValue(record_key()));
if (rec == nullptr) {
if (FALSE == ::TlsSetValue(record_key(), static_cast<LPVOID>(rec = new rec_t))) {
ipc::error("[record] TlsSetValue failed[%lu].\n", ::GetLastError());
return false;
}
}
rec->insert(tls);
return true;
}
static void erase_record(tls_data* tls) {
auto rec = static_cast<rec_t*>(::TlsGetValue(record_key()));
if (rec == nullptr) return;
rec->erase(tls);
}
static void clear_all_records() {
auto rec = static_cast<rec_t*>(::TlsGetValue(record_key()));
if (rec == nullptr) return;
for (auto tls : *rec) {
if (tls != nullptr) {
tls->destruct(::TlsGetValue(tls->win_key_));
}
}
delete rec;
::TlsSetValue(record_key(), static_cast<LPVOID>(nullptr));
}
} // internal-linkage } // internal-linkage
namespace tls { namespace tls {
key_t create(destructor_t destructor) { key_t create(destructor_t destructor) {
key_t key = static_cast<key_t>(::TlsAlloc()); record_key(); // gen record-key
if (key == TLS_OUT_OF_INDEXES) return invalid_value; auto tls_dat = new tls_data { ::TlsAlloc(), destructor };
auto rec = tls_data::records(); std::atomic_thread_fence(std::memory_order_seq_cst);
if (rec == nullptr) rec = tls_data::records(new tls_data::map_t); if (tls_dat->win_key_ == TLS_OUT_OF_INDEXES) {
if (rec == nullptr) return key; ipc::error("[tls::create] TlsAlloc failed[%lu].\n", ::GetLastError());
rec->emplace(key, tls_data{ key, destructor }); delete tls_dat;
return key; return invalid_value;
}
return reinterpret_cast<key_t>(tls_dat);
} }
void release(key_t key) { void release(key_t tls_key) {
auto rec = tls_data::records(); if (tls_key == invalid_value) {
if (rec == nullptr) return; ipc::error("[tls::release] tls_key is invalid_value.\n");
rec->erase(key); return;
::TlsFree(static_cast<DWORD>(key)); }
auto tls_dat = reinterpret_cast<tls_data*>(tls_key);
if (tls_dat == nullptr) {
ipc::error("[tls::release] tls_dat is nullptr.\n");
return;
}
erase_record(tls_dat);
::TlsFree(tls_dat->win_key_);
delete tls_dat;
} }
bool set(key_t key, void* ptr) { bool set(key_t tls_key, void* ptr) {
return ::TlsSetValue(static_cast<DWORD>(key), if (tls_key == invalid_value) {
static_cast<LPVOID>(ptr)) == TRUE; ipc::error("[tls::set] tls_key is invalid_value.\n");
return false;
}
auto tls_dat = reinterpret_cast<tls_data*>(tls_key);
if (tls_dat == nullptr) {
ipc::error("[tls::set] tls_dat is nullptr.\n");
return false;
}
if (FALSE == ::TlsSetValue(tls_dat->win_key_, static_cast<LPVOID>(ptr))) {
ipc::error("[tls::set] TlsSetValue failed[%lu].\n", ::GetLastError());
return false;
}
record(tls_dat);
return true;
} }
void* get(key_t key) { void* get(key_t tls_key) {
return static_cast<void*>(::TlsGetValue(static_cast<DWORD>(key))); if (tls_key == invalid_value) {
ipc::error("[tls::get] tls_key is invalid_value.\n");
return nullptr;
}
auto tls_dat = reinterpret_cast<tls_data*>(tls_key);
if (tls_dat == nullptr) {
ipc::error("[tls::get] tls_dat is nullptr.\n");
return nullptr;
}
return ::TlsGetValue(tls_dat->win_key_);
} }
} // namespace tls } // namespace tls
@ -101,10 +151,7 @@ void* get(key_t key) {
namespace { namespace {
void OnThreadExit() { void OnThreadExit() {
auto rec = tls_data::records(); clear_all_records();
if (rec == nullptr) return;
delete rec;
tls_data::records(nullptr);
} }
void NTAPI OnTlsCallback(PVOID, DWORD dwReason, PVOID) { void NTAPI OnTlsCallback(PVOID, DWORD dwReason, PVOID) {

View File

@ -174,7 +174,7 @@ struct prod_cons_impl<wr<relat::multi , relat::multi, trans::unicast>>
template <> template <>
struct prod_cons_impl<wr<relat::single, relat::multi, trans::broadcast>> { struct prod_cons_impl<wr<relat::single, relat::multi, trans::broadcast>> {
using rc_t = std::size_t; using rc_t = std::uint32_t;
template <std::size_t DataSize, std::size_t AlignSize> template <std::size_t DataSize, std::size_t AlignSize>
struct elem_t { struct elem_t {

View File

@ -238,7 +238,7 @@ private slots:
void test_prod_cons_1v3(); void test_prod_cons_1v3();
void test_prod_cons_performance(); void test_prod_cons_performance();
void test_queue(); void test_queue();
} /*unit__*/; } unit__;
#include "test_circ.moc" #include "test_circ.moc"

0
test/test_ipc.cpp Executable file → Normal file
View File

11
test/test_mem.cpp Executable file → Normal file
View File

@ -25,7 +25,7 @@ private slots:
void test_alloc_free(); void test_alloc_free();
void test_static(); void test_static();
void test_pool(); void test_pool();
} /*unit__*/; } unit__;
#include "test_mem.moc" #include "test_mem.moc"
@ -178,9 +178,12 @@ void Unit::test_static() {
} }
void Unit::test_pool() { void Unit::test_pool() {
test_performance<ipc::mem::pool_alloc, alloc_FIFO , 8>::start(); // test_performance<ipc::mem::pool_alloc, alloc_FIFO , 8>::start();
test_performance<ipc::mem::pool_alloc, alloc_LIFO , 8>::start(); // for (;;) {
test_performance<ipc::mem::pool_alloc, alloc_random, 8>::start(); test_performance<ipc::mem::pool_alloc, alloc_FIFO , 8>::start();
test_performance<ipc::mem::pool_alloc, alloc_LIFO , 8>::start();
test_performance<ipc::mem::pool_alloc, alloc_random, 8>::start();
// }
} }
} // internal-linkage } // internal-linkage