41 |
41 |
42 #include "MainWindow.xaml.h" |
42 #include "MainWindow.xaml.h" |
43 |
43 |
44 #include "App.xaml.h" |
44 #include "App.xaml.h" |
45 |
45 |
46 #include <thread> |
|
47 |
|
48 using namespace winrt; |
46 using namespace winrt; |
49 using namespace Microsoft::UI::Xaml; |
47 using namespace Microsoft::UI::Xaml; |
50 using namespace Microsoft::UI::Xaml::Controls; |
48 using namespace Microsoft::UI::Xaml::Controls; |
51 using namespace Microsoft::UI::Xaml::XamlTypeInfo; |
49 using namespace Microsoft::UI::Xaml::XamlTypeInfo; |
52 using namespace Microsoft::UI::Xaml::Markup; |
50 using namespace Microsoft::UI::Xaml::Markup; |
249 event.eventdata = NULL; |
247 event.eventdata = NULL; |
250 job->finish_callback(&event, job->finish_data); |
248 job->finish_callback(&event, job->finish_data); |
251 } |
249 } |
252 |
250 |
253 static void ui_job_thread(UiJob* job) { |
251 static void ui_job_thread(UiJob* job) { |
254 if (!job->job_func(job->job_data)) { |
252 if (!job->job_func(job->job_data) && job->finish_callback) { |
255 bool isQueued = uiDispatcherQueue.TryEnqueue([job]() |
253 bool isQueued = uiDispatcherQueue.TryEnqueue([job]() |
256 { |
254 { |
257 UiEvent event; |
255 UiEvent event; |
258 event.obj = job->obj; |
256 event.obj = job->obj; |
259 event.window = job->obj->window; |
257 event.window = job->obj->window; |
293 if (!isQueued) { |
291 if (!isQueued) { |
294 // TODO: error or try again? |
292 // TODO: error or try again? |
295 exit(-1); |
293 exit(-1); |
296 } |
294 } |
297 } |
295 } |
|
296 |
|
297 static UiJob kill_job; // &kill_job indicates to stop the thread |
|
298 |
|
299 static void ui_threadpool_run(UiThreadpool* pool) { |
|
300 for (;;) { |
|
301 UiJob* job = pool->GetJob(); |
|
302 if (job == &kill_job) { |
|
303 return; |
|
304 } |
|
305 else if (job) { |
|
306 ui_job_thread(job); |
|
307 } |
|
308 } |
|
309 } |
|
310 |
|
311 UiThreadpool::UiThreadpool(int nthreads) { |
|
312 for (int i = 0; i < nthreads; i++) { |
|
313 std::thread thread(ui_threadpool_run, this); |
|
314 thread.detach(); |
|
315 } |
|
316 } |
|
317 |
|
318 void UiThreadpool::EnqueueJob(UiJob* job) |
|
319 { |
|
320 std::unique_lock<std::mutex> lock(mutex); |
|
321 queue.push(job); |
|
322 lock.unlock(); |
|
323 condition.notify_one(); |
|
324 } |
|
325 |
|
326 UiJob* UiThreadpool::GetJob() { |
|
327 std::unique_lock<std::mutex> lock(mutex); |
|
328 |
|
329 UiJob* job = nullptr; |
|
330 while (!job) { |
|
331 if (queue.empty()) { |
|
332 condition.wait(lock); |
|
333 continue; |
|
334 } |
|
335 else |
|
336 { |
|
337 job = queue.front(); |
|
338 queue.pop(); |
|
339 } |
|
340 } |
|
341 |
|
342 return job; |
|
343 } |
|
344 |
|
345 UIEXPORT UiThreadpool* ui_threadpool_create(int nthreads) { |
|
346 return new UiThreadpool(nthreads); |
|
347 } |
|
348 |
|
349 UIEXPORT void ui_threadpool_destroy(UiThreadpool* pool) { |
|
350 // TODO |
|
351 } |
|
352 |
|
353 UIEXPORT void ui_threadpool_job(UiThreadpool* pool, UiObject* obj, ui_threadfunc tf, void* td, ui_callback f, void* fd) { |
|
354 UiJob* job = new UiJob; |
|
355 job->obj = obj; |
|
356 job->job_func = tf; |
|
357 job->job_data = td; |
|
358 job->finish_callback = f; |
|
359 job->finish_data = fd; |
|
360 pool->EnqueueJob(job); |
|
361 } |
|
362 |