Migrate libasyncio from boost.signal to signals2 (#8756)
[libasyncio] / utils / asyncio_ptr_list.hpp
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 */
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 &copy; Copyright 2008 Intra2Net AG
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             }
146             this->push_back(item);
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:
184             this->erase(
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