在《
基于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
23template<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 >
29class 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
35public:
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
76public:
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
213private:
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 }
291private:
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
7class raw_ptr_compare
8{
9public:
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 }
17private:
18 void* m_ptr;
19};
20
21typedef STLCollection<boost::shared_ptr<void> > ptr_container;
22typedef boost::weak_ptr<ptr_container> wp_ptr_container;
23
24#ifdef _LOKI_SINGLETON
25#include <loki/Singleton.h>
26
27template<class T>
28struct 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};
41typedef ::Loki::SingletonHolder<wp_ptr_container> SingletonSmartPointerContainer;
42#endif
43
44#endif 应用的示例代码如下:
1//在工作线程中,执行调用同步webservice方法login
2void 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消息处理
22LRESULT 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
春秋十二月 阅读(3150)
评论(1) 编辑 收藏 引用 所属分类:
Opensrc