|
9 | 9 |
|
10 | 10 | template<typename T> class Queue
|
11 | 11 | {
|
| 12 | + private: |
| 13 | + template<typename M> class ulock : public std::unique_lock<M> { |
| 14 | + std::condition_variable& cv; |
| 15 | + public: |
| 16 | + ulock(M& m, std::condition_variable& cv_) : std::unique_lock<M>(m), cv(cv_) {} |
| 17 | + void unlock() { std::unique_lock<M>::unlock(); cv.notify_all(); } |
| 18 | + }; |
| 19 | + |
12 | 20 | public:
|
13 | 21 | Queue(const unsigned limit_) : limit(limit_) {}
|
14 | 22 |
|
15 | 23 | inline T pop()
|
16 | 24 | {
|
17 |
| - std::unique_lock<std::mutex> lock(mutex); |
| 25 | + // std::unique_lock<std::mutex> lock_(mutex); |
| 26 | + ulock<std::mutex> lock_(mutex, cv2); |
18 | 27 |
|
19 | 28 | if (queue.empty()) {
|
20 |
| - cv1.wait(lock, [this] { return !queue.empty(); }); |
| 29 | + cv1.wait(lock_, [this] { return !queue.empty(); }); |
21 | 30 | }
|
22 | 31 |
|
23 | 32 | T item = queue.front();
|
24 | 33 | queue.pop_front();
|
25 |
| - lock.unlock(); |
26 |
| - cv2.notify_all(); |
| 34 | + // lock_.unlock(); |
| 35 | + // cv2.notify_all(); |
27 | 36 |
|
28 | 37 | return item;
|
29 | 38 | }
|
30 | 39 |
|
31 |
| - void try_fetch(const std::function<void (T&)>& cb, const std::chrono::milliseconds timeout) |
| 40 | + inline void try_fetch(const std::function<void (T&)>& cb, const std::chrono::milliseconds timeout) |
32 | 41 | {
|
33 |
| - std::unique_lock<std::mutex> lock(mutex); |
34 |
| - |
35 |
| - if (!queue.empty() || cv1.wait_for(lock, timeout, [this] { return !queue.empty(); })) { |
36 |
| - unsigned cnt = queue.size(); |
37 |
| - do { |
38 |
| - T item = queue.front(); |
39 |
| - queue.pop_front(); |
40 |
| - lock.unlock(); |
41 |
| - cv2.notify_all(); |
42 |
| - |
43 |
| - cb(item); |
44 |
| - |
45 |
| - if (--cnt) { |
46 |
| - lock.lock(); |
47 |
| - continue; |
48 |
| - } |
49 |
| - } while (false); |
| 42 | + // std::unique_lock<std::mutex> lock_(mutex); |
| 43 | + ulock<std::mutex> lock_(mutex, cv2); |
| 44 | + |
| 45 | + if (queue.empty() && !cv1.wait_for(lock_, timeout, [this] { return !queue.empty(); })) { |
| 46 | + return; |
50 | 47 | }
|
51 | 48 |
|
52 |
| - lock.unlock(); |
53 |
| - cv2.notify_all(); |
| 49 | + unsigned cnt = queue.size(); |
| 50 | + do { |
| 51 | + T item = queue.front(); |
| 52 | + queue.pop_front(); |
| 53 | + lock_.unlock(); |
| 54 | + //cv2.notify_all(); |
| 55 | + |
| 56 | + cb(item); |
| 57 | + |
| 58 | + if (--cnt) { |
| 59 | + lock_.lock(); |
| 60 | + continue; |
| 61 | + } |
| 62 | + } while (false); |
54 | 63 | }
|
55 | 64 |
|
56 | 65 | inline void push(const T& item)
|
57 | 66 | {
|
58 |
| - std::unique_lock<std::mutex> lock(mutex); |
| 67 | + // std::unique_lock<std::mutex> lock_(mutex); |
| 68 | + ulock<std::mutex> lock_(mutex, cv1); |
59 | 69 |
|
60 | 70 | if (queue.size() >= limit) {
|
61 |
| - cv2.wait(lock, [this] { return queue.size() < limit; }); |
| 71 | + cv2.wait(lock_, [this] { return queue.size() < limit; }); |
62 | 72 | }
|
63 | 73 |
|
64 | 74 | queue.push_back(item);
|
65 |
| - lock.unlock(); |
66 |
| - cv1.notify_one(); |
| 75 | + // lock_.unlock(); |
| 76 | + // cv1.notify_one(); |
67 | 77 | }
|
68 | 78 |
|
69 | 79 | inline unsigned size() const {
|
70 |
| - // std::lock_guard<std::mutex> lock(mutex); |
| 80 | + // std::lock_guard<std::mutex> lock_(mutex); |
71 | 81 | return queue.size();
|
72 | 82 | }
|
73 | 83 |
|
|
0 commit comments