-
Notifications
You must be signed in to change notification settings - Fork 0
/
lib.h
129 lines (89 loc) · 3.4 KB
/
lib.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
#pragma once
//#define USE_DEBUG
#include <cstddef>
#include <memory>
namespace Zeropimpl {
// Memory layout is next:
// sizeof(size_t) - size of private data
// sizeof(Private) - instance private data memory
// sizeof(size_t) - size of private data (again)
// size - instance memory
template <typename T>
void * alloc(std::size_t size)
{
typedef typename T::Private Private;
constexpr std::size_t sizeo = sizeof(std::size_t);
constexpr std::size_t sizep = sizeof(Private);
uint8_t * const data = static_cast<uint8_t*>(std::malloc(sizeo + sizep + sizeo + size));
reinterpret_cast<std::size_t&>(*data) = sizep;
reinterpret_cast<std::size_t&>(*(data + sizeo + sizep)) = sizep;
void * const i = data + sizeo + sizep + sizeo;
Private * const p = new (data + sizeo) Private;
#ifdef USE_DEBUG
std::printf("%s %d class=%p private=%p sizep=%d\n", __PRETTY_FUNCTION__, int(size), i, p, int(sizep));
std::fflush(stdout);
#endif
return i;
}
template <typename T>
void free(void * const ptr)
{
typedef typename T::Private Private;
constexpr std::size_t sizeo = sizeof(std::size_t);
constexpr std::size_t sizep = sizeof(Private);
uint8_t * const data = static_cast<uint8_t*>(ptr) - sizeo - sizep - sizeo;
Private * const p = reinterpret_cast<Private*>(data + sizeo);
p->~Private();
std::free(data);
#ifdef USE_DEBUG
std::printf("%s class=%p private=%p\n", __PRETTY_FUNCTION__, ptr, p);
std::fflush(stdout);
#endif
}
template <typename T>
static const T & fromPrivate(const typename T::Private & p)
{
typedef typename T::Private Private;
constexpr std::size_t sizeo = sizeof(std::size_t);
const std::size_t sizep = reinterpret_cast<const std::size_t&>(*(reinterpret_cast<const uint8_t*>(&p) - sizeo));
return reinterpret_cast<const T&>(*(reinterpret_cast<const uint8_t*>(&p) + sizep + sizeo));
}
template <typename T>
static const typename T::Private & toPrivate(const T & t)
{
typedef typename T::Private Private;
constexpr std::size_t sizeo = sizeof(std::size_t);
const std::size_t sizep = reinterpret_cast<const std::size_t&>(*(reinterpret_cast<const uint8_t*>(&t) - sizeo));
const Private & p = reinterpret_cast<const Private&>(*(reinterpret_cast<const uint8_t*>(&t) - sizeo - sizep));
#ifdef USE_DEBUG
std::printf("%s class=%p private=%p sizep=%d\n", __PRETTY_FUNCTION__, &t, &p, int(sizep));
std::fflush(stdout);
#endif
return p;
}
#define DECLARE_PRIVATE(T) \
public: \
void * operator new(std::size_t size); \
void operator delete(void * ptr); \
\
class Private; \
\
template <typename... Args> \
static std::unique_ptr<T> make(Args... args) \
{ \
return std::unique_ptr<T>(new T(std::forward<Args...>(args...))); \
} \
\
private: \
static const T & from_private(const Private & p); \
static T & from_private(Private & p); \
const Private & to_private() const; \
Private & to_private();
#define DEFINE_PRIVATE(T) \
void * T::operator new(const std::size_t size) { return Zeropimpl::alloc<T>(size); } \
void T::operator delete(void * const ptr) { Zeropimpl::free<T>(ptr); } \
inline const T & T::from_private(const Private & p) { return Zeropimpl::fromPrivate<T>(p); } \
inline T & T::from_private(Private & p) { return const_cast<T&>(Zeropimpl::fromPrivate<T>(p)); } \
inline const T::Private & T::to_private() const { return Zeropimpl::toPrivate<T>(*this); } \
inline T::Private & T::to_private() { return const_cast<T::Private&>(Zeropimpl::toPrivate<T>(*this)); }
} // Zeropimpl