add IPC_CONSTEXPR_;

add variable_wrapper instead of fixed_alloc_policy
This commit is contained in:
zhangyi 2019-07-01 17:28:02 +08:00
parent 4aecd5b28b
commit 15e71bd1a1
8 changed files with 94 additions and 110 deletions

View File

@ -22,7 +22,6 @@ HEADERS += \
../../include/tls_pointer.h \
../../include/pool_alloc.h \
../../include/buffer.h \
../../src/memory/detail.h \
../../src/memory/alloc.h \
../../src/memory/wrapper.h \
../../src/memory/resource.h \

View File

@ -91,13 +91,15 @@ struct conn_info_head {
shm::handle acc_h_;
/*
<Remarks> thread_local may have some bugs.
See: https://sourceforge.net/p/mingw-w64/bugs/727/
https://sourceforge.net/p/mingw-w64/bugs/527/
https://github.com/Alexpux/MINGW-packages/issues/2519
https://github.com/ChaiScript/ChaiScript/issues/402
https://developercommunity.visualstudio.com/content/problem/124121/thread-local-variables-fail-to-be-initialized-when.html
https://software.intel.com/en-us/forums/intel-c-compiler/topic/684827
* <Remarks> thread_local may have some bugs.
*
* <Reference>
* - https://sourceforge.net/p/mingw-w64/bugs/727/
* - https://sourceforge.net/p/mingw-w64/bugs/527/
* - https://github.com/Alexpux/MINGW-packages/issues/2519
* - https://github.com/ChaiScript/ChaiScript/issues/402
* - https://developercommunity.visualstudio.com/content/problem/124121/thread-local-variables-fail-to-be-initialized-when.html
* - https://software.intel.com/en-us/forums/intel-c-compiler/topic/684827
*/
tls::pointer<ipc::unordered_map<msg_id_t, cache_t>> recv_cache_;

View File

@ -1,72 +0,0 @@
#pragma once
#include <cstddef>
#include "memory/alloc.h"
#include "platform/detail.h"
namespace ipc {
namespace mem {
namespace detail {
enum : std::size_t {
base_size = sizeof(void*)
};
#if __cplusplus >= 201703L
constexpr std::size_t classify(std::size_t size) {
constexpr std::size_t mapping[] = {
#else /*__cplusplus < 201703L*/
inline std::size_t classify(std::size_t size) {
static const std::size_t mapping[] = {
#endif/*__cplusplus < 201703L*/
/* 1 */
0 , 1 , 2 , 3 ,
/* 2 */
5 , 5 , 7 , 7 ,
9 , 9 , 11, 11,
13, 13, 15, 15,
/* 4 */
19, 19, 19, 19,
23, 23, 23, 23,
27, 27, 27, 27,
31, 31, 31, 31
};
size = (size - 1) / base_size;
#if __cplusplus >= 201703L
return (size < std::size(mapping)) ? mapping[size] : 32;
#else /*__cplusplus < 201703L*/
return (size < (sizeof(mapping) / sizeof(mapping[0]))) ? mapping[size] : 32;
#endif/*__cplusplus < 201703L*/
}
template <template <std::size_t> class Fixed, typename F>
decltype(auto) choose(std::size_t size, F&& f) {
return ipc::detail::static_switch<32>(classify(size), [&f](auto index) {
return f(Fixed<(decltype(index)::value + 1) * base_size>::instance());
}, [&f] {
return f(static_alloc{});
});
}
template <template <std::size_t> class Fixed>
class fixed_alloc_policy {
public:
static void clear() {
ipc::detail::static_for<32>([](auto index) {
Fixed<(decltype(index)::value + 1) * base_size>::instance().clear();
});
}
static void* alloc(std::size_t size) {
return choose<Fixed>(size, [size](auto&& fp) { return fp.alloc(size); });
}
static void free(void* p, std::size_t size) {
choose<Fixed>(size, [p](auto&& fp) { fp.free(p); });
}
};
} // namespace detail
} // namespace mem
} // namespace ipc

View File

@ -12,15 +12,14 @@
#include "memory/alloc.h"
#include "memory/wrapper.h"
#include "memory/detail.h"
#include "platform/detail.h"
namespace ipc {
namespace mem {
template <std::size_t Size>
using static_async_fixed = mem::static_wrapper<mem::async_wrapper<mem::fixed_alloc<Size>>>;
using async_pool_alloc = mem::detail::fixed_alloc_policy<static_async_fixed>;
using static_async_fixed = static_wrapper<async_wrapper<fixed_alloc<Size>>>;
using async_pool_alloc = variable_wrapper<static_async_fixed>;
template <typename T>
using allocator = allocator_wrapper<T, async_pool_alloc>;

View File

@ -13,6 +13,8 @@
#include "def.h"
#include "rw_lock.h"
#include "tls_pointer.h"
#include "memory/alloc.h"
#include "platform/detail.h"
namespace ipc {
@ -181,12 +183,8 @@ public:
return get_alloc().alloc(size);
}
void free(void* p) {
get_alloc().free(p);
}
void free(void* p, std::size_t /*size*/) {
free(p);
void free(void* p, std::size_t size) {
get_alloc().free(p, size);
}
};
@ -217,5 +215,63 @@ public:
}
};
////////////////////////////////////////////////////////////////
/// Variable memory allocation wrapper
////////////////////////////////////////////////////////////////
template <std::size_t BaseSize = sizeof(void*)>
struct default_mapping_policy {
enum : std::size_t {
base_size = BaseSize,
classes_size = 32
};
static const std::size_t table[classes_size];
constexpr static std::size_t classify(std::size_t size) {
return (((size - 1) / base_size) < classes_size) ? table[((size - 1) / base_size)] : classes_size;
}
};
template <std::size_t B>
const std::size_t default_mapping_policy<B>::table[default_mapping_policy<B>::classes_size] = {
/* 1 - 8 ~ 32 */
0 , 1 , 2 , 3 ,
/* 2 - 48 ~ 256 */
5 , 5 , 7 , 7 , 9 , 9 , 11, 11, 13, 13, 15, 15, 17, 17,
19, 19, 21, 21, 23, 23, 25, 25, 27, 27, 29, 29, 31, 31
};
template <template <std::size_t> class Fixed,
typename StaticAlloc = mem::static_alloc,
typename MappingP = default_mapping_policy<>>
class variable_wrapper {
template <typename 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 f(Fixed<(decltype(index)::value + 1) * MappingP::base_size>{});
}, [&f] {
return f(StaticAlloc{});
});
}
public:
static void clear() {
ipc::detail::static_for<MappingP::classes_size>([](auto index) {
Fixed<(decltype(index)::value + 1) * MappingP::base_size>::clear();
});
}
static void* alloc(std::size_t size) {
return choose(size, [size](auto&& alc) { return alc.alloc(size); });
}
static void free(void* p, std::size_t size) {
choose(size, [p, size](auto&& alc) { alc.free(p, size); });
}
};
} // namespace mem
} // namespace ipc

View File

@ -24,12 +24,16 @@
#ifdef IPC_STBIND_
# error "IPC_STBIND_ has been defined."
#endif
#ifdef IPC_CONSTEXPR_
# error "IPC_CONSTEXPR_ has been defined."
#endif
#if __cplusplus >= 201703L
#define IPC_UNUSED_ [[maybe_unused]]
#define IPC_FALLTHROUGH_ [[fallthrough]]
#define IPC_STBIND_(A, B, ...) auto [A, B] = __VA_ARGS__
#define IPC_CONSTEXPR_ constexpr
#else /*__cplusplus < 201703L*/
@ -48,6 +52,8 @@
auto A = std::get<0>(tp___); \
auto B = std::get<1>(tp___)
#define IPC_CONSTEXPR_ inline
#endif/*__cplusplus < 201703L*/
#if __cplusplus >= 201703L
@ -121,20 +127,12 @@ constexpr decltype(auto) static_switch(std::size_t i, F&& f, D&& def) {
}
template <typename F, std::size_t...I>
#if __cplusplus >= 201703L
constexpr void static_for(std::index_sequence<I...>, F&& f) {
#else /*__cplusplus < 201703L*/
inline void static_for(std::index_sequence<I...>, F&& f) {
#endif/*__cplusplus < 201703L*/
IPC_CONSTEXPR_ void static_for(std::index_sequence<I...>, F&& f) {
IPC_UNUSED_ auto expand = { (std::forward<F>(f)(std::integral_constant<size_t, I>{}), 0)... };
}
template <std::size_t N, typename F>
#if __cplusplus >= 201703L
constexpr void static_for(F&& f) {
#else /*__cplusplus < 201703L*/
inline void static_for(F&& f) {
#endif/*__cplusplus < 201703L*/
IPC_CONSTEXPR_ void static_for(F&& f) {
static_for(std::make_index_sequence<N>{}, std::forward<F>(f));
}

View File

@ -6,15 +6,17 @@
namespace ipc {
/*
<Remarks>
Windows doesn't support a per-thread destructor with its TLS primitives.
So, here will build it manually by inserting a function to be called on each thread's exit.
See: https://www.codeproject.com/Articles/8113/Thread-Local-Storage-The-C-Way
https://src.chromium.org/viewvc/chrome/trunk/src/base/threading/thread_local_storage_win.cc
https://github.com/mirror/mingw-org-wsl/blob/master/src/libcrt/crt/tlssup.c
https://github.com/Alexpux/mingw-w64/blob/master/mingw-w64-crt/crt/tlssup.c
http://svn.boost.org/svn/boost/trunk/libs/thread/src/win32/tss_pe.cpp
* <Remarks>
*
* Windows doesn't support a per-thread destructor with its TLS primitives.
* So, here will build it manually by inserting a function to be called on each thread's exit.
*
* <Reference>
* - https://www.codeproject.com/Articles/8113/Thread-Local-Storage-The-C-Way
* - https://src.chromium.org/viewvc/chrome/trunk/src/base/threading/thread_local_storage_win.cc
* - https://github.com/mirror/mingw-org-wsl/blob/master/src/libcrt/crt/tlssup.c
* - https://github.com/Alexpux/mingw-w64/blob/master/mingw-w64-crt/crt/tlssup.c
* - http://svn.boost.org/svn/boost/trunk/libs/thread/src/win32/tss_pe.cpp
*/
namespace {

View File

@ -25,13 +25,13 @@ private slots:
void test_alloc_free();
void test_static();
void test_pool();
} /*unit__*/;
} unit__;
#include "test_mem.moc"
constexpr int DataMin = sizeof(void*);
constexpr int DataMax = sizeof(void*) * 16;
constexpr int LoopCount = 10000000;
constexpr int LoopCount = 1000000;
std::vector<std::size_t> sizes__;