source: trunk/FACT++/src/queue.h@ 16482

Last change on this file since 16482 was 16481, checked in by tbretz, 12 years ago
included the header for list
File size: 3.3 KB
Line 
1#ifndef FACT_Queue
2#define FACT_Queue
3
4#include <list>
5#include <thread>
6#include <condition_variable>
7
8template<class T>
9class Queue : std::list<T>
10{
11 std::mutex fMutex; // Mutex needed for the conditional
12 std::condition_variable fCond; // Conditional
13
14 enum state_t
15 {
16 kIdle,
17 kRun,
18 kStop,
19 kAbort,
20 };
21
22 size_t fSize; // Only necessary for before C++11
23
24 state_t fState; // Stop signal for the thread
25
26 typedef std::function<void(const T &)> callback;
27 callback fCallback; // Callback function called by the thread
28
29 std::thread fThread; // Handle to the thread
30
31 void Thread()
32 {
33 std::unique_lock<std::mutex> lock(fMutex);
34
35 while (1)
36 {
37 while (std::list<T>::empty() && fState==kRun)
38 fCond.wait(lock);
39
40 if (fState==kAbort)
41 break;
42
43 if (fState==kStop && std::list<T>::empty())
44 break;
45
46 const T &val = std::list<T>::front();
47
48 // Theoretically, we can loose a signal here, but this is
49 // not a problem, because then we detect a non-empty queue
50 lock.unlock();
51
52 if (fCallback)
53 fCallback(val);
54
55 lock.lock();
56
57 std::list<T>::pop_front();
58 fSize--;
59 }
60
61 std::list<T>::clear();
62 fSize = 0;
63
64 fState = kIdle;
65 }
66
67public:
68 Queue(const callback &f) : fSize(0), fState(kIdle), fCallback(f)
69 {
70 start();
71 }
72 ~Queue()
73 {
74 wait(true);
75 }
76
77 bool start()
78 {
79 const std::lock_guard<std::mutex> lock(fMutex);
80 if (fState!=kIdle)
81 return false;
82
83 fState = kRun;
84 fThread = std::thread(std::bind(&Queue::Thread, this));
85 return true;
86 }
87
88 bool stop()
89 {
90 const std::lock_guard<std::mutex> lock(fMutex);
91 if (fState==kIdle)
92 return false;
93
94 fState = kStop;
95 fCond.notify_one();
96
97 return true;
98 }
99
100 bool abort()
101 {
102 const std::lock_guard<std::mutex> lock(fMutex);
103 if (fState==kIdle)
104 return false;
105
106 fState = kAbort;
107 fCond.notify_one();
108
109 return true;
110 }
111
112 bool wait(bool abrt=false)
113 {
114 {
115 const std::lock_guard<std::mutex> lock(fMutex);
116 if (fState==kIdle)
117 return false;
118
119 if (fState==kRun)
120 {
121 fState = abrt ? kAbort : kStop;
122 fCond.notify_one();
123 }
124 }
125
126 fThread.join();
127 return true;
128 }
129
130 bool post(const T &val)
131 {
132 const std::lock_guard<std::mutex> lock(fMutex);
133 if (fState==kIdle)
134 return false;
135
136 std::list<T>::push_back(val);
137 fSize++;
138
139 fCond.notify_one();
140
141 return true;
142 }
143
144#ifdef __GXX_EXPERIMENTAL_CXX0X__
145 template<typename... _Args>
146 bool emplace(_Args&&... __args)
147 {
148 const std::lock_guard<std::mutex> lock(fMutex);
149 if (fState==kIdle)
150 return false;
151
152 std::list<T>::emplace_back(__args...);
153 fSize++;
154
155 fCond.notify_one();
156
157 return true;
158
159 }
160
161 bool post(T &&val) { return emplace(std::move(val)); }
162#endif
163
164 size_t size() const
165 {
166 return fSize;
167 }
168};
169
170#endif
Note: See TracBrowser for help on using the repository browser.