1 #ifndef AESALON_MISC_REFERENCE_COUNTER_H
2 #define AESALON_MISC_REFERENCE_COUNTER_H
9 #include "StreamAsString.h"
21 class UntrackedMemoryException
: public Exception
{
23 UntrackedMemoryException() : Exception(StreamAsString()
24 << "Asked to decrement refcount on untracked block.") {}
27 class ReferenceCounter
: public Singleton
<ReferenceCounter
> {
29 typedef std::size_t refcount_t
;
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
;
40 block_map_t block_map
;
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
;
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 . . . */
76 (*i
).second
.set_refcount((*i
).second
.get_refcount()-1);
78 if((*i
).second
.get_refcount() == 0) {
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();
93 } // namespace Aesalon