Ripped out the old StringHandler/StringManager system and began replacing it.
[aesalon.git] / src / misc / ReferenceCounter.h
blob2ea9c53292c39d45aa75d7fda102128fc4c09d28
1 #ifndef AESALON_MISC_REFERENCE_COUNTER_H
2 #define AESALON_MISC_REFERENCE_COUNTER_H
4 #include <cstddef>
5 #include <map>
7 #include "Singleton.h"
8 #include "Exception.h"
9 #include "StreamAsString.h"
11 namespace Aesalon {
13 namespace Interface {
14 namespace GDB {
15 class Controller;
19 namespace Misc {
21 class UntrackedMemoryException : public Exception {
22 public:
23 UntrackedMemoryException() : Exception(StreamAsString()
24 << "Asked to decrement refcount on untracked block.") {}
27 class ReferenceCounter : public Singleton<ReferenceCounter> {
28 public:
29 typedef std::size_t refcount_t;
30 protected:
31 class MemoryBlock {
32 private:
33 refcount_t refcount;
34 public:
35 refcount_t get_refcount() const { return refcount; }
36 void set_refcount(refcount_t new_refcount) { refcount = new_refcount; }
38 typedef std::map<const void *, MemoryBlock> block_map_t;
39 private:
40 block_map_t block_map;
42 public:
43 ReferenceCounter() {}
44 virtual ~ReferenceCounter() {}
45 template<typename Type> void increment_block(const Type *data);
46 template<typename Type> void decrement_block(const Type *data);
48 template<typename Type> refcount_t get_block_references(const Type *data);
51 template<typename Type>
52 void ReferenceCounter::increment_block(const Type *data) {
53 if(data == NULL) return;
55 block_map_t::iterator i = block_map.find(data);
56 if(i == block_map.end()) {
57 MemoryBlock new_block;
58 new_block.set_refcount(1);
59 block_map[data] = new_block;
61 else {
62 (*i).second.set_refcount((*i).second.get_refcount()+1);
66 template<typename Type>
67 void ReferenceCounter::decrement_block(const Type *data) {
68 if(data == NULL) return;
70 block_map_t::iterator i = block_map.find(data);
71 if(i == block_map.end()) {
72 /* This memory isn't currently in the counter . . . */
73 return;
75 else {
76 (*i).second.set_refcount((*i).second.get_refcount()-1);
78 if((*i).second.get_refcount() == 0) {
79 delete data;
83 template<typename Type>
84 ReferenceCounter::refcount_t ReferenceCounter::get_block_references(const Type* data) {
85 block_map_t::iterator i = block_map.find(data);
86 if(i == block_map.end()) return 0;
87 else return (*i).second.get_refcount();
92 } // namespace Misc
93 } // namespace Aesalon
95 #endif