1
#ifndef _STL_COLLECTION_H
2
#define _STL_COLLECTION_H
3
4
#include <memory>
5
#include <vector>
6
#include <loki/Threads.h>
7
8
/**
9
@class STLCollection
10
@brief 基于STL容器(vector,list,deque)實現(xiàn)的數(shù)據(jù)結構通用集合類
11
12
* 提供以索引作為外參的以下公共通用接口
13
* add --- 向前或向后增加單個元素
14
* insert --- 插入單個元素
15
* erase --- 刪除單個或多個元素
16
* set --- 修改某個元素
17
* get --- 獲取某個元素
18
* find --- 查找某個元素
19
* front --- 獲取第一個元素
20
* back --- 獲取最后一個元素
21
*/
22
23
template<typename T,
24
template <class, class> class ThreadModel = LOKI_DEFAULT_THREADING,
25
class MutexPolicy = LOKI_DEFAULT_MUTEX,
26
template<class T,class U > class C = std::vector,
27
template <class T> class U = std::allocator
28
>
29
class STLCollection : public C<T,U<T> >
30
{
31
typedef U<T> Allocator;
32
typedef C<T,Allocator> base;
33
typedef STLCollection<T,ThreadModel,MutexPolicy,C,U> self;
34
35
public:
36
STLCollection()
37
{
38
}
39
explicit STLCollection(const Allocator& al)
40
:base(al)
41
{
42
}
43
explicit STLCollection(size_t n)
44
:base(n)
45
{
46
}
47
STLCollection(size_t n,const T& t)
48
:base(n,t)
49
{
50
}
51
STLCollection(size_t n,const T& t,const Allocator& al)
52
:base(n,t,al)
53
{
54
}
55
STLCollection(const STLCollection& right)
56
:base(right)
57
{
58
}
59
60
template<class InputIterator>
61
STLCollection(InputIterator first,InputIterator last)
62
:base(first,last)
63
{
64
}
65
66
template<class InputIterator>
67
STLCollection(InputIterator first,InputIterator last,const Allocator& al)
68
:base(first,last,al)
69
{
70
}
71
~STLCollection()
72
{
73
typename ThreadModel<self,MutexPolicy>::Lock guard(lock_);
74
}
75
76
public:
77
using base::erase;
78
using base::insert;
79
using base::front;
80
using base::back;
81
82
void add(const T& t,bool append = true)
83
{
84
typename ThreadModel<self,MutexPolicy>::Lock guard(lock_);
85
if (append)
86
base::insert(base::end(),t);
87
else
88
base::insert(base::begin(),t);
89
}
90
void insert(size_t index,const T& t)
91
{
92
typename ThreadModel<self,MutexPolicy>::Lock guard(lock_);
93
insert_impl(index,t,typename std::iterator_traits<typename base::iterator>::iterator_category());
94
}
95
96
void erase(size_t index)
97
{
98
typename ThreadModel<self,MutexPolicy>::Lock guard(lock_);
99
erase_impl(index,typename std::iterator_traits<typename base::iterator>::iterator_category());
100
}
101
void erase(size_t beg,size_t end)
102
{
103
typename ThreadModel<self,MutexPolicy>::Lock guard(lock_);
104
erase_impl(beg,end,typename std::iterator_traits<typename base::iterator>::iterator_category());
105
}
106
void erase(const T& val)
107
{
108
typename ThreadModel<self,MutexPolicy>::Lock guard(lock_);
109
typename base::iterator it = std::find(base::begin(),base::end(),val);
110
if (it != base::end()) base::erase(it);
111
}
112
template<class Predicate>
113
void erase(const Predicate& Pred)
114
{
115
typename ThreadModel<self,MutexPolicy>::Lock guard(lock_);
116
typename base::iterator it = std::find_if(base::begin(),base::end(),Pred);
117
if (it != base::end()) base::erase(it);
118
}
119
120
void set(size_t index,const T& t)
121
{
122
typename ThreadModel<self,MutexPolicy>::Lock guard(lock_);
123
T* p = get(index);
124
if (p) *p = t;
125
}
126
127
T* get(size_t index)
128
{
129
typename ThreadModel<self,MutexPolicy>::Lock guard(lock_);
130
return get_impl(index,typename std::iterator_traits<typename base::iterator>::iterator_category());
131
}
132
const T* get(size_t index) const
133
{
134
typename ThreadModel<self,MutexPolicy>::Lock guard(lock_);
135
return get_impl(index,typename std::iterator_traits<typename base::iterator>::iterator_category());
136
}
137
138
T* find(const T& val,size_t* index)
139
{
140
typename ThreadModel<self,MutexPolicy>::Lock guard(lock_);
141
142
typename base::iterator it = std::find(base::begin(),base::end(),val);
143
if (it == base::end()) return NULL;
144
if (index) *index = std::distance(base::begin(),it);
145
return ⁢
146
}
147
const T* find(const T& val,size_t* index) const
148
{
149
typename ThreadModel<self,MutexPolicy>::Lock guard(lock_);
150
151
typename base::const_iterator it = std::find(base::begin(),base::end(),val);
152
if (it == base::end()) return NULL;
153
if (index) *index = std::distance(base::begin(),it);
154
return ⁢
155
}
156
template<class Predicate>
157
T* find(const Predicate& Pred,size_t* index)
158
{
159
typename ThreadModel<self,MutexPolicy>::Lock guard(lock_);
160
161
typename base::iterator it = std::find_if(base::begin(),base::end(),Pred);
162
if (it == base::end()) return NULL;
163
if (index) *index = std::distance(base::begin(),it);
164
return ⁢
165
}
166
template<class Predicate>
167
const T* find(const Predicate& Pred,size_t* index) const
168
{
169
typename ThreadModel<self,MutexPolicy>::Lock guard(lock_);
170
171
typename base::const_iterator it = std::find_if(base::begin(),base::end(),Pred);
172
if (it == base::end()) return NULL;
173
if (index) *index = std::distance(base::begin(),it);
174
return ⁢
175
}
176
177
T* front()
178
{
179
typename ThreadModel<self,MutexPolicy>::Lock guard(lock_);
180
181
if (base::empty()) return NULL;
182
return &base::front();
183
}
184
const T* front() const
185
{
186
typename ThreadModel<self,MutexPolicy>::Lock guard(lock_);
187
188
if (base::empty()) return NULL;
189
return &base::front();
190
}
191
192
T* back()
193
{
194
typename ThreadModel<self,MutexPolicy>::Lock guard(lock_);
195
196
if (base::empty()) return NULL;
197
return &base::back();
198
}
199
const T* back() const
200
{
201
typename ThreadModel<self,MutexPolicy>::Lock guard(lock_);
202
203
if (base::empty()) return NULL;
204
return &base::back();
205
}
206
207
bool is_empty() const
208
{
209
typename ThreadModel<self,MutexPolicy>::Lock guard(lock_);
210
return base::empty();
211
}
212
213
private:
214
void insert_impl(size_t index,const T& t,std::random_access_iterator_tag tag)
215
{
216
if (index < base::size())
217
{
218
base::insert(base::begin()+index,t);
219
}
220
}
221
void insert_impl(size_t index,const T& t,std::input_iterator_tag tag)
222
{
223
if (index < base::size())
224
{
225
typename base::iterator it = base::begin();
226
while(index--) ++it;
227
base::insert(it,t);
228
}
229
}
230
void erase_impl(size_t index,std::random_access_iterator_tag tag)
231
{
232
if (index < base::size())
233
{
234
base::erase(base::begin()+index);
235
}
236
}
237
void erase_impl(size_t index,std::input_iterator_tag tag)
238
{
239
if (index < base::size())
240
{
241
typename base::iterator it = base::begin();
242
while(index--) ++it;
243
base::erase(it);
244
}
245
}
246
void erase_impl(size_t beg,size_t end,std::random_access_iterator_tag tag)
247
{
248
end = std::min(end,base::size());
249
if (beg < end)
250
{
251
base::erase(base::begin()+beg,base::begin()+end);
252
}
253
}
254
void erase_impl(size_t beg,size_t end,std::input_iterator_tag tag)
255
{
256
end = std::min(end,base::size());
257
if (beg < end)
258
{
259
typename base::iterator it = base::begin();
260
while(beg++ < end) it = base::erase(it);
261
}
262
}
263
T* get_impl(size_t index,std::random_access_iterator_tag tag)
264
{
265
if (index>=base::size())
266
return NULL;
267
return &(*(base::begin()+index));
268
}
269
const T* get_impl(size_t index,std::random_access_iterator_tag tag) const
270
{
271
if (index>=base::size())
272
return NULL;
273
return &(*(base::begin()+index));
274
}
275
T* get_impl(size_t index,std::input_iterator_tag tag)
276
{
277
if (index>=base::size())
278
return NULL;
279
typename base::iterator it = base::begin();
280
while (index--) ++it;
281
return &(*it);
282
}
283
const T* get_impl(size_t index,std::input_iterator_tag tag) const
284
{
285
if (index>=base::size())
286
return NULL;
287
typename base::const_iterator it = base::begin();
288
while(index--) ++it;
289
return &(*it);
290
}
291
private:
292
ThreadModel<STLCollection,MutexPolicy> lock_;
293
};
294
295
#endif
#ifndef _STL_COLLECTION_H2
#define _STL_COLLECTION_H3

4
#include <memory>5
#include <vector>6
#include <loki/Threads.h>7

8
/**9
@class STLCollection10
@brief 基于STL容器(vector,list,deque)實現(xiàn)的數(shù)據(jù)結構通用集合類11

12
* 提供以索引作為外參的以下公共通用接口13
* add --- 向前或向后增加單個元素14
* insert --- 插入單個元素15
* erase --- 刪除單個或多個元素16
* set --- 修改某個元素17
* get --- 獲取某個元素18
* find --- 查找某個元素19
* front --- 獲取第一個元素20
* back --- 獲取最后一個元素21
*/22

23
template<typename T,24
template <class, class> class ThreadModel = LOKI_DEFAULT_THREADING,25
class MutexPolicy = LOKI_DEFAULT_MUTEX,26
template<class T,class U > class C = std::vector,27
template <class T> class U = std::allocator28
>29
class STLCollection : public C<T,U<T> >30
{31
typedef U<T> Allocator;32
typedef C<T,Allocator> base;33
typedef STLCollection<T,ThreadModel,MutexPolicy,C,U> self;34

35
public:36
STLCollection()37
{38
}39
explicit STLCollection(const Allocator& al)40
:base(al)41
{42
}43
explicit STLCollection(size_t n)44
:base(n)45
{46
}47
STLCollection(size_t n,const T& t)48
:base(n,t)49
{50
}51
STLCollection(size_t n,const T& t,const Allocator& al)52
:base(n,t,al)53
{54
}55
STLCollection(const STLCollection& right)56
:base(right)57
{58
}59

60
template<class InputIterator>61
STLCollection(InputIterator first,InputIterator last)62
:base(first,last)63
{64
}65

66
template<class InputIterator>67
STLCollection(InputIterator first,InputIterator last,const Allocator& al)68
:base(first,last,al)69
{70
}71
~STLCollection()72
{73
typename ThreadModel<self,MutexPolicy>::Lock guard(lock_);74
}75

76
public:77
using base::erase;78
using base::insert;79
using base::front;80
using base::back;81

82
void add(const T& t,bool append = true)83
{84
typename ThreadModel<self,MutexPolicy>::Lock guard(lock_);85
if (append)86
base::insert(base::end(),t);87
else88
base::insert(base::begin(),t);89
}90
void insert(size_t index,const T& t)91
{92
typename ThreadModel<self,MutexPolicy>::Lock guard(lock_);93
insert_impl(index,t,typename std::iterator_traits<typename base::iterator>::iterator_category());94
}95

96
void erase(size_t index)97
{98
typename ThreadModel<self,MutexPolicy>::Lock guard(lock_);99
erase_impl(index,typename std::iterator_traits<typename base::iterator>::iterator_category());100
}101
void erase(size_t beg,size_t end)102
{103
typename ThreadModel<self,MutexPolicy>::Lock guard(lock_);104
erase_impl(beg,end,typename std::iterator_traits<typename base::iterator>::iterator_category());105
}106
void erase(const T& val)107
{108
typename ThreadModel<self,MutexPolicy>::Lock guard(lock_);109
typename base::iterator it = std::find(base::begin(),base::end(),val);110
if (it != base::end()) base::erase(it);111
}112
template<class Predicate>113
void erase(const Predicate& Pred)114
{115
typename ThreadModel<self,MutexPolicy>::Lock guard(lock_);116
typename base::iterator it = std::find_if(base::begin(),base::end(),Pred);117
if (it != base::end()) base::erase(it);118
}119

120
void set(size_t index,const T& t)121
{122
typename ThreadModel<self,MutexPolicy>::Lock guard(lock_);123
T* p = get(index);124
if (p) *p = t;125
}126

127
T* get(size_t index) 128
{129
typename ThreadModel<self,MutexPolicy>::Lock guard(lock_);130
return get_impl(index,typename std::iterator_traits<typename base::iterator>::iterator_category());131
}132
const T* get(size_t index) const133
{134
typename ThreadModel<self,MutexPolicy>::Lock guard(lock_);135
return get_impl(index,typename std::iterator_traits<typename base::iterator>::iterator_category());136
}137

138
T* find(const T& val,size_t* index)139
{140
typename ThreadModel<self,MutexPolicy>::Lock guard(lock_);141

142
typename base::iterator it = std::find(base::begin(),base::end(),val);143
if (it == base::end()) return NULL;144
if (index) *index = std::distance(base::begin(),it);145
return ⁢146
}147
const T* find(const T& val,size_t* index) const148
{149
typename ThreadModel<self,MutexPolicy>::Lock guard(lock_);150

151
typename base::const_iterator it = std::find(base::begin(),base::end(),val);152
if (it == base::end()) return NULL;153
if (index) *index = std::distance(base::begin(),it);154
return ⁢155
}156
template<class Predicate>157
T* find(const Predicate& Pred,size_t* index)158
{159
typename ThreadModel<self,MutexPolicy>::Lock guard(lock_);160

161
typename base::iterator it = std::find_if(base::begin(),base::end(),Pred);162
if (it == base::end()) return NULL;163
if (index) *index = std::distance(base::begin(),it);164
return ⁢165
}166
template<class Predicate>167
const T* find(const Predicate& Pred,size_t* index) const168
{169
typename ThreadModel<self,MutexPolicy>::Lock guard(lock_);170

171
typename base::const_iterator it = std::find_if(base::begin(),base::end(),Pred);172
if (it == base::end()) return NULL;173
if (index) *index = std::distance(base::begin(),it);174
return ⁢175
}176

177
T* front()178
{179
typename ThreadModel<self,MutexPolicy>::Lock guard(lock_);180

181
if (base::empty()) return NULL;182
return &base::front();183
}184
const T* front() const185
{186
typename ThreadModel<self,MutexPolicy>::Lock guard(lock_);187

188
if (base::empty()) return NULL;189
return &base::front();190
}191

192
T* back()193
{194
typename ThreadModel<self,MutexPolicy>::Lock guard(lock_);195

196
if (base::empty()) return NULL;197
return &base::back();198
}199
const T* back() const200
{201
typename ThreadModel<self,MutexPolicy>::Lock guard(lock_);202

203
if (base::empty()) return NULL;204
return &base::back();205
}206

207
bool is_empty() const208
{209
typename ThreadModel<self,MutexPolicy>::Lock guard(lock_);210
return base::empty();211
}212

213
private:214
void insert_impl(size_t index,const T& t,std::random_access_iterator_tag tag)215
{216
if (index < base::size())217
{218
base::insert(base::begin()+index,t);219
}220
}221
void insert_impl(size_t index,const T& t,std::input_iterator_tag tag)222
{223
if (index < base::size())224
{225
typename base::iterator it = base::begin();226
while(index--) ++it;227
base::insert(it,t);228
}229
}230
void erase_impl(size_t index,std::random_access_iterator_tag tag)231
{232
if (index < base::size())233
{234
base::erase(base::begin()+index);235
}236
}237
void erase_impl(size_t index,std::input_iterator_tag tag)238
{239
if (index < base::size())240
{241
typename base::iterator it = base::begin();242
while(index--) ++it;243
base::erase(it);244
}245
}246
void erase_impl(size_t beg,size_t end,std::random_access_iterator_tag tag)247
{248
end = std::min(end,base::size());249
if (beg < end)250
{251
base::erase(base::begin()+beg,base::begin()+end);252
}253
}254
void erase_impl(size_t beg,size_t end,std::input_iterator_tag tag)255
{256
end = std::min(end,base::size());257
if (beg < end)258
{259
typename base::iterator it = base::begin();260
while(beg++ < end) it = base::erase(it);261
}262
}263
T* get_impl(size_t index,std::random_access_iterator_tag tag)264
{265
if (index>=base::size())266
return NULL;267
return &(*(base::begin()+index));268
}269
const T* get_impl(size_t index,std::random_access_iterator_tag tag) const270
{271
if (index>=base::size())272
return NULL;273
return &(*(base::begin()+index));274
}275
T* get_impl(size_t index,std::input_iterator_tag tag)276
{277
if (index>=base::size())278
return NULL;279
typename base::iterator it = base::begin();280
while (index--) ++it;281
return &(*it);282
}283
const T* get_impl(size_t index,std::input_iterator_tag tag) const284
{285
if (index>=base::size())286
return NULL;287
typename base::const_iterator it = base::begin();288
while(index--) ++it;289
return &(*it);290
}291
private:292
ThreadModel<STLCollection,MutexPolicy> lock_;293
};294

295
#endif現(xiàn)在來看一下它的應用,一個網(wǎng)絡通訊項目,由UI客戶端(gsoap & c++開發(fā))和服務端(java開發(fā))構成,服務端已實現(xiàn)了一些web service的同步方法,客戶端需要調(diào)用它實現(xiàn)相關功能,為了不阻塞界面,因此需要轉(zhuǎn)化成異步方式調(diào)用,調(diào)用的結果使用PostMessage API 發(fā)自定義消息給窗口,因此發(fā)送消息方new 了一個結果的拷貝給窗口,窗口收到后再delete這個結果,但有個問題是post消息可能會丟失導致結果得不到釋放,產(chǎn)生內(nèi)存泄露。因此設計一個智能指針容器而且是線程安全的,在發(fā)消息時將結果拷貝加到容器中,在接收方處理結果后再從容器中刪除它,這樣就可保證無內(nèi)存泄露問題了。關于智能指針容器,boost中有ptr_vector,ptr_list,ptr_set等現(xiàn)成的,但是它們不是按照指針本身而是指針指向的對象來對待的,也就是說你要刪除其中的指針,是按照指針指向的對象來比較查找的,原因是其內(nèi)部迭代器的訪問作了特殊處理,因此這點不符合上面應用的需求,當然可以在指針指向的對象中做點手腳,但是這方法有點勉強,應用要的只是刪除指針,而不必關心它指向的對象。為了達到目的又能最大程度地復用代碼,因此改進了STLCollection,簡單地實現(xiàn)了智能指針容器,代碼如下:
1
#ifndef _PTR_CONTAINER_H
2
#define _PTR_CONTAINER_H
3
4
#include "stl_collection.h"
5
#include <boost/smart_ptr.hpp>
6
7
class raw_ptr_compare
8
{
9
public:
10
raw_ptr_compare(void* ptr):m_ptr(ptr)
11
{
12
}
13
bool operator()(const boost::shared_ptr<void>& sp) const
14
{
15
return sp.get()==m_ptr;
16
}
17
private:
18
void* m_ptr;
19
};
20
21
typedef STLCollection<boost::shared_ptr<void> > ptr_container;
22
typedef boost::weak_ptr<ptr_container> wp_ptr_container;
23
24
#ifdef _LOKI_SINGLETON
25
#include <loki/Singleton.h>
26
27
template<class T>
28
struct Loki::CreateUsingNew<boost::weak_ptr<T> >
29
{
30
static boost::weak_ptr<T>* Create()
31
{
32
static boost::shared_ptr<T> sp(new T);
33
static boost::weak_ptr<T> wp = sp;
34
return ℘
35
}
36
37
static void Destroy(boost::weak_ptr<T>* p)
38
{
39
}
40
};
41
typedef ::Loki::SingletonHolder<wp_ptr_container> SingletonSmartPointerContainer;
42
#endif
43
44
#endif
#ifndef _PTR_CONTAINER_H2
#define _PTR_CONTAINER_H3

4
#include "stl_collection.h"5
#include <boost/smart_ptr.hpp>6

7
class raw_ptr_compare8
{9
public:10
raw_ptr_compare(void* ptr):m_ptr(ptr)11
{12
}13
bool operator()(const boost::shared_ptr<void>& sp) const14
{15
return sp.get()==m_ptr;16
}17
private:18
void* m_ptr;19
};20

21
typedef STLCollection<boost::shared_ptr<void> > ptr_container;22
typedef boost::weak_ptr<ptr_container> wp_ptr_container;23

24
#ifdef _LOKI_SINGLETON25
#include <loki/Singleton.h>26

27
template<class T>28
struct Loki::CreateUsingNew<boost::weak_ptr<T> >29
{30
static boost::weak_ptr<T>* Create()31
{32
static boost::shared_ptr<T> sp(new T);33
static boost::weak_ptr<T> wp = sp;34
return ℘35
}36

37
static void Destroy(boost::weak_ptr<T>* p)38
{39
}40
};41
typedef ::Loki::SingletonHolder<wp_ptr_container> SingletonSmartPointerContainer;42
#endif43

44
#endif應用的示例代碼如下:
1
//在工作線程中,執(zhí)行調(diào)用同步webservice方法login
2
void login_task::Run(const volatile BOOL& bExit)
3
{
4
assert(m_client);
5
login_output out;
6
if (m_client->login(*this,out))
7
{
8
boost::shared_ptr<void> sp(new login_output(out));
9
boost::shared_ptr<ptr_container> sp_ptr = SingletonSmartPointerContainer::Instance().lock();
10
if (sp_ptr)
11
{
12
sp_ptr->add(sp);
13
::PostMessage(m_hWnd,WM_LOGIN,0,(LPARAM)sp.get());
14
}
15
}
16
else
17
{
18
::PostMessage(m_hWnd,WM_LOGIN,1,0);
19
}
20
}
21
//在UI線程中,異步回調(diào)WM_LOGIN消息處理
22
LRESULT Cvpn_ca_clientDlg::OnLoginCallback(WPARAM wParam,LPARAM lParam)
23
{
24
if (0==wParam)
25
{
26
login_output* p_out = (login_output*)lParam;
27
boost::shared_ptr<ptr_container> sp = SingletonSmartPointerContainer::Instance().lock();
28
if (sp)
29
{
30
sp->erase(raw_ptr_compare(p_out));
31
}
32
}
33
else if (1==wParam)
34
{
35
36
}
37
return S_OK;
38
}
//在工作線程中,執(zhí)行調(diào)用同步webservice方法login2
void login_task::Run(const volatile BOOL& bExit)3
{4
assert(m_client);5
login_output out;6
if (m_client->login(*this,out))7
{8
boost::shared_ptr<void> sp(new login_output(out));9
boost::shared_ptr<ptr_container> sp_ptr = SingletonSmartPointerContainer::Instance().lock();10
if (sp_ptr) 11
{12
sp_ptr->add(sp);13
::PostMessage(m_hWnd,WM_LOGIN,0,(LPARAM)sp.get());14
}15
}16
else17
{18
::PostMessage(m_hWnd,WM_LOGIN,1,0);19
}20
}21
//在UI線程中,異步回調(diào)WM_LOGIN消息處理22
LRESULT Cvpn_ca_clientDlg::OnLoginCallback(WPARAM wParam,LPARAM lParam)23
{24
if (0==wParam)25
{26
login_output* p_out = (login_output*)lParam;27
boost::shared_ptr<ptr_container> sp = SingletonSmartPointerContainer::Instance().lock();28
if (sp) 29
{30
sp->erase(raw_ptr_compare(p_out));31
}32
}33
else if (1==wParam)34
{35

36
}37
return S_OK;38
}



