diff --git a/small__buffer__allocator_8cpp_source.html b/small__buffer__allocator_8cpp_source.html index 386689c..2a4fe39 100644 --- a/small__buffer__allocator_8cpp_source.html +++ b/small__buffer__allocator_8cpp_source.html @@ -113,167 +113,106 @@
12
13namespace dispenso {
14namespace detail {
-
15// It may be possible that some tsan impls try to do global ctors and dtors in parallel.
-
16static std::atomic<int> g_smallBufferSchwarzCounter; // global is zero-init
-
17
-
18#define SMALL_BUFFER_GLOBALS_DECL(N) \
-
19 static AlignedBuffer<SmallBufferGlobals> g_globalsBuffer##N; \
-
20 static SmallBufferGlobals& g_globals##N = \
-
21 reinterpret_cast<SmallBufferGlobals&>(g_globalsBuffer##N)
+
15
+
16template <size_t kChunkSize>
+
17SmallBufferGlobals& getSmallBufferGlobals() {
+
18 // controlled leak here
+
19 static SmallBufferGlobals* globals = new SmallBufferGlobals();
+
20 return *globals;
+
21}
22
-
23SMALL_BUFFER_GLOBALS_DECL(4);
-
24SMALL_BUFFER_GLOBALS_DECL(8);
-
25SMALL_BUFFER_GLOBALS_DECL(16);
-
26SMALL_BUFFER_GLOBALS_DECL(32);
-
27SMALL_BUFFER_GLOBALS_DECL(64);
-
28SMALL_BUFFER_GLOBALS_DECL(128);
-
29SMALL_BUFFER_GLOBALS_DECL(256);
-
30
-
31#define SMALL_BUFFER_GLOBAL_FUNC_DEFS(N) \
-
32 template <> \
-
33 SmallBufferGlobals& getSmallBufferGlobals<N>() { \
-
34 return g_globals##N; \
-
35 }
-
36
-
37SMALL_BUFFER_GLOBAL_FUNC_DEFS(4)
-
38SMALL_BUFFER_GLOBAL_FUNC_DEFS(8)
-
39SMALL_BUFFER_GLOBAL_FUNC_DEFS(16)
-
40SMALL_BUFFER_GLOBAL_FUNC_DEFS(32)
-
41SMALL_BUFFER_GLOBAL_FUNC_DEFS(64)
-
42SMALL_BUFFER_GLOBAL_FUNC_DEFS(128)
-
43SMALL_BUFFER_GLOBAL_FUNC_DEFS(256)
+
23char* allocSmallBufferImpl(size_t ordinal) {
+
24 switch (ordinal) {
+
25 case 0:
+
26 return detail::SmallBufferAllocator<4>::alloc();
+
27 case 1:
+
28 return detail::SmallBufferAllocator<8>::alloc();
+
29 case 2:
+
30 return detail::SmallBufferAllocator<16>::alloc();
+
31 case 3:
+
32 return detail::SmallBufferAllocator<32>::alloc();
+
33 case 4:
+
34 return detail::SmallBufferAllocator<64>::alloc();
+
35 case 5:
+
36 return detail::SmallBufferAllocator<128>::alloc();
+
37 case 6:
+
38 return detail::SmallBufferAllocator<256>::alloc();
+
39 default:
+
40 assert(false && "Invalid small buffer ordinal requested");
+
41 return nullptr;
+
42 }
+
43}
44
-
45SchwarzSmallBufferInit::SchwarzSmallBufferInit() {
-
46 if (g_smallBufferSchwarzCounter.fetch_add(1, std::memory_order_acq_rel) == 0) {
-
47 ::new (&g_globals4) SmallBufferGlobals();
-
48 ::new (&g_globals8) SmallBufferGlobals();
-
49 ::new (&g_globals16) SmallBufferGlobals();
-
50 ::new (&g_globals32) SmallBufferGlobals();
-
51 ::new (&g_globals64) SmallBufferGlobals();
-
52 ::new (&g_globals128) SmallBufferGlobals();
-
53 ::new (&g_globals256) SmallBufferGlobals();
-
54 }
-
55}
-
56
-
57static void destroySmallBufferGlobals() {
-
58 DISPENSO_TSAN_ANNOTATE_IGNORE_WRITES_BEGIN();
-
59 g_globals4.~SmallBufferGlobals();
-
60 g_globals8.~SmallBufferGlobals();
-
61 g_globals16.~SmallBufferGlobals();
-
62 g_globals32.~SmallBufferGlobals();
-
63 g_globals64.~SmallBufferGlobals();
-
64 g_globals128.~SmallBufferGlobals();
-
65 g_globals256.~SmallBufferGlobals();
-
66 DISPENSO_TSAN_ANNOTATE_IGNORE_WRITES_END();
-
67}
-
68
-
69SchwarzSmallBufferInit::~SchwarzSmallBufferInit() {
-
70 if (g_smallBufferSchwarzCounter.fetch_sub(1, std::memory_order_acq_rel) == 1) {
-
71 destroySmallBufferGlobals();
-
72 }
-
73}
-
74
-
75char* allocSmallBufferImpl(size_t ordinal) {
-
76 switch (ordinal) {
-
77 case 0:
-
78 return detail::SmallBufferAllocator<4>::alloc();
-
79 case 1:
-
80 return detail::SmallBufferAllocator<8>::alloc();
-
81 case 2:
-
82 return detail::SmallBufferAllocator<16>::alloc();
-
83 case 3:
-
84 return detail::SmallBufferAllocator<32>::alloc();
-
85 case 4:
-
86 return detail::SmallBufferAllocator<64>::alloc();
-
87 case 5:
-
88 return detail::SmallBufferAllocator<128>::alloc();
-
89 case 6:
-
90 return detail::SmallBufferAllocator<256>::alloc();
-
91 default:
-
92 assert(false && "Invalid small buffer ordinal requested");
-
93 return nullptr;
-
94 }
-
95}
-
96
-
97void deallocSmallBufferImpl(size_t ordinal, void* buf) {
-
98 switch (ordinal) {
-
99 case 0:
-
100 detail::SmallBufferAllocator<4>::dealloc(reinterpret_cast<char*>(buf));
-
101 break;
-
102 case 1:
-
103 detail::SmallBufferAllocator<8>::dealloc(reinterpret_cast<char*>(buf));
-
104 break;
-
105 case 2:
-
106 detail::SmallBufferAllocator<16>::dealloc(reinterpret_cast<char*>(buf));
-
107 break;
-
108 case 3:
-
109 detail::SmallBufferAllocator<32>::dealloc(reinterpret_cast<char*>(buf));
-
110 break;
-
111 case 4:
-
112 detail::SmallBufferAllocator<64>::dealloc(reinterpret_cast<char*>(buf));
-
113 break;
-
114 case 5:
-
115 detail::SmallBufferAllocator<128>::dealloc(reinterpret_cast<char*>(buf));
-
116 break;
-
117 case 6:
-
118 detail::SmallBufferAllocator<256>::dealloc(reinterpret_cast<char*>(buf));
-
119 break;
-
120 default:
-
121 assert(false && "Invalid small buffer ordinal requested");
-
122 }
-
123}
-
124
-
125size_t approxBytesAllocatedSmallBufferImpl(size_t ordinal) {
-
126 switch (ordinal) {
-
127 case 0:
-
128 return detail::SmallBufferAllocator<4>::bytesAllocated();
-
129 case 1:
-
130 return detail::SmallBufferAllocator<8>::bytesAllocated();
-
131 case 2:
-
132 return detail::SmallBufferAllocator<16>::bytesAllocated();
-
133 case 3:
-
134 return detail::SmallBufferAllocator<32>::bytesAllocated();
-
135 case 4:
-
136 return detail::SmallBufferAllocator<64>::bytesAllocated();
-
137 case 5:
-
138 return detail::SmallBufferAllocator<128>::bytesAllocated();
-
139 case 6:
-
140 return detail::SmallBufferAllocator<256>::bytesAllocated();
-
141 default:
-
142 assert(false && "Invalid small buffer ordinal requested");
-
143 return 0;
-
144 }
-
145}
-
146
-
147template <size_t kChunkSize>
-
148SmallBufferAllocator<kChunkSize>::PerThreadQueuingData::~PerThreadQueuingData() {
-
149 // Sadly, it is entirely possible that some threads shut down after exiting main, which could mean
-
150 // that the SmallBufferGlobals are no longer valid. We need to "lock" on the schwarz counter to
-
151 // ensure it is safe to release these resources.
-
152 if (g_smallBufferSchwarzCounter.fetch_add(1, std::memory_order_acq_rel) > 0) {
-
153 enqueue_bulk(buffers_, count_);
-
154 }
-
155
-
156 if (g_smallBufferSchwarzCounter.fetch_sub(1, std::memory_order_acq_rel) == 1) {
-
157 destroySmallBufferGlobals();
-
158 }
-
159
-
160 DISPENSO_TSAN_ANNOTATE_IGNORE_WRITES_BEGIN();
-
161 ptoken().~ProducerToken();
-
162 ctoken().~ConsumerToken();
-
163 DISPENSO_TSAN_ANNOTATE_IGNORE_WRITES_END();
-
164}
-
165
-
166template class SmallBufferAllocator<4>;
-
167template class SmallBufferAllocator<8>;
-
168template class SmallBufferAllocator<16>;
-
169template class SmallBufferAllocator<32>;
-
170template class SmallBufferAllocator<64>;
-
171template class SmallBufferAllocator<128>;
-
172template class SmallBufferAllocator<256>;
-
173
-
174} // namespace detail
-
175} // namespace dispenso
+
45void deallocSmallBufferImpl(size_t ordinal, void* buf) {
+
46 switch (ordinal) {
+
47 case 0:
+
48 detail::SmallBufferAllocator<4>::dealloc(reinterpret_cast<char*>(buf));
+
49 break;
+
50 case 1:
+
51 detail::SmallBufferAllocator<8>::dealloc(reinterpret_cast<char*>(buf));
+
52 break;
+
53 case 2:
+
54 detail::SmallBufferAllocator<16>::dealloc(reinterpret_cast<char*>(buf));
+
55 break;
+
56 case 3:
+
57 detail::SmallBufferAllocator<32>::dealloc(reinterpret_cast<char*>(buf));
+
58 break;
+
59 case 4:
+
60 detail::SmallBufferAllocator<64>::dealloc(reinterpret_cast<char*>(buf));
+
61 break;
+
62 case 5:
+
63 detail::SmallBufferAllocator<128>::dealloc(reinterpret_cast<char*>(buf));
+
64 break;
+
65 case 6:
+
66 detail::SmallBufferAllocator<256>::dealloc(reinterpret_cast<char*>(buf));
+
67 break;
+
68 default:
+
69 assert(false && "Invalid small buffer ordinal requested");
+
70 }
+
71}
+
72
+
73size_t approxBytesAllocatedSmallBufferImpl(size_t ordinal) {
+
74 switch (ordinal) {
+
75 case 0:
+
76 return detail::SmallBufferAllocator<4>::bytesAllocated();
+
77 case 1:
+
78 return detail::SmallBufferAllocator<8>::bytesAllocated();
+
79 case 2:
+
80 return detail::SmallBufferAllocator<16>::bytesAllocated();
+
81 case 3:
+
82 return detail::SmallBufferAllocator<32>::bytesAllocated();
+
83 case 4:
+
84 return detail::SmallBufferAllocator<64>::bytesAllocated();
+
85 case 5:
+
86 return detail::SmallBufferAllocator<128>::bytesAllocated();
+
87 case 6:
+
88 return detail::SmallBufferAllocator<256>::bytesAllocated();
+
89 default:
+
90 assert(false && "Invalid small buffer ordinal requested");
+
91 return 0;
+
92 }
+
93}
+
94
+
95template <size_t kChunkSize>
+
96SmallBufferAllocator<kChunkSize>::PerThreadQueuingData::~PerThreadQueuingData() {
+
97 enqueue_bulk(buffers_, count_);
+
98
+
99 DISPENSO_TSAN_ANNOTATE_IGNORE_WRITES_BEGIN();
+
100 ptoken().~ProducerToken();
+
101 ctoken().~ConsumerToken();
+
102 DISPENSO_TSAN_ANNOTATE_IGNORE_WRITES_END();
+
103}
+
104
+
105template class SmallBufferAllocator<4>;
+
106template class SmallBufferAllocator<8>;
+
107template class SmallBufferAllocator<16>;
+
108template class SmallBufferAllocator<32>;
+
109template class SmallBufferAllocator<64>;
+
110template class SmallBufferAllocator<128>;
+
111template class SmallBufferAllocator<256>;
+
112
+
113} // namespace detail
+
114} // namespace dispenso
small_buffer_allocator.h
diff --git a/small__buffer__allocator_8h.html b/small__buffer__allocator_8h.html index 2898cc1..55ef8c0 100644 --- a/small__buffer__allocator_8h.html +++ b/small__buffer__allocator_8h.html @@ -163,7 +163,7 @@

Returns
The pointer to the allocated block of memory.
Note
: The returned buffer must be returned to the pool via deallocSmallBuffer templatized on the same block size. If kBlockSize > kMaxSmallBufferSize, this function falls back on alignedMalloc. If DISPENSO_NO_SMALL_BUFFER_ALLOCATOR is defined, we will always fall back on alignedMalloc/alignedFree.
-

Definition at line 96 of file small_buffer_allocator.h.

+

Definition at line 88 of file small_buffer_allocator.h.

@@ -191,7 +191,7 @@

Definition at line 121 of file small_buffer_allocator.h.

+

Definition at line 113 of file small_buffer_allocator.h.

@@ -235,7 +235,7 @@

Note
: If kBlockSize > kMaxSmallBufferSize, this function falls back on alignedFree.
-

Definition at line 109 of file small_buffer_allocator.h.

+

Definition at line 101 of file small_buffer_allocator.h.

diff --git a/small__buffer__allocator_8h_source.html b/small__buffer__allocator_8h_source.html index 0827f5b..6ac7d74 100644 --- a/small__buffer__allocator_8h_source.html +++ b/small__buffer__allocator_8h_source.html @@ -161,42 +161,34 @@
71 alignedFree(buf);
72}
73
-
74DISPENSO_DISABLE_WARNING_PUSH
-
75DISPENSO_DISABLE_WARNING_GLOBAL_CONSTRUCTORS
-
76static struct SchwarzSmallBufferInit {
-
77 DISPENSO_DLL_ACCESS SchwarzSmallBufferInit();
-
78 DISPENSO_DLL_ACCESS ~SchwarzSmallBufferInit();
-
79} smallBufferInit;
-
80DISPENSO_DISABLE_WARNING_POP
-
81
-
82} // namespace detail
-
83
-
95template <size_t kBlockSize>
-
-
96inline char* allocSmallBuffer() {
-
97 return detail::allocSmallOrLarge<kBlockSize>();
-
98}
+
74} // namespace detail
+
75
+
87template <size_t kBlockSize>
+
+
88inline char* allocSmallBuffer() {
+
89 return detail::allocSmallOrLarge<kBlockSize>();
+
90}
-
108template <size_t kBlockSize>
-
-
109inline void deallocSmallBuffer(void* buf) {
-
110 detail::deallocSmallOrLarge<kBlockSize>(buf);
-
111}
+
100template <size_t kBlockSize>
+
+
101inline void deallocSmallBuffer(void* buf) {
+
102 detail::deallocSmallOrLarge<kBlockSize>(buf);
+
103}
-
112
-
120template <size_t kBlockSize>
-
- -
122 return detail::approxBytesAllocatedSmallBufferImpl(detail::getOrdinal(kBlockSize));
-
123}
+
104
+
112template <size_t kBlockSize>
+
+ +
114 return detail::approxBytesAllocatedSmallBufferImpl(detail::getOrdinal(kBlockSize));
+
115}
-
124
-
125} // namespace dispenso
+
116
+
117} // namespace dispenso
detail::OpResult< T > OpResult
Definition pipeline.h:29
-
void deallocSmallBuffer(void *buf)
+
void deallocSmallBuffer(void *buf)
constexpr size_t kMaxSmallBufferSize
-
char * allocSmallBuffer()
-
size_t approxBytesAllocatedSmallBuffer()
+
char * allocSmallBuffer()
+
size_t approxBytesAllocatedSmallBuffer()