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