source: trunk/Mars/mcore/MemoryManager.h@ 17223

Last change on this file since 17223 was 17219, checked in by lyard, 11 years ago
draft zofits working with Queue and MemoryManager
File size: 4.4 KB
Line 
1#include <forward_list>
2
3class MemoryStock
4{
5 friend class MemoryChunk;
6 friend class MemoryManager;
7
8 size_t fChunkSize;
9 size_t fMaxMemory;
10
11 size_t fInUse;
12 size_t fAllocated;
13
14 size_t fMaxInUse;
15
16 std::mutex fMutexMem;
17 std::mutex fMutexCond;
18 std::condition_variable fCond;
19
20 std::forward_list<std::shared_ptr<char>> fMemoryStock;
21
22public:
23 MemoryStock(size_t chunk, size_t max) : fChunkSize(chunk), fMaxMemory(max),
24 fInUse(0), fAllocated(0), fMaxInUse(0)
25 {
26 if (chunk>max)
27 throw std::runtime_error("Size mismatch: Size of a single chunk exceeds maximum size of memory");
28 }
29
30private:
31 std::shared_ptr<char> pop(bool block)
32 {
33 if (block)
34 {
35 // No free slot available, next alloc would exceed max memory:
36 // block until a slot is available
37 std::unique_lock<std::mutex> lock(fMutexCond);
38 while (fMemoryStock.empty() && fAllocated+fChunkSize>fMaxMemory)
39 fCond.wait(lock);
40 }
41 else
42 {
43 // No free slot available, next alloc would exceed max memory
44 // return an empty pointer
45 if (fMemoryStock.empty() && fAllocated+fChunkSize>fMaxMemory)
46 return std::shared_ptr<char>();
47 }
48
49 // We will return this amount of memory
50 // This is not 100% thread safe, but it is not a super accurate measure anyway
51 fInUse += fChunkSize;
52 if (fInUse>fMaxInUse)
53 fMaxInUse = fInUse;
54
55 if (fMemoryStock.empty())
56 {
57 // No free slot available, allocate a new one
58 fAllocated += fChunkSize;
59 return std::shared_ptr<char>(new char[fChunkSize]);
60 }
61
62 // Get the next free slot from the stack and return it
63 const std::lock_guard<std::mutex> lock(fMutexMem);
64
65 const auto mem = fMemoryStock.front();
66 fMemoryStock.pop_front();
67 return mem;
68 };
69
70 void push(const std::shared_ptr<char> &mem)
71 {
72 if (!mem)
73 return;
74
75 // Decrease the amont of memory in use accordingly
76 fInUse -= fChunkSize;
77
78 // If the maximum memory has changed, we might be over the limit.
79 // In this case: free a slot
80 if (fAllocated>fMaxMemory)
81 {
82 fAllocated -= fChunkSize;
83 return;
84 }
85
86 {
87 const std::lock_guard<std::mutex> lock(fMutexMem);
88 fMemoryStock.emplace_front(mem);
89 }
90
91 {
92 const std::lock_guard<std::mutex> lock(fMutexCond);
93 fCond.notify_one();
94 }
95 }
96};
97
98class MemoryChunk
99{
100 friend class MemoryManager;
101
102 std::shared_ptr<MemoryStock> fMemoryStock;
103 std::shared_ptr<char> fPointer;
104 char* fRealPointer;
105
106 MemoryChunk(const std::shared_ptr<MemoryStock> &mem, bool block) : fMemoryStock(mem)
107 {
108 fPointer = fMemoryStock->pop(block);
109 fRealPointer = fPointer.get();
110 }
111
112public:
113 ~MemoryChunk()
114 {
115 fMemoryStock->push(fPointer);
116 }
117
118public:
119 char* get() { return fPointer.get();}
120};
121
122class MemoryManager
123{
124 std::shared_ptr<MemoryStock> fMemoryStock;
125
126public:
127
128 MemoryManager(size_t chunk, size_t max) : fMemoryStock(std::make_shared<MemoryStock>(chunk, max))
129 {
130 }
131
132 std::shared_ptr<MemoryChunk> malloc(bool block=true)
133 {
134 MemoryChunk *chunk = new MemoryChunk(fMemoryStock, block);
135 //Etienne cannot get the aliasing to work (at least with g++ 4.4.6
136 return std::shared_ptr<MemoryChunk>(std::shared_ptr<MemoryChunk>(chunk));//, chunk->fRealPointer);
137 }
138
139 size_t getChunkSize() const { return fMemoryStock->fChunkSize; }
140 void setChunkSize(const size_t size)
141 {
142 if (getInUse() != 0)
143 throw std::runtime_error("Cannot change the chunk size while there is memory in use");
144
145 if (getMaxMemory() < size)
146 {
147 std::ostringstream str;
148 str << "Chunk size(" << size << ") larger thank allowed memory(" << getMaxMemory() << "). Cannot allocate a single chunk.";
149 throw std::runtime_error(str.str());
150 }
151 fMemoryStock->fChunkSize = size;
152 }
153 size_t getMaxMemory() const { return fMemoryStock->fMaxMemory; }
154 size_t getInUse() const { return fMemoryStock->fInUse; }
155 size_t getAllocated() const { return fMemoryStock->fAllocated; }
156 size_t getMaxInUse() const { return fMemoryStock->fMaxInUse; }
157};
158
159
Note: See TracBrowser for help on using the repository browser.