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

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