patterncppMinor
static_new and static_delete
Viewed 0 times
static_newstatic_deleteand
Problem
Here's a trick for preallocating some memory for some type
```
#include
#include
#include
#include
#include
#include
#include
namespace
{
template
struct static_store
{
static constexpr auto const max_instances =
::std::numeric_limits::digits * sizeof(A);
static void cleanup() { delete [] store_; }
#ifdef __GNUC__
template
static int ffz(U const v)
{
return __builtin_ctzll(~v);
}
#elif _MSC_VER && !__INTEL_COMPILER
template
static int ffz(U const v)
{
return ::std::numeric_limits::digits * sizeof(v) -
__lzcnt64(v & -v);
}
#elif __INTEL_COMPILER
template
static int ffz(U const v)
{
return _bit_scan_forward(~v);
}
#else
template
static int ffz(U v)
{
decltype(ffz()) b{};
for (; (v & 1); ++b)
{
v >>= 1;
}
return b;
}
#endif
static ::std::atomic_flag lock_;
static A memory_map_;
static typename ::std::aligned_storage::type* store_;
};
template
::std::atomic_flag static_store::lock_;
template
A static_store::memory_map_;
template
typename ::std::aligned_storage::type*
static_store::store_{(::std::atexit(static_store::cleanup),
new typename ::std::aligned_storage::type[static_store::max_instances])};
template
inline T* static_new(A&& ...args)
{
using static_store = static_store;
while (static_store::lock_.test_and_set(::std::memory_order_acquire))
{
::std::this_thread::yield();
}
auto const i(static_store::ffz(static_store::memory_map_));
auto p(new (&static_store::store_[i]) T(::std::forward(args)...));
static_store::memory_map_ |= 1ull
inline void static_delete(T* const p)
{
using static_store = static_store;
auto const i(p - static_cast(static_cast(
static_store::store_)));
//assert(!as_const(static_store::memory_map_)[i]);
while (st
T. Do there exist similar tricks? Improvements?```
#include
#include
#include
#include
#include
#include
#include
namespace
{
template
struct static_store
{
static constexpr auto const max_instances =
::std::numeric_limits::digits * sizeof(A);
static void cleanup() { delete [] store_; }
#ifdef __GNUC__
template
static int ffz(U const v)
{
return __builtin_ctzll(~v);
}
#elif _MSC_VER && !__INTEL_COMPILER
template
static int ffz(U const v)
{
return ::std::numeric_limits::digits * sizeof(v) -
__lzcnt64(v & -v);
}
#elif __INTEL_COMPILER
template
static int ffz(U const v)
{
return _bit_scan_forward(~v);
}
#else
template
static int ffz(U v)
{
decltype(ffz()) b{};
for (; (v & 1); ++b)
{
v >>= 1;
}
return b;
}
#endif
static ::std::atomic_flag lock_;
static A memory_map_;
static typename ::std::aligned_storage::type* store_;
};
template
::std::atomic_flag static_store::lock_;
template
A static_store::memory_map_;
template
typename ::std::aligned_storage::type*
static_store::store_{(::std::atexit(static_store::cleanup),
new typename ::std::aligned_storage::type[static_store::max_instances])};
template
inline T* static_new(A&& ...args)
{
using static_store = static_store;
while (static_store::lock_.test_and_set(::std::memory_order_acquire))
{
::std::this_thread::yield();
}
auto const i(static_store::ffz(static_store::memory_map_));
auto p(new (&static_store::store_[i]) T(::std::forward(args)...));
static_store::memory_map_ |= 1ull
inline void static_delete(T* const p)
{
using static_store = static_store;
auto const i(p - static_cast(static_cast(
static_store::store_)));
//assert(!as_const(static_store::memory_map_)[i]);
while (st
Solution
I still have trouble understanding how the whole works, but there are still some small things that could be improved:
-
In your comments, you say that
You could even make it an error to use a nonconforming type and create a
-
I got confused with these lines:
It is once again a naming problem: I had in mind the template parameter
-
You could probably slightly hide details and reduce the visual burden by using a
-
In your comments, you say that
A is an integer type used as a bitmask. The safest bitmask types are unsigned types or std::bitset. You should make this condition clear in your code, writetemplate
struct static_store { /* ... */ };You could even make it an error to use a nonconforming type and create a
is_bitmask trait, which would allow you to create a meaningful error message:static_assert(is_bitmask::value,
"the BitmaskType requirements are not satisfied");-
I got confused with these lines:
template
inline T* static_new(A&& ...args)It is once again a naming problem: I had in mind the template parameter
A from static_store. Since it represents arguments to be forwarding, you should just use the common convetion and name it Args instead. I don't know whether there are written guidelines to name variadic parameter packs, but Args is probably the name that I saw the most often.-
You could probably slightly hide details and reduce the visual burden by using a
typedef for the type of store_:using store_type = typename ::std::aligned_storage::type;Code Snippets
template <typename T, typename BitmaskType=unsigned>
struct static_store { /* ... */ };static_assert(is_bitmask<BitmaskType>::value,
"the BitmaskType requirements are not satisfied");template <typename T, typename ...A>
inline T* static_new(A&& ...args)using store_type = typename ::std::aligned_storage<sizeof(T), alignof(T)>::type;Context
StackExchange Code Review Q#31319, answer score: 8
Revisions (0)
No revisions yet.