mirror of
https://github.com/mutouyun/cpp-ipc.git
synced 2025-12-07 01:06:45 +08:00
Revert "update IPC_CONCEPT_"
This reverts commit 1e5547e6dfd0605fa62be67899c6c893aa61f9fc.
This commit is contained in:
parent
54bc3386dd
commit
ff488e002f
@ -44,8 +44,7 @@ constexpr std::size_t aligned(std::size_t size, size_t alignment) noexcept {
|
|||||||
return ( (size - 1) & ~(alignment - 1) ) + alignment;
|
return ( (size - 1) & ~(alignment - 1) ) + alignment;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
IPC_CONCEPT_(has_take, take(std::move(std::declval<Type>())));
|
||||||
IPC_CONCEPT_(has_take, require<T>([](auto && t)->decltype(t.take(std::move(t))) {}));
|
|
||||||
|
|
||||||
class scope_alloc_base {
|
class scope_alloc_base {
|
||||||
protected:
|
protected:
|
||||||
@ -117,13 +116,13 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename A = AllocP>
|
template <typename A = AllocP>
|
||||||
auto take(scope_alloc && rhs) -> std::enable_if_t<detail::has_take<A>::value> {
|
auto take(scope_alloc && rhs) -> ipc::require<detail::has_take<A>::value> {
|
||||||
base_t::take(std::move(rhs));
|
base_t::take(std::move(rhs));
|
||||||
alloc_.take(std::move(rhs.alloc_));
|
alloc_.take(std::move(rhs.alloc_));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename A = AllocP>
|
template <typename A = AllocP>
|
||||||
auto take(scope_alloc && rhs) -> std::enable_if_t<!detail::has_take<A>::value> {
|
auto take(scope_alloc && rhs) -> ipc::require<!detail::has_take<A>::value> {
|
||||||
base_t::take(std::move(rhs));
|
base_t::take(std::move(rhs));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -256,7 +255,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename A = AllocP>
|
template <typename A = AllocP>
|
||||||
auto take(fixed_alloc && rhs) -> std::enable_if_t<detail::has_take<A>::value> {
|
auto take(fixed_alloc && rhs) -> ipc::require<detail::has_take<A>::value> {
|
||||||
base_t::take(std::move(rhs));
|
base_t::take(std::move(rhs));
|
||||||
alloc_.take(std::move(rhs.alloc_));
|
alloc_.take(std::move(rhs.alloc_));
|
||||||
}
|
}
|
||||||
@ -395,7 +394,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename A = AllocP>
|
template <typename A = AllocP>
|
||||||
auto take(variable_alloc && rhs) -> std::enable_if_t<detail::has_take<A>::value> {
|
auto take(variable_alloc && rhs) -> ipc::require<detail::has_take<A>::value> {
|
||||||
base_t::take(std::move(rhs));
|
base_t::take(std::move(rhs));
|
||||||
alloc_.take(std::move(rhs.alloc_));
|
alloc_.take(std::move(rhs.alloc_));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -27,8 +27,7 @@ namespace mem {
|
|||||||
|
|
||||||
namespace detail {
|
namespace detail {
|
||||||
|
|
||||||
template <typename T>
|
IPC_CONCEPT_(is_comparable, operator<(std::declval<Type>()));
|
||||||
IPC_CONCEPT_(is_comparable, require<const T>([](auto && t)->decltype(t < t) {}));
|
|
||||||
|
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
|
|
||||||
@ -72,10 +71,8 @@ public:
|
|||||||
template <typename AllocP>
|
template <typename AllocP>
|
||||||
class default_recycler : public limited_recycler<AllocP> {
|
class default_recycler : public limited_recycler<AllocP> {
|
||||||
|
|
||||||
template <typename T>
|
IPC_CONCEPT_(has_remain, remain());
|
||||||
IPC_CONCEPT_(has_remain, require<const T>([](auto && t)->decltype(t.remain()) {}));
|
IPC_CONCEPT_(has_empty , empty());
|
||||||
template <typename T>
|
|
||||||
IPC_CONCEPT_(has_empty, require<const T>([](auto && t)->decltype(t.empty()) {}));
|
|
||||||
|
|
||||||
template <typename A>
|
template <typename A>
|
||||||
void try_fill(A & alc) {
|
void try_fill(A & alc) {
|
||||||
@ -89,28 +86,28 @@ public:
|
|||||||
|
|
||||||
template <typename A = AllocP>
|
template <typename A = AllocP>
|
||||||
auto try_replenish(alloc_policy & alc, std::size_t size)
|
auto try_replenish(alloc_policy & alc, std::size_t size)
|
||||||
-> std::enable_if_t<detail::has_take<A>::value && has_remain<A>::value> {
|
-> ipc::require<detail::has_take<A>::value && has_remain<A>::value> {
|
||||||
if (alc.remain() >= size) return;
|
if (alc.remain() >= size) return;
|
||||||
this->try_fill(alc);
|
this->try_fill(alc);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename A = AllocP>
|
template <typename A = AllocP>
|
||||||
auto try_replenish(alloc_policy & alc, std::size_t /*size*/)
|
auto try_replenish(alloc_policy & alc, std::size_t /*size*/)
|
||||||
-> std::enable_if_t<detail::has_take<A>::value && !has_remain<A>::value && has_empty<A>::value> {
|
-> ipc::require<detail::has_take<A>::value && !has_remain<A>::value && has_empty<A>::value> {
|
||||||
if (!alc.empty()) return;
|
if (!alc.empty()) return;
|
||||||
this->try_fill(alc);
|
this->try_fill(alc);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename A = AllocP>
|
template <typename A = AllocP>
|
||||||
auto try_replenish(alloc_policy & alc, std::size_t /*size*/)
|
auto try_replenish(alloc_policy & alc, std::size_t /*size*/)
|
||||||
-> std::enable_if_t<!detail::has_take<A>::value && has_empty<A>::value> {
|
-> ipc::require<!detail::has_take<A>::value && has_empty<A>::value> {
|
||||||
if (!alc.empty()) return;
|
if (!alc.empty()) return;
|
||||||
this->try_recover(alc);
|
this->try_recover(alc);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename A = AllocP>
|
template <typename A = AllocP>
|
||||||
IPC_CONSTEXPR_ auto try_replenish(alloc_policy & /*alc*/, std::size_t /*size*/) noexcept
|
IPC_CONSTEXPR_ auto try_replenish(alloc_policy & /*alc*/, std::size_t /*size*/) noexcept
|
||||||
-> std::enable_if_t<(!detail::has_take<A>::value || !has_remain<A>::value) && !has_empty<A>::value> {
|
-> ipc::require<(!detail::has_take<A>::value || !has_remain<A>::value) && !has_empty<A>::value> {
|
||||||
// Do Nothing.
|
// Do Nothing.
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@ -7,6 +7,7 @@
|
|||||||
* @remarks
|
* @remarks
|
||||||
* Windows doesn't support a per-thread destructor with its TLS primitives.
|
* 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.
|
* So, here will build it manually by inserting a function to be called on each thread's exit.
|
||||||
|
*
|
||||||
* @see
|
* @see
|
||||||
* - https://www.codeproject.com/Articles/8113/Thread-Local-Storage-The-C-Way
|
* - 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://src.chromium.org/viewvc/chrome/trunk/src/base/threading/thread_local_storage_win.cc
|
||||||
|
|||||||
@ -15,14 +15,19 @@
|
|||||||
namespace ipc {
|
namespace ipc {
|
||||||
namespace detail {
|
namespace detail {
|
||||||
|
|
||||||
|
struct has_value_type_ {
|
||||||
|
template <typename T> static std::true_type check(typename T::value_type *);
|
||||||
|
template <typename T> static std::false_type check(...);
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T, typename U, typename = decltype(has_value_type_::check<U>(nullptr))>
|
||||||
|
struct is_same_char : std::is_same<T, U> {};
|
||||||
|
|
||||||
template <typename T, typename U>
|
template <typename T, typename U>
|
||||||
IPC_CONCEPT_(has_same_char,
|
struct is_same_char<T, U, std::true_type> : std::is_same<T, typename U::value_type> {};
|
||||||
require([]()->std::enable_if_t<std::is_same<T, typename U::value_type>::value> {}) ||
|
|
||||||
require([]()->std::enable_if_t<std::is_same<T, U>::value> {})
|
|
||||||
);
|
|
||||||
|
|
||||||
template <typename T, typename S, typename R = S>
|
template <typename T, typename S, typename R = S>
|
||||||
using IsSameChar = std::enable_if_t<has_same_char<T, S>::value, R>;
|
using IsSameChar = ipc::require<is_same_char<T, S>::value, R>;
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////
|
||||||
/// to_tchar implementation
|
/// to_tchar implementation
|
||||||
|
|||||||
@ -1,42 +1,29 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <type_traits> // std::declval
|
#include <type_traits> // std::enable_if
|
||||||
|
|
||||||
namespace ipc {
|
namespace ipc {
|
||||||
|
|
||||||
/**
|
// concept helpers
|
||||||
* @remarks
|
|
||||||
* <<Concepts emulation>> Concepts TS Improve on C++17
|
|
||||||
* @see
|
|
||||||
* - http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0726r0.html
|
|
||||||
* - https://www.youtube.com/watch?v=TorW5ekkL_w
|
|
||||||
*/
|
|
||||||
namespace detail {
|
|
||||||
|
|
||||||
template <typename F, typename... Args,
|
template <bool Cond, typename R = void>
|
||||||
typename = decltype(std::declval<F&&>()(std::declval<Args&&>()...))>
|
using require = typename std::enable_if<Cond, R>::type;
|
||||||
constexpr bool require_impl(int) { return true; }
|
|
||||||
|
|
||||||
template <typename F, typename... Args>
|
|
||||||
constexpr bool require_impl(...) { return false; }
|
|
||||||
|
|
||||||
} // namespace detail
|
|
||||||
|
|
||||||
template <typename... Args, typename F>
|
|
||||||
constexpr bool require(F&&) {
|
|
||||||
return detail::require_impl<F&&, Args&&...>(int{});
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace ipc
|
|
||||||
|
|
||||||
/// concept helpers
|
|
||||||
|
|
||||||
#ifdef IPC_CONCEPT_
|
#ifdef IPC_CONCEPT_
|
||||||
# error "IPC_CONCEPT_ has been defined."
|
# error "IPC_CONCEPT_ has been defined."
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define IPC_CONCEPT_($$name, $$what) \
|
#define IPC_CONCEPT_(NAME, WHAT) \
|
||||||
class $$name { \
|
template <typename T> \
|
||||||
|
class NAME { \
|
||||||
|
private: \
|
||||||
|
template <typename Type> \
|
||||||
|
static std::true_type check(decltype(std::declval<Type>().WHAT)*); \
|
||||||
|
template <typename Type> \
|
||||||
|
static std::false_type check(...); \
|
||||||
public: \
|
public: \
|
||||||
constexpr static bool value = $$what; \
|
using type = decltype(check<T>(nullptr)); \
|
||||||
|
constexpr static auto value = type::value; \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace ipc
|
||||||
|
|||||||
@ -8,19 +8,14 @@
|
|||||||
|
|
||||||
namespace ipc {
|
namespace ipc {
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
IPC_CONCEPT_(is_impl_comfortable,
|
|
||||||
require<T>([](auto && t)->std::enable_if_t<(sizeof(t) <= sizeof(T*))> {})
|
|
||||||
);
|
|
||||||
|
|
||||||
template <typename T, typename R = T*>
|
|
||||||
using IsImplComfortable = std::enable_if_t<is_impl_comfortable<T>::value, R>;
|
|
||||||
|
|
||||||
template <typename T, typename R = T*>
|
|
||||||
using IsImplUncomfortable = std::enable_if_t<!is_impl_comfortable<T>::value, R>;
|
|
||||||
|
|
||||||
// pimpl small object optimization helpers
|
// pimpl small object optimization helpers
|
||||||
|
|
||||||
|
template <typename T, typename R = T*>
|
||||||
|
using IsImplComfortable = ipc::require<(sizeof(T) <= sizeof(T*)), R>;
|
||||||
|
|
||||||
|
template <typename T, typename R = T*>
|
||||||
|
using IsImplUncomfortable = ipc::require<(sizeof(T) > sizeof(T*)), R>;
|
||||||
|
|
||||||
template <typename T, typename... P>
|
template <typename T, typename... P>
|
||||||
constexpr auto make_impl(P&&... params) -> IsImplComfortable<T> {
|
constexpr auto make_impl(P&&... params) -> IsImplComfortable<T> {
|
||||||
T* buf {};
|
T* buf {};
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user