OLD | NEW |
1 #include "SkTaskGroup.h" | 1 #include "SkTaskGroup.h" |
2 | 2 |
3 #include "SkCondVar.h" | 3 #include "SkCondVar.h" |
4 #include "SkTDArray.h" | 4 #include "SkTDArray.h" |
5 #include "SkThread.h" | 5 #include "SkThread.h" |
6 #include "SkThreadUtils.h" | 6 #include "SkThreadUtils.h" |
7 | 7 |
8 #if defined(SK_BUILD_FOR_WIN32) | 8 #if defined(SK_BUILD_FOR_WIN32) |
9 static inline int num_cores() { | 9 static inline int num_cores() { |
10 SYSTEM_INFO sysinfo; | 10 SYSTEM_INFO sysinfo; |
(...skipping 18 matching lines...) Expand all Loading... |
29 gGlobal->add(&CallRunnable, task, pending); | 29 gGlobal->add(&CallRunnable, task, pending); |
30 } | 30 } |
31 | 31 |
32 static void Add(void (*fn)(void*), void* arg, int32_t* pending) { | 32 static void Add(void (*fn)(void*), void* arg, int32_t* pending) { |
33 if (!gGlobal) { | 33 if (!gGlobal) { |
34 return fn(arg); | 34 return fn(arg); |
35 } | 35 } |
36 gGlobal->add(fn, arg, pending); | 36 gGlobal->add(fn, arg, pending); |
37 } | 37 } |
38 | 38 |
| 39 static void Batch(void (*fn)(void*), void* args, int N, size_t stride, int32
_t* pending) { |
| 40 if (!gGlobal) { |
| 41 for (int i = 0; i < N; i++) { fn((char*)args + i*stride); } |
| 42 return; |
| 43 } |
| 44 gGlobal->batch(fn, args, N, stride, pending); |
| 45 } |
| 46 |
39 static void Wait(int32_t* pending) { | 47 static void Wait(int32_t* pending) { |
40 if (!gGlobal) { // If we have no threads, the work must already be done
. | 48 if (!gGlobal) { // If we have no threads, the work must already be done
. |
41 SkASSERT(*pending == 0); | 49 SkASSERT(*pending == 0); |
42 return; | 50 return; |
43 } | 51 } |
44 while (sk_acquire_load(pending) > 0) { // Pairs with sk_atomic_dec here
or in Loop. | 52 while (sk_acquire_load(pending) > 0) { // Pairs with sk_atomic_dec here
or in Loop. |
45 // Lend a hand until our SkTaskGroup of interest is done. | 53 // Lend a hand until our SkTaskGroup of interest is done. |
46 Work work; | 54 Work work; |
47 { | 55 { |
48 AutoLock lock(&gGlobal->fReady); | 56 AutoLock lock(&gGlobal->fReady); |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
103 void add(void (*fn)(void*), void* arg, int32_t* pending) { | 111 void add(void (*fn)(void*), void* arg, int32_t* pending) { |
104 Work work = { fn, arg, pending }; | 112 Work work = { fn, arg, pending }; |
105 sk_atomic_inc(pending); // No barrier needed. | 113 sk_atomic_inc(pending); // No barrier needed. |
106 { | 114 { |
107 AutoLock lock(&fReady); | 115 AutoLock lock(&fReady); |
108 fWork.push(work); | 116 fWork.push(work); |
109 fReady.signal(); | 117 fReady.signal(); |
110 } | 118 } |
111 } | 119 } |
112 | 120 |
| 121 void batch(void (*fn)(void*), void* arg, int N, size_t stride, int32_t* pend
ing) { |
| 122 sk_atomic_add(pending, N); // No barrier needed. |
| 123 { |
| 124 AutoLock lock(&fReady); |
| 125 Work* batch = fWork.append(N); |
| 126 for (int i = 0; i < N; i++) { |
| 127 Work work = { fn, (char*)arg + i*stride, pending }; |
| 128 batch[i] = work; |
| 129 } |
| 130 fReady.broadcast(); |
| 131 } |
| 132 } |
| 133 |
113 static void Loop(void* arg) { | 134 static void Loop(void* arg) { |
114 ThreadPool* pool = (ThreadPool*)arg; | 135 ThreadPool* pool = (ThreadPool*)arg; |
115 Work work; | 136 Work work; |
116 while (true) { | 137 while (true) { |
117 { | 138 { |
118 AutoLock lock(&pool->fReady); | 139 AutoLock lock(&pool->fReady); |
119 while (pool->fWork.isEmpty()) { | 140 while (pool->fWork.isEmpty()) { |
120 if (pool->fDraining) { | 141 if (pool->fDraining) { |
121 return; | 142 return; |
122 } | 143 } |
(...skipping 24 matching lines...) Expand all Loading... |
147 ThreadPool::gGlobal = SkNEW_ARGS(ThreadPool, (threads)); | 168 ThreadPool::gGlobal = SkNEW_ARGS(ThreadPool, (threads)); |
148 } | 169 } |
149 } | 170 } |
150 | 171 |
151 SkTaskGroup::Enabler::~Enabler() { | 172 SkTaskGroup::Enabler::~Enabler() { |
152 SkDELETE(ThreadPool::gGlobal); | 173 SkDELETE(ThreadPool::gGlobal); |
153 } | 174 } |
154 | 175 |
155 SkTaskGroup::SkTaskGroup() : fPending(0) {} | 176 SkTaskGroup::SkTaskGroup() : fPending(0) {} |
156 | 177 |
| 178 void SkTaskGroup::wait() { ThreadPool::Wait(&fPending
); } |
157 void SkTaskGroup::add(SkRunnable* task) { ThreadPool::Add(task, &fPe
nding); } | 179 void SkTaskGroup::add(SkRunnable* task) { ThreadPool::Add(task, &fPe
nding); } |
158 void SkTaskGroup::add(void (*fn)(void*), void* arg) { ThreadPool::Add(fn, arg, &
fPending); } | 180 void SkTaskGroup::add(void (*fn)(void*), void* arg) { ThreadPool::Add(fn, arg, &
fPending); } |
159 void SkTaskGroup::wait() { ThreadPool::Wait(&fPending
); } | 181 void SkTaskGroup::batch (void (*fn)(void*), void* args, int N, size_t stride) { |
| 182 ThreadPool::Batch(fn, args, N, stride, &fPending); |
| 183 } |
160 | 184 |
OLD | NEW |