48 using namespace Microsoft::UI::Xaml::Controls; |
48 using namespace Microsoft::UI::Xaml::Controls; |
49 using namespace Microsoft::UI::Xaml::XamlTypeInfo; |
49 using namespace Microsoft::UI::Xaml::XamlTypeInfo; |
50 using namespace Microsoft::UI::Xaml::Markup; |
50 using namespace Microsoft::UI::Xaml::Markup; |
51 using namespace Windows::UI::Xaml::Interop; |
51 using namespace Windows::UI::Xaml::Interop; |
52 using namespace winrt::Windows::Foundation; |
52 using namespace winrt::Windows::Foundation; |
|
53 using namespace Windows::UI::Core; |
53 |
54 |
54 static const char* application_name; |
55 static const char* application_name; |
55 |
56 |
56 static ui_callback startup_func; |
57 static ui_callback startup_func; |
57 static void* startup_data; |
58 static void* startup_data; |
67 static void* appclose_udata; |
68 static void* appclose_udata; |
68 |
69 |
69 |
70 |
70 static UiObject* active_window; |
71 static UiObject* active_window; |
71 |
72 |
|
73 static winrt::Microsoft::UI::Dispatching::DispatcherQueue uiDispatcherQueue = { nullptr }; |
|
74 |
72 void ui_app_run_startup() { |
75 void ui_app_run_startup() { |
|
76 uiDispatcherQueue = winrt::Microsoft::UI::Dispatching::DispatcherQueue::GetForCurrentThread(); |
|
77 |
73 if (startup_func) { |
78 if (startup_func) { |
74 startup_func(NULL, startup_data); |
79 startup_func(NULL, startup_data); |
75 } |
80 } |
76 } |
81 } |
77 |
82 |
231 |
236 |
232 void ui_close(UiObject* obj) { |
237 void ui_close(UiObject* obj) { |
233 |
238 |
234 } |
239 } |
235 |
240 |
|
241 static void ui_job_finished(UiJob *job) { |
|
242 UiEvent event; |
|
243 event.obj = job->obj; |
|
244 event.window = job->obj->window; |
|
245 event.document = job->obj->ctx->document; |
|
246 event.intval = 0; |
|
247 event.eventdata = NULL; |
|
248 job->finish_callback(&event, job->finish_data); |
|
249 } |
|
250 |
|
251 static void ui_job_thread(UiJob* job) { |
|
252 if (!job->job_func(job->job_data) && job->finish_callback) { |
|
253 bool isQueued = uiDispatcherQueue.TryEnqueue([job]() |
|
254 { |
|
255 UiEvent event; |
|
256 event.obj = job->obj; |
|
257 event.window = job->obj->window; |
|
258 event.document = job->obj->ctx->document; |
|
259 event.intval = 0; |
|
260 event.eventdata = NULL; |
|
261 job->finish_callback(&event, job->finish_data); |
|
262 delete job; |
|
263 }); |
|
264 if (!isQueued) { |
|
265 // TODO: error or try again? |
|
266 exit(-1); |
|
267 } |
|
268 } |
|
269 else { |
|
270 delete job; |
|
271 } |
|
272 } |
|
273 |
|
274 UIEXPORT void ui_job(UiObject* obj, ui_threadfunc tf, void* td, ui_callback f, void* fd) { |
|
275 UiJob* job = new UiJob; |
|
276 job->obj = obj; |
|
277 job->job_func = tf; |
|
278 job->job_data = td; |
|
279 job->finish_callback = f; |
|
280 job->finish_data = fd; |
|
281 |
|
282 std::thread jobThread(ui_job_thread, job); |
|
283 jobThread.detach(); |
|
284 } |
|
285 |
|
286 UIEXPORT void ui_call_mainthread(ui_threadfunc tf, void* td) { |
|
287 bool isQueued = uiDispatcherQueue.TryEnqueue([tf, td]() |
|
288 { |
|
289 (void)tf(td); |
|
290 }); |
|
291 if (!isQueued) { |
|
292 // TODO: error or try again? |
|
293 exit(-1); |
|
294 } |
|
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 |