1 #include "RNSkDispatchQueue.h"
2 
3 #include <memory>
4 #include <mutex>
5 #include <utility>
6 
7 namespace RNSkia {
8 
~RNSkDispatchQueue()9 RNSkDispatchQueue::~RNSkDispatchQueue() {
10   // Signal to dispatch threads that it's time to wrap up
11   std::unique_lock<std::mutex> lock(lock_);
12   quit_ = true;
13   lock.unlock();
14   cv_.notify_all();
15 
16   // Wait for threads to finish before we exit
17   for (size_t i = 0; i < threads_.size(); i++) {
18     if (threads_[i].joinable()) {
19       threads_[i].join();
20     }
21   }
22 }
23 
RNSkDispatchQueue(std::string name,size_t thread_cnt)24 RNSkDispatchQueue::RNSkDispatchQueue(std::string name, size_t thread_cnt)
25     : name_{std::move(name)}, threads_(thread_cnt) {
26   for (size_t i = 0; i < threads_.size(); i++) {
27     threads_[i] =
28         std::thread(&RNSkDispatchQueue::dispatch_thread_handler, this);
29   }
30 }
31 
dispatch(const fp_t & op)32 void RNSkDispatchQueue::dispatch(const fp_t &op) {
33   std::unique_lock<std::mutex> lock(lock_);
34   q_.push(op);
35 
36   // Manual unlocking is done before notifying, to avoid waking up
37   // the waiting thread only to block again (see notify_one for details)
38   lock.unlock();
39   cv_.notify_one();
40 }
41 
dispatch(fp_t && op)42 void RNSkDispatchQueue::dispatch(fp_t &&op) {
43   std::unique_lock<std::mutex> lock(lock_);
44   q_.push(std::move(op));
45 
46   // Manual unlocking is done before notifying, to avoid waking up
47   // the waiting thread only to block again (see notify_one for details)
48   lock.unlock();
49   cv_.notify_one();
50 }
51 
dispatch_thread_handler(void)52 void RNSkDispatchQueue::dispatch_thread_handler(void) {
53   std::unique_lock<std::mutex> lock(lock_);
54 
55   do {
56     // Wait until we have data or a quit signal
57     cv_.wait(lock, [this] { return (q_.size() || quit_); });
58 
59     // after wait, we own the lock
60     if (!quit_ && q_.size()) {
61       auto op = std::move(q_.front());
62       q_.pop();
63 
64       // unlock now that we're done messing with the queue
65       lock.unlock();
66 
67       op();
68 
69       lock.lock();
70     }
71   } while (!quit_);
72 }
73 } // namespace RNSkia
74