在《
基于stl序列容器實現的通用集合類》一文中,已經講到了具體實現,近來因再次用到它又改進完善了,主要體現在以下幾點:1)增加了查找操作方法,支持按值類型和謂詞條件兩種方式。2)增加重載了按值類型和謂詞條件2種方式刪除元素的方法。3)增加了2個模板參數以支持線程安全,一個是線程模型模板類,一個是互斥鎖類,使用loki庫來實現,因此所有方法現在都是線程安全的,當需要在多線程環境使用時,注意這里是對象級別鎖而不是類級別鎖,只需定義loki中的宏LOKI_OBJECT_LEVEL_THREADING即可;當在單線程環境使用時,LOKI_CLASS_LEVEL_THREADING和LOKI_OBJECT_LEVEL_THREADING兩個宏都不要定義。代碼如下:
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)實現的數據結構通用集合類
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 現在來看一下它的應用,一個網絡通訊項目,由UI客戶端(gsoap & c++開發)和服務端(java開發)構成,服務端已實現了一些web service的同步方法,客戶端需要調用它實現相關功能,為了不阻塞界面,因此需要轉化成異步方式調用,調用的結果使用PostMessage API 發自定義消息給窗口,因此發送消息方new 了一個結果的拷貝給窗口,窗口收到后再delete這個結果,但有個問題是post消息可能會丟失導致結果得不到釋放,產生內存泄露。因此設計一個智能指針容器而且是線程安全的,在發消息時將結果拷貝加到容器中,在接收方處理結果后再從容器中刪除它,這樣就可保證無內存泄露問題了。關于智能指針容器,boost中有ptr_vector,ptr_list,ptr_set等現成的,但是它們不是按照指針本身而是指針指向的對象來對待的,也就是說你要刪除其中的指針,是按照指針指向的對象來比較查找的,原因是其內部迭代器的訪問作了特殊處理,因此這點不符合上面應用的需求,當然可以在指針指向的對象中做點手腳,但是這方法有點勉強,應用要的只是刪除指針,而不必關心它指向的對象。為了達到目的又能最大程度地復用代碼,因此改進了STLCollection,簡單地實現了智能指針容器,代碼如下:
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 應用的示例代碼如下:
1
//在工作線程中,執行調用同步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線程中,異步回調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
}
posted on 2011-10-21 18:43
春秋十二月 閱讀(3173)
評論(1) 編輯 收藏 引用 所屬分類:
Opensrc