acl  3.5.3.0
tbox.hpp
浏览该文件的文档.
1 #pragma once
2 #include "../acl_cpp_define.hpp"
3 #include <list>
4 #include <stdlib.h>
5 #include "thread_mutex.hpp"
6 #include "thread_cond.hpp"
7 #include "noncopyable.hpp"
8 
9 namespace acl
10 {
11 
12 /**
13  * 用于线程之间的消息通信,通过线程条件变量及线程锁实现
14  *
15  * 示例:
16  *
17  * class myobj
18  * {
19  * public:
20  * myobj(void) {}
21  * ~myobj(void) {}
22  *
23  * void test(void) { printf("hello world\r\n"); }
24  * };
25  *
26  * acl::tbox<myobj> tbox;
27  *
28  * void thread_producer(void)
29  * {
30  * myobj* o = new myobj;
31  * tbox.push(o);
32  * }
33  *
34  * void thread_consumer(void)
35  * {
36  * myobj* o = tbox.pop();
37  * o->test();
38  * delete o;
39  * }
40  */
41 
42 template<typename T>
43 class tbox : public noncopyable
44 {
45 public:
46  /**
47  * 构造方法
48  * @param free_obj {bool} 当 tbox 销毁时,是否自动检查并释放
49  * 未被消费的动态对象
50  */
51  tbox(bool free_obj = true)
52  : size_(0), free_obj_(free_obj), cond_(&lock_) {}
53 
54  ~tbox(void)
55  {
56  clear(free_obj_);
57  }
58 
59  /**
60  * 清理消息队列中未被消费的消息对象
61  * @param free_obj {bool} 释放调用 delete 方法删除消息对象
62  */
63  void clear(bool free_obj = false)
64  {
65  if (free_obj) {
66  for (typename std::list<T*>::iterator it =
67  tbox_.begin(); it != tbox_.end(); ++it) {
68 
69  delete *it;
70  }
71  }
72  tbox_.clear();
73  }
74 
75  /**
76  * 发送消息对象
77  * @param t {T*} 非空消息对象
78  * @param notify_first {bool} 如果为 true,则先通知后解锁,否则先解锁
79  * 后通知,注意二者的区别
80  * @return {bool}
81  */
82  bool push(T* t, bool notify_first = true)
83  {
84  if (lock_.lock() == false) {
85  abort();
86  }
87  tbox_.push_back(t);
88  size_++;
89 
90  if (notify_first) {
91  if (cond_.notify() == false) {
92  abort();
93  }
94  if (lock_.unlock() == false) {
95  abort();
96  }
97  } else {
98  if (lock_.unlock() == false) {
99  abort();
100  }
101  if (cond_.notify() == false) {
102  abort();
103  }
104  }
105 
106  return true;
107  }
108 
109  /**
110  * 接收消息对象
111  * @param wait_ms {int} >= 0 时设置等待超时时间(毫秒级别),
112  * 否则永远等待直到读到消息对象或出错
113  * @param found {bool*} 非空时用来存放是否获得了一个消息对象,主要用在
114  * 当允许传递空对象时的检查
115  * @return {T*} 非 NULL 表示获得一个消息对象,返回 NULL 时得需要做进一
116  * 步检查,生产者如果 push 了一个空对象(NULL),则消费者也会获得 NULL,
117  * 但此时仍然认为获得了一个消息对象,只不过为空对象;如果 wait_ms 参数
118  * 为 -1 时返回 NULL 依然认为获得了一个空消息对象,如果 wait_ms 大于
119  * 等于 0 时返回 NULL,则应该检查 found 参数的值为 true 还是 false 来
120  * 判断是否获得了一个空消息对象
121  */
122  T* pop(int wait_ms = -1, bool* found = NULL)
123  {
124  long long n = ((long long) wait_ms) * 1000;
125  bool found_flag;
126  if (lock_.lock() == false) {
127  abort();
128  }
129  while (true) {
130  T* t = peek(found_flag);
131  if (found_flag) {
132  if (lock_.unlock() == false) {
133  abort();
134  }
135  if (found) {
136  *found = found_flag;
137  }
138  return t;
139  }
140 
141  // 注意调用顺序,必须先调用 wait 再判断 wait_ms
142  if (!cond_.wait(n, true) && wait_ms >= 0) {
143  if (lock_.unlock() == false) {
144  abort();
145  }
146  if (found) {
147  *found = false;
148  }
149  return NULL;
150  }
151  }
152  }
153 
154  /**
155  * 返回当前存在于消息队列中的消息数量
156  * @return {size_t}
157  */
158  size_t size(void) const
159  {
160  return size_;
161  }
162 
163 public:
164  void lock(void)
165  {
166  if (lock_.lock() == false) {
167  abort();
168  }
169  }
170 
171  void unlock(void)
172  {
173  if (lock_.unlock() == false) {
174  abort();
175  }
176  }
177 
178 private:
179  std::list<T*> tbox_;
180  size_t size_;
181  bool free_obj_;
182  thread_mutex lock_;
183  thread_cond cond_;
184 
185  T* peek(bool& found_flag)
186  {
187  typename std::list<T*>::iterator it = tbox_.begin();
188  if (it == tbox_.end()) {
189  found_flag = false;
190  return NULL;
191  }
192  found_flag = true;
193  size_--;
194  T* t = *it;
195  tbox_.erase(it);
196  return t;
197  }
198 };
199 
200 } // namespace acl
T * pop(int wait_ms=-1, bool *found=NULL)
Definition: tbox.hpp:122
void clear(bool free_obj=false)
Definition: tbox.hpp:63
bool wait(long long microseconds=-1, bool locked=false)
void unlock(void)
Definition: tbox.hpp:171
bool unlock(void)
~tbox(void)
Definition: tbox.hpp:54
tbox(bool free_obj=true)
Definition: tbox.hpp:51
bool push(T *t, bool notify_first=true)
Definition: tbox.hpp:82
void lock(void)
Definition: tbox.hpp:164
size_t size(void) const
Definition: tbox.hpp:158
bool notify(void)