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