]> git.cworth.org Git - apitrace/blob - common/workqueue_posix.cpp
9b02d6c0c2fc5683638280c99ac43182ae57ea73
[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     lock.lock();
16
17     while (work_queue.empty() && !exit_workqueue)
18         pthread_cond_wait(&wake_cond, &lock.native_handle());
19
20     if (exit_workqueue) {
21         lock.unlock();
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     pthread_cond_signal(&complete_cond);
45
46     lock.unlock();
47
48     return 0;
49 }
50
51 /* Must be called with WorkQueue::lock held */
52 void WorkQueue::wake_up_thread(void)
53 {
54     pthread_cond_signal(&wake_cond);
55 }
56
57 void WorkQueue::queue_work(WorkQueueWork *task)
58 {
59     lock.lock();
60     work_queue.push(task);
61     wake_up_thread();
62     lock.unlock();
63 }
64
65 void WorkQueue::flush(void)
66 {
67     lock.lock();
68     while (!work_queue.empty() || busy)
69         pthread_cond_wait(&complete_cond, &lock.native_handle());
70     lock.unlock();
71 }
72
73 void WorkQueue::thread_entry(void)
74 {
75     int err;
76
77     do {
78         err = run_tasks();
79     } while (!err);
80 }
81
82 void WorkQueue::destroy(void)
83 {
84     lock.lock();
85     exit_workqueue = true;
86     wake_up_thread();
87     lock.unlock();
88 }
89
90 extern "C"
91 void *WorkQueue__entry_thunk(void *data)
92 {
93     WorkQueue *thread = static_cast<WorkQueue *>(data);
94
95     thread->thread_entry();
96
97     return NULL;
98 }
99
100 WorkQueue::WorkQueue(void) :
101     busy(false), exit_workqueue(false)
102 {
103     int err;
104
105     pthread_cond_init(&wake_cond, NULL);
106     pthread_cond_init(&complete_cond, NULL);
107     err = pthread_create(&handle, NULL, WorkQueue__entry_thunk, this);
108     assert(!err);
109 }
110
111 WorkQueue::~WorkQueue(void)
112 {
113     pthread_join(handle, NULL);
114 }
115
116 }