Commit | Line | Data |
---|---|---|
8c15b8c7 TJ |
1 | /* |
2 | The software in this package is distributed under the GNU General | |
3 | Public License version 2 (with a special exception described below). | |
4 | ||
5 | A copy of GNU General Public License (GPL) is included in this distribution, | |
6 | in the file COPYING.GPL. | |
7 | ||
8 | As a special exception, if other files instantiate templates or use macros | |
9 | or inline functions from this file, or you compile this file and link it | |
10 | with other works to produce a work based on this file, this file | |
11 | does not by itself cause the resulting work to be covered | |
12 | by the GNU General Public License. | |
13 | ||
14 | However the source code for this file must still be made available | |
15 | in accordance with section (3) of the GNU General Public License. | |
16 | ||
17 | This exception does not invalidate any other reasons why a work based | |
18 | on this file might be covered by the GNU General Public License. | |
19 | */ | |
aba4c34d RP |
20 | /** |
21 | * @file | |
22 | * @brief a pointer list | |
23 | * | |
24 | * provides a pointer list which is prepared for being used in nested | |
25 | * iterator loops. | |
26 | * | |
27 | * @author Reinhard Pfau \<reinhard.pfau@intra2net.com\> | |
28 | * | |
29 | * @copyright © Copyright 2008 Intra2Net AG | |
aba4c34d RP |
30 | */ |
31 | ||
32 | #ifndef __ASYNCIO__PTR_LIST_HPP__ | |
33 | #define __ASYNCIO__PTR_LIST_HPP__ | |
34 | ||
35 | #include <list> | |
36 | #include <algorithm> | |
37 | ||
38 | ||
39 | namespace AsyncIo | |
40 | { | |
41 | namespace Utils | |
42 | { | |
43 | ||
44 | ||
45 | /** | |
46 | * @brief provides a global instance counter. | |
47 | * | |
48 | * The global instance counter must be initialized by the module which uses it. | |
49 | * The main purpose for this is to keep track of the instances when PtrList's are | |
50 | * used as global objects. | |
51 | */ | |
52 | template< class T, bool globalcounted > | |
53 | class GlobalCounted | |
54 | { | |
55 | static int InstanceCount; | |
56 | ||
57 | public: | |
58 | ||
59 | GlobalCounted() | |
60 | { | |
61 | ++InstanceCount; | |
62 | } // eo GlobalCounted | |
63 | ||
64 | ||
65 | virtual ~GlobalCounted() | |
66 | { | |
67 | --InstanceCount; | |
68 | } // eo ~GlobalCounted | |
69 | ||
70 | static int Instances() | |
71 | { | |
72 | return InstanceCount; | |
73 | } | |
74 | }; // eo GlobalCounted | |
75 | ||
76 | ||
77 | template<> | |
78 | class GlobalCounted< class T, false > | |
79 | { | |
80 | public: | |
81 | GlobalCounted() | |
82 | { | |
83 | } // eo GlobalCounted | |
84 | ||
85 | ||
86 | virtual ~GlobalCounted() | |
87 | { | |
88 | } // eo ~GlobalCounted | |
89 | ||
90 | }; // eo GlobalCounted | |
91 | ||
92 | ||
93 | ||
94 | /** | |
95 | * @brief pointer list which supports deletion by set to NULL. | |
96 | * | |
97 | * This list can be used in nested iterator loops as long as some conditions | |
98 | * are fulfilled: | |
99 | * - inside the loops each iterator value is tested for not get NULL. | |
100 | * - cleaning the list is only allowed when the outmost loop exits. | |
101 | * . | |
102 | * | |
103 | * | |
104 | * @tparam T type of the pointers. | |
105 | * @tparam globalcounted determine if a global instance counter should be included. | |
106 | */ | |
107 | template<class T, bool globalcounted= false> | |
108 | class PtrList | |
109 | : public GlobalCounted< PtrList< T, globalcounted >, globalcounted > | |
110 | , protected std::list<T*> | |
111 | { | |
112 | typedef std::list<T*> inherited; | |
113 | ||
114 | public: | |
115 | typedef GlobalCounted< PtrList< T, globalcounted >, globalcounted > GlobalCountType; | |
116 | ||
117 | typedef typename inherited::iterator iterator; | |
118 | typedef typename inherited::const_iterator const_iterator; | |
119 | ||
120 | public: | |
121 | ||
122 | PtrList() | |
123 | : Dirty(false) | |
124 | { | |
125 | } // eo PtrList | |
126 | ||
127 | ||
128 | ~PtrList() | |
129 | { | |
130 | } // eo ~PtrList | |
131 | ||
132 | ||
133 | /** | |
134 | * @brief add a new item pointer to the list. | |
135 | * | |
136 | * @param item item pointer which should be added | |
137 | */ | |
138 | void add_item(T* item) | |
139 | { | |
140 | typename inherited::iterator it= std::find(inherited::begin(), inherited::end(), item); | |
141 | if (it != inherited::end()) | |
142 | { | |
143 | // nothing to do since item is already in the list | |
144 | return; | |
145 | } | |
05682361 | 146 | this->push_back(item); |
aba4c34d RP |
147 | } // eo add |
148 | ||
149 | ||
150 | /** | |
151 | * @brief remove an item pointer from the list by setting to NULL. | |
152 | * | |
153 | * This sets the pointer in the list to NULL and marks the list as dirty. | |
154 | * | |
155 | * @param item the io object which should be removed from the list. | |
156 | */ | |
157 | void remove_item(T* item) | |
158 | { | |
159 | typename inherited::iterator it= std::find(inherited::begin(), inherited::end(), item); | |
160 | if (it == inherited::end()) | |
161 | { | |
162 | // nothing to do: | |
163 | return; | |
164 | } | |
165 | *it = NULL; // forget the pointer | |
166 | Dirty= true; // ..and mark the list as dirty (i.e. has NULL elements) | |
167 | } // eo remove | |
168 | ||
169 | ||
170 | /** | |
171 | * @brief cleans the list of objects by removing the NULL elements (if any). | |
172 | * | |
173 | * @note this function should only be called when it is ensured that no | |
174 | * other functions using iterators of this list. | |
175 | */ | |
176 | void clean_list() | |
177 | { | |
178 | if (!Dirty) | |
179 | { | |
180 | // nothing to do | |
181 | return; | |
182 | } | |
183 | // remove the NULL elements now: | |
05682361 | 184 | this->erase( |
aba4c34d RP |
185 | std::remove( inherited::begin(), inherited::end(), (T*)NULL), |
186 | inherited::end() ); | |
187 | Dirty= false; | |
188 | } // eo clean_list | |
189 | ||
190 | ||
191 | /** | |
192 | * @brief explicit set the list dirty. | |
193 | * | |
194 | * use this to mark the list as dirty, when an item is set to NULL via | |
195 | * a non const iterator. | |
196 | * | |
197 | * @note This is really dirty; better use remove_item(T*) in that cases! | |
198 | */ | |
199 | void set_dirty() | |
200 | { | |
201 | Dirty= true; | |
202 | } // eo set_dirty | |
203 | ||
204 | ||
205 | iterator begin() | |
206 | { | |
207 | return inherited::begin(); | |
208 | } | |
209 | ||
210 | ||
211 | iterator end() | |
212 | { | |
213 | return inherited::end(); | |
214 | } | |
215 | ||
216 | ||
217 | const_iterator begin() const | |
218 | { | |
219 | return inherited::begin(); | |
220 | } | |
221 | ||
222 | ||
223 | const_iterator end() const | |
224 | { | |
225 | return inherited::end(); | |
226 | } | |
227 | ||
228 | protected: | |
229 | bool Dirty; | |
230 | ||
231 | }; // eo class PtrList | |
232 | ||
233 | ||
234 | } // eo namespace Utils | |
235 | } // eo namespace AsyncIo | |
236 | ||
237 | #endif |