]> git.cworth.org Git - apitrace/blob - common/workqueue_posix.cpp
f46bbd977bd20ee87e5e273539df8512a38ac41d
[apitrace] / common / workqueue_posix.cpp
1 #include <pthread.h>
2 #include <queue>
3 #include <assert.h>
4
5 #include "os_workqueue.hpp"
6
7 namespace os
8 {
9
10 /**
11  * return 0 on batch complete, -1 on thread exit request.
12  */
13 int WorkQueue::run_tasks(void)
14 {
15     os::unique_lock<os::mutex> lock(mutex);
16
17     while (work_queue.empty() && !exit_workqueue) {
18         wake_cond.wait(lock);
19     }
20
21     if (exit_workqueue) {
22         return -1;
23     }
24
25     std::queue<WorkQueueWork *> batch;
26     std::swap(work_queue, batch);
27     busy = true;
28
29     lock.unlock();
30
31     assert(!batch.empty());
32     while (!batch.empty()) {
33         WorkQueueWork *task;
34
35         task = batch.front();
36         task->run();
37         batch.pop();
38         delete task;
39     }
40
41     lock.lock();
42
43     busy = false;
44     complete_cond.signal();
45
46     return 0;
47 }
48
49 /* Must be called with WorkQueue::lock held */
50 void WorkQueue::wake_up_thread(void)
51 {
52     wake_cond.signal();
53 }
54
55 void WorkQueue::queue_work(WorkQueueWork *task)
56 {
57     mutex.lock();
58     work_queue.push(task);
59     wake_up_thread();
60     mutex.unlock();
61 }
62
63 void WorkQueue::flush(void)
64 {
65     os::unique_lock<os::mutex> lock(mutex);
66     while (!work_queue.empty() || busy) {
67         complete_cond.wait(lock);
68     }
69 }
70
71 void WorkQueue::thread_entry(void)
72 {
73     int err;
74
75     do {
76         err = run_tasks();
77     } while (!err);
78 }
79
80 void WorkQueue::destroy(void)
81 {
82     mutex.lock();
83     exit_workqueue = true;
84     wake_up_thread();
85     mutex.unlock();
86 }
87
88 extern "C"
89 void *WorkQueue__entry_thunk(void *data)
90 {
91     WorkQueue *thread = static_cast<WorkQueue *>(data);
92
93     thread->thread_entry();
94
95     return NULL;
96 }
97
98 WorkQueue::WorkQueue(void) :
99     busy(false), exit_workqueue(false)
100 {
101     int err;
102
103     err = pthread_create(&handle, NULL, WorkQueue__entry_thunk, this);
104     assert(!err);
105 }
106
107 WorkQueue::~WorkQueue(void)
108 {
109     pthread_join(handle, NULL);
110 }
111
112 }