root/lang/objective-cplusplus/i3/trunk/src/mil/include/mil/Pool.h @ 37815

Revision 37815, 9.1 kB (checked in by saturday06, 3 years ago)

boost::pool ... . ...

  • Property svn:executable set to *
Line 
1#pragma once
2
3#include "Mil.h"
4#include "Thread.h"
5
6#define MIL_DEBUG_PRODUCER   0
7#define MIL_MY_PRODUCER      0
8#define MIL_MALLOC_PRODUCER  1
9#define MIL_TBB_PRODUCER     0
10
11namespace mil {
12namespace pool {
13
14typedef class MemoryHandle_ {
15    int unused;
16} * MemoryHandle;
17
18class MemoryHeader {
19    boost::uint_fast32_t header;
20public:
21#if MIL_DEBUG_PRODUCER   
22    thread::native_id_t os_thread_id;
23    thread::id_t mil_thread_id;
24    int blocks;
25    void* instance;
26    bool cleaned;
27#endif
28    bool isMalloced() const {
29        return (getBlocks() == 0xFFFF);
30    }
31    void* getMemory() const {
32        return (void*)((char*)this + sizeof(*this));
33    }
34    boost::uint16_t getBlocks() const {
35#if MIL_MALLOC_PRODUCER
36        return 1;
37#else
38        return static_cast<boost::uint16_t>(0xFFFF & (header >> 16));
39#endif
40    }
41    thread::id_t getThreadId() const {
42#if MIL_MY_PRODUCER
43        return static_cast<thread::id_t>(0xFFFF & header);
44#else
45        return ~0;
46#endif
47    }
48    static MemoryHeader& get(void* memory) {
49        return *(static_cast<MemoryHeader*>(memory) - 1);
50    }
51    static MemoryHeader& create(
52        void* memory, boost::uint16_t blocks, thread::id_t thread_id) {
53
54        MemoryHeader* this_ = static_cast<MemoryHeader*>(memory);
55
56        BOOST_STATIC_ASSERT(sizeof(this_->header) >=
57                            (sizeof(blocks) + sizeof(thread_id)));
58
59        this_->header = (blocks << 16) | thread_id;
60        return *this_;
61    }
62};
63
64namespace private_ {
65class MemoryList {
66public:
67    MemoryList* next;
68};
69
70const unsigned int BLOCK_SIZE = sizeof(void*) * 4;
71
72#if MIL_DEBUG_PRODUCER
73const unsigned int MALLOC_BLOCKS_THESHOLD = 3;
74#else
75const unsigned int MALLOC_BLOCKS_THESHOLD = 10;
76#endif
77
78static inline boost::uint16_t bytes_to_blocks(size_t bytes) {
79    if (bytes == 0) {
80        return 1;
81    }
82    size_t blocks = ((bytes - 1) / BLOCK_SIZE) + 1;
83    if (std::numeric_limits<boost::uint16_t>::max() < blocks) {
84        return 0xFFFF;
85    }
86    return (boost::uint16_t)blocks;
87}
88
89}
90}
91}
92
93namespace mil {
94namespace pool {
95
96class MallocProducer {
97public:
98    MallocProducer(thread::id_t thread_id) {
99        (void)thread_id;
100    }
101
102    void* allocate(int bytes) {
103        return ::malloc(bytes);
104    }
105
106    template <typename Type>
107    Type* allocate() {
108        return (Type*)allocate(sizeof(Type));
109    }
110
111    void free(void* memory) {
112        ::free(memory);
113    }
114
115    void free(MemoryHandle m) {
116        (void)m;
117    }
118};
119
120class MallocConsumer {
121public:
122    MemoryHandle pop(thread::id_t owner_id) {
123        (void)owner_id;
124        return (MemoryHandle)NULL;
125    }
126
127    void store(void* memory) {
128        free(memory);
129    }
130};
131}
132}
133
134#if HAVE_TBB_TBB_ALLOCATOR_H
135#include <tbb/tbb_allocator.h>
136namespace mil {
137namespace pool {
138
139struct TBBMemoryUnit {
140    char data[private_::BLOCK_SIZE];
141};
142
143extern tbb::tbb_allocator<TBBMemoryUnit> tbb_a;
144
145class TBBProducer {
146public:
147    TBBProducer(thread::id_t thread_id) {
148        (void)thread_id;
149    }
150
151    void* allocate(int bytes) {
152        boost::uint_fast32_t blocks = private_::bytes_to_blocks(bytes);
153        bytes += sizeof(blocks);
154        void* memory = NULL;
155        if (blocks <= private_::MALLOC_BLOCKS_THESHOLD) {
156            memory = tbb_a.allocate(blocks);
157        } else {
158            memory = malloc(bytes);
159        }
160        if (!memory) {
161            halt << "can't allocate memory";
162        }
163        *(boost::uint_fast32_t*)memory = blocks;
164        memory = (void*)((char*)memory + sizeof(blocks));
165        return memory;
166    }
167
168    template <typename Type>
169    Type* allocate() {
170        return (Type*)allocate(sizeof(Type));
171    }
172
173    void free(void* memory) {
174        (void)memory;
175    }
176
177    void free(MemoryHandle m) {
178        (void)m;
179    }
180};
181
182class TBBConsumer {
183public:
184    MemoryHandle pop(thread::id_t owner_id) {
185        (void)owner_id;
186        return (MemoryHandle)NULL;
187    }
188
189    void store(void* memory) {
190        boost::uint_fast32_t blocks = 0;
191        memory = (void*)((char*)memory - sizeof(blocks));
192        blocks = *(boost::uint_fast32_t*)memory;
193        if (blocks <= private_::MALLOC_BLOCKS_THESHOLD) {
194            tbb_a.deallocate((mil::pool::TBBMemoryUnit*)memory, blocks);
195        } else {
196            ::free((void*)memory);
197        }       
198    }
199};
200
201}
202}
203#endif
204namespace mil {
205namespace pool {
206
207class MyProducer : public boost::noncopyable {
208public:
209    boost::pool<> p;
210    const thread::id_t thread_id;
211    MyProducer(thread::id_t thread_id) : p(private_::BLOCK_SIZE), thread_id(thread_id) {
212    }
213
214    void* allocate(int bytes) {
215        bytes += sizeof(MemoryHeader);
216        boost::uint16_t blocks = private_::bytes_to_blocks(bytes);
217
218        void* memory = NULL;
219        if (blocks == 1) {
220            memory = p.malloc();
221        } else if (blocks <= private_::MALLOC_BLOCKS_THESHOLD) {
222            memory = p.ordered_malloc(blocks);
223        } else {
224            memory = malloc(bytes);
225        }
226        if (!memory) {
227            halt << "can't allocate memory";
228        }
229        MemoryHeader& header = MemoryHeader::create(memory, blocks, thread_id);
230
231#if MIL_DEBUG_PRODUCER
232        {
233            header.os_thread_id  = mil::thread::get_native_id();
234            header.mil_thread_id = thread_id;
235            header.blocks        = private_::bytes_to_blocks(bytes);
236            header.instance      = (void*)this;
237            header.cleaned       = false;
238        }
239#endif
240
241        return header.getMemory();
242    }
243
244    template <typename Type>
245    Type* allocate() {
246        return (Type*)allocate(sizeof(Type));
247    }
248
249    void free(void* memory) {
250        MemoryHeader& header = MemoryHeader::get(memory);
251        boost::uint16_t blocks = header.getBlocks();
252        thread::id_t memory_thread_id = header.getThreadId();
253        memory = (void*)&header;
254
255#if MIL_DEBUG_PRODUCER
256        {
257            if (header.os_thread_id != mil::thread::get_native_id()) {
258                halt << "header.os_thread_id != mil::thread::get_native_id(), "
259                     << header.os_thread_id << " != " << mil::thread::get_native_id();
260            }
261            if (header.mil_thread_id != thread_id) {
262                halt << "header.mil_thread_id == thread_id, "
263                     << header.mil_thread_id << " != " << thread_id;
264            }
265            if (header.mil_thread_id != memory_thread_id) {
266                halt << "header.mil_thread_id == memory_thread_id, "
267                     << header.mil_thread_id << " != " << thread_id;
268            }
269            if (header.blocks != blocks) {
270                halt << "header.blocks != blocks, "
271                     << header.blocks << " != " << blocks;
272            }
273            if (header.instance != (void*)this) {
274                halt << "header.instance != this, "
275                     << header.instance << " != " << this;
276            }
277            if (header.cleaned) {
278                halt << "header.cleaned == true, ";
279            }
280            header.cleaned = true;
281        }
282#else
283        (void)memory_thread_id;
284#endif
285
286        if (blocks == 1) {
287            p.free(memory);
288        } else if (blocks <= private_::MALLOC_BLOCKS_THESHOLD) {
289            p.free(memory, blocks);
290        } else {
291            ::free(memory);
292        }
293    }
294
295    void free(MemoryHandle m) {
296        private_::MemoryList* current = (private_::MemoryList*)m;
297        for (;;) {
298            if (!current) {
299                break;
300            }
301            private_::MemoryList* next = current->next;
302            this->free((void*)current);
303            current = next;
304        }
305    }
306};
307
308class MyConsumer : public boost::noncopyable {
309    private_::MemoryList* heads[MIL_MAX_THREADS];
310    int sizes[MIL_MAX_THREADS];
311
312    enum {
313        MAX_STORES = 50,
314    };
315
316public:
317    MyConsumer() {
318        memset((void*)heads, 0, sizeof(heads));
319        memset((void*)sizes, 0, sizeof(sizes));
320    }
321
322    MemoryHandle pop(thread::id_t owner_id) {
323        if (sizes[owner_id] < MAX_STORES) {
324            return NULL;
325        }
326        private_::MemoryList* result = heads[owner_id];
327        heads[owner_id] = 0;
328        sizes[owner_id] = 0;
329        return (MemoryHandle)result;
330    }
331
332    void store(void* memory) {
333        MemoryHeader& header = MemoryHeader::get(memory);
334        //if (header.isMalloced()) {
335        //    free(&header);
336        //    return;
337        //}
338        thread::id_t owner_id = header.getThreadId();
339        private_::MemoryList* l = (private_::MemoryList*)memory;
340        l->next = heads[owner_id];
341        heads[owner_id] = l;
342        sizes[owner_id]++;
343    }
344};
345}
346}
347
348namespace mil {
349namespace pool {
350#if MIL_MALLOC_PRODUCER
351    typedef MallocProducer Producer;
352    typedef MallocConsumer Consumer;
353#elif MIL_TBB_PRODUCER
354    typedef TBBProducer Producer;
355    typedef TBBConsumer Consumer;
356#elif MIL_MY_PRODUCER
357    typedef MyProducer Producer;
358    typedef MyConsumer Consumer;
359#else
360#error
361#endif
362}
363}
Note: See TracBrowser for help on using the browser.