1 | /*
|
---|
2 | * IdPool_impl.hpp
|
---|
3 | *
|
---|
4 | * Created on: Dec 23, 2011
|
---|
5 | * Author: heber
|
---|
6 | */
|
---|
7 |
|
---|
8 | #ifndef IDPOOL_IMPL_HPP_
|
---|
9 | #define IDPOOL_IMPL_HPP_
|
---|
10 |
|
---|
11 | // include config.h
|
---|
12 | #ifdef HAVE_CONFIG_H
|
---|
13 | #include <config.h>
|
---|
14 | #endif
|
---|
15 |
|
---|
16 | #include "IdPool.hpp"
|
---|
17 |
|
---|
18 | #include "CodePatterns/Log.hpp"
|
---|
19 |
|
---|
20 | template <class T, class idpolicy>
|
---|
21 | IdPool<T,idpolicy>::IdPool(const T _currId, const unsigned int _max_skips, const unsigned int _max_size) :
|
---|
22 | lastAction(NoAction),
|
---|
23 | currId(_currId),
|
---|
24 | lastPoolSize(0),
|
---|
25 | numDefragSkips(0),
|
---|
26 | MAX_FRAGMENTATION_SKIPS(_max_skips),
|
---|
27 | MAX_POOL_FRAGMENTATION(_max_size)
|
---|
28 | {}
|
---|
29 |
|
---|
30 | template <class T, class idpolicy>
|
---|
31 | IdPool<T,idpolicy>::~IdPool()
|
---|
32 | {}
|
---|
33 |
|
---|
34 | template <class T, class idpolicy>
|
---|
35 | T IdPool<T,idpolicy>::getNextId()
|
---|
36 | {
|
---|
37 | setLastAction(reserve);
|
---|
38 | return idpolicy::getNextId_impl(pool, currId);
|
---|
39 | }
|
---|
40 |
|
---|
41 | template <class T, class idpolicy>
|
---|
42 | void IdPool<T,idpolicy>::releaseId(T id)
|
---|
43 | {
|
---|
44 | setLastAction(release);
|
---|
45 | pool.insert(makeRange(id,id+1));
|
---|
46 | defragIdPool();
|
---|
47 | }
|
---|
48 |
|
---|
49 | template <class T, class idpolicy>
|
---|
50 | bool IdPool<T,idpolicy>::reserveId(T id)
|
---|
51 | {
|
---|
52 | setLastAction(reserve);
|
---|
53 | if(id>=currId ) {
|
---|
54 | range<T> newRange = makeRange(currId,id);
|
---|
55 | if(newRange.first<newRange.last)
|
---|
56 | pool.insert(newRange);
|
---|
57 | currId=id+1;
|
---|
58 | defragIdPool();
|
---|
59 | return true;
|
---|
60 | }
|
---|
61 | // look for a range that matches the request
|
---|
62 | for(typename IdPool_t::iterator iter=pool.begin();iter!=pool.end();++iter){
|
---|
63 | if(iter->isBefore(id)){
|
---|
64 | // we have covered all available ranges... nothing to be found here
|
---|
65 | break;
|
---|
66 | }
|
---|
67 | // no need to check first, since it has to be <=id, since otherwise we would have broken out
|
---|
68 | if(!iter->isBeyond(id)){
|
---|
69 | // we found a matching range... get the id from this range
|
---|
70 |
|
---|
71 | // split up this range at the point of id
|
---|
72 | range<T> bottomRange = makeRange(iter->first,id);
|
---|
73 | range<T> topRange = makeRange(id+1,iter->last);
|
---|
74 | // remove this range
|
---|
75 | pool.erase(iter);
|
---|
76 | if(bottomRange.first<bottomRange.last){
|
---|
77 | pool.insert(bottomRange);
|
---|
78 | }
|
---|
79 | if(topRange.first<topRange.last){
|
---|
80 | pool.insert(topRange);
|
---|
81 | }
|
---|
82 | defragIdPool();
|
---|
83 | return true;
|
---|
84 | }
|
---|
85 | }
|
---|
86 | // this ID could not be reserved
|
---|
87 | return false;
|
---|
88 | }
|
---|
89 |
|
---|
90 | template <class T, class idpolicy>
|
---|
91 | void IdPool<T,idpolicy>::defragIdPool()
|
---|
92 | {
|
---|
93 | // check if the situation is bad enough to make defragging neccessary
|
---|
94 | if((numDefragSkips<MAX_FRAGMENTATION_SKIPS) &&
|
---|
95 | (pool.size()<lastPoolSize+MAX_POOL_FRAGMENTATION)) {
|
---|
96 | return;
|
---|
97 | }
|
---|
98 | LOG(1, "STATUS: Defragmenting id pool.");
|
---|
99 | for(typename IdPool_t::iterator iter = pool.begin();iter!=pool.end();) {
|
---|
100 | // see if this range is adjacent to the next one
|
---|
101 | typename IdPool_t::iterator next = iter;
|
---|
102 | next++;
|
---|
103 | if(next!=pool.end() && (next->first==iter->last)) {
|
---|
104 | // merge the two ranges
|
---|
105 | range<T> newRange = makeRange(iter->first,next->last);
|
---|
106 | pool.erase(iter);
|
---|
107 | pool.erase(next);
|
---|
108 | pair<typename IdPool_t::iterator,bool> res = pool.insert(newRange);
|
---|
109 | ASSERT(res.second,"Id-Pool was confused");
|
---|
110 | iter=res.first;
|
---|
111 | continue;
|
---|
112 | }
|
---|
113 | ++iter;
|
---|
114 | }
|
---|
115 | if(!pool.empty()) {
|
---|
116 | // check if the last range is at the border
|
---|
117 | typename IdPool_t::iterator iter = pool.end();
|
---|
118 | iter--;
|
---|
119 | if(iter->last==currId){
|
---|
120 | currId=iter->first;
|
---|
121 | pool.erase(iter);
|
---|
122 | }
|
---|
123 | }
|
---|
124 | lastPoolSize=pool.size();
|
---|
125 | numDefragSkips=0;
|
---|
126 | }
|
---|
127 |
|
---|
128 | /**
|
---|
129 | * This define allows simple instantiation of the necessary singleton functions
|
---|
130 | * at a chosen place.
|
---|
131 | */
|
---|
132 | #define CONSTRUCT_IDPOOL(name, idpolicy) \
|
---|
133 | template name IdPool< name, idpolicy >::getNextId(); \
|
---|
134 | template bool IdPool< name, idpolicy >::reserveId( name ); \
|
---|
135 | template void IdPool< name, idpolicy >::releaseId( name ); \
|
---|
136 | template void IdPool< name, idpolicy >::setLastAction(const enum Actions _action); \
|
---|
137 | template void IdPool< name, idpolicy >::defragIdPool() ;
|
---|
138 |
|
---|
139 | #endif /* IDPOOL_IMPL_HPP_ */
|
---|