Blender V5.0
wm_jobs.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2009 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
10
11#include <cstring>
12
14
15#include "MEM_guardedalloc.h"
16
17#include "BLI_build_config.h"
18#include "BLI_listbase.h"
19#include "BLI_string.h"
20#include "BLI_threads.h"
21#include "BLI_time.h"
22#include "BLI_utildefines.h"
23
24#if OS_WINDOWS
25# include "BLI_winstuff.h"
26#endif
27
28#include "BKE_global.hh"
29#include "BKE_report.hh"
30
31#include "SEQ_prefetch.hh"
32
33#include "WM_api.hh"
34#include "WM_types.hh"
35#include "wm.hh"
36#include "wm_event_types.hh"
37
38/*
39 * Add new job
40 * - register in WM
41 * - configure callbacks
42 *
43 * Start or re-run job
44 * - if job running
45 * - signal job to end
46 * - add timer notifier to verify when it has ended, to start it
47 * - else
48 * - start job
49 * - add timer notifier to handle progress
50 *
51 * Stop job
52 * - signal job to end
53 * on end, job will tag itself as sleeping
54 *
55 * Remove job
56 * - signal job to end
57 * on end, job will remove itself
58 *
59 * When job is done:
60 * - it puts timer to sleep (or removes?)
61 */
62
63struct wmJob {
65
68
75 void (*initjob)(void *);
85 void (*update)(void *);
90 void (*free)(void *);
95 void (*endjob)(void *);
100 void (*completed)(void *);
105 void (*canceled)(void *);
106
108 double time_step;
114
115 /* Internal. */
116 const void *owner;
120
123
125 char name[128];
126
129 void (*run_free)(void *);
130
133
135
141};
142
143/* Main thread locking. */
144
149
154
155static void wm_job_main_thread_yield(wmJob *wm_job)
156{
157 /* Unlock and lock the ticket mutex. because it's a fair mutex any job that
158 * is waiting to acquire the lock will get it first, before we can lock. */
161}
162
164{
165 /* A QoS API is currently only available for Windows. */
166#if OS_WINDOWS
167 LISTBASE_FOREACH (wmJob *, wm_job, &wm->runtime->jobs) {
168 if (wm_job->flag & WM_JOB_PRIORITY) {
170 return;
171 }
172 }
173
175#else
176 UNUSED_VARS(wm);
177#endif
178}
179
182static wmJob *wm_job_find(const wmWindowManager *wm, const void *owner, const eWM_JobType job_type)
183{
184 if (owner && (job_type != WM_JOB_TYPE_ANY)) {
185 LISTBASE_FOREACH (wmJob *, wm_job, &wm->runtime->jobs) {
186 if (wm_job->owner == owner && wm_job->job_type == job_type) {
187 return wm_job;
188 }
189 }
190 }
191 else if (owner) {
192 LISTBASE_FOREACH (wmJob *, wm_job, &wm->runtime->jobs) {
193 if (wm_job->owner == owner) {
194 return wm_job;
195 }
196 }
197 }
198 else if (job_type != WM_JOB_TYPE_ANY) {
199 LISTBASE_FOREACH (wmJob *, wm_job, &wm->runtime->jobs) {
200 if (wm_job->job_type == job_type) {
201 return wm_job;
202 }
203 }
204 }
205
206 return nullptr;
207}
208
209/* ******************* public API ***************** */
210
212 wmWindow *win,
213 const void *owner,
214 const char *name,
215 const eWM_JobFlag flag,
216 const eWM_JobType job_type)
217{
218 wmJob *wm_job = wm_job_find(wm, owner, job_type);
219
220 if (wm_job == nullptr) {
221 wm_job = MEM_callocN<wmJob>("new job");
222
223 BLI_addtail(&wm->runtime->jobs, wm_job);
224 wm_job->win = win;
225 wm_job->owner = owner;
226 wm_job->flag = flag;
227 wm_job->job_type = job_type;
228 STRNCPY(wm_job->name, name);
229
232
236
238 }
239 /* Else: a running job, be careful. */
240
241 /* Prevent creating a job with an invalid type. */
243
244 return wm_job;
245}
246
247bool WM_jobs_test(const wmWindowManager *wm, const void *owner, int job_type)
248{
249 /* Job can be running or about to run (suspended). */
250 LISTBASE_FOREACH (wmJob *, wm_job, &wm->runtime->jobs) {
251 if (wm_job->owner != owner) {
252 continue;
253 }
254
255 if (!ELEM(job_type, WM_JOB_TYPE_ANY, wm_job->job_type)) {
256 continue;
257 }
258
259 if ((wm_job->flag & WM_JOB_PROGRESS) && (wm_job->running || wm_job->suspended)) {
260 return true;
261 }
262 }
263
264 return false;
265}
266
267float WM_jobs_progress(const wmWindowManager *wm, const void *owner)
268{
269 const wmJob *wm_job = wm_job_find(wm, owner, WM_JOB_TYPE_ANY);
270
271 if (wm_job && wm_job->flag & WM_JOB_PROGRESS) {
272 return wm_job->worker_status.progress;
273 }
274
275 return 0.0;
276}
277
279{
280 float total_progress = 0.0f;
281 float jobs_progress = 0;
282
283 LISTBASE_FOREACH (wmJob *, wm_job, &wm->runtime->jobs) {
284 if (wm_job->threads.first && !wm_job->ready) {
285 if (wm_job->flag & WM_JOB_PROGRESS) {
286 /* Accumulate global progress for running jobs. */
287 jobs_progress++;
288 total_progress += wm_job->worker_status.progress;
289 }
290 }
291 }
292
293 /* If there are running jobs, set the global progress indicator. */
294 if (jobs_progress > 0) {
295 float progress = total_progress / jobs_progress;
296
297 LISTBASE_FOREACH (wmWindow *, win, &wm->windows) {
298 WM_progress_set(win, progress);
299 }
300 }
301 else {
302 LISTBASE_FOREACH (wmWindow *, win, &wm->windows) {
304 }
305 }
306}
307
308double WM_jobs_starttime(const wmWindowManager *wm, const void *owner)
309{
310 const wmJob *wm_job = wm_job_find(wm, owner, WM_JOB_TYPE_ANY);
311
312 if (wm_job && wm_job->flag & WM_JOB_PROGRESS) {
313 return wm_job->start_time;
314 }
315
316 return 0;
317}
318
319const char *WM_jobs_name(const wmWindowManager *wm, const void *owner)
320{
321 wmJob *wm_job = wm_job_find(wm, owner, WM_JOB_TYPE_ANY);
322
323 if (wm_job) {
324 return wm_job->name;
325 }
326
327 return nullptr;
328}
329
330void *WM_jobs_customdata_from_type(wmWindowManager *wm, const void *owner, int job_type)
331{
332 wmJob *wm_job = wm_job_find(wm, owner, eWM_JobType(job_type));
333
334 if (wm_job) {
335 return WM_jobs_customdata_get(wm_job);
336 }
337
338 return nullptr;
339}
340
341bool WM_jobs_is_running(const wmJob *wm_job)
342{
343 return wm_job->running;
344}
345
346bool WM_jobs_is_stopped(const wmWindowManager *wm, const void *owner)
347{
348 wmJob *wm_job = wm_job_find(wm, owner, WM_JOB_TYPE_ANY);
349 return wm_job ? wm_job->worker_status.stop : true; /* XXX to be redesigned properly. */
350}
351
353{
354 if (!wm_job->customdata) {
355 return wm_job->run_customdata;
356 }
357 return wm_job->customdata;
358}
359
360void WM_jobs_customdata_set(wmJob *wm_job, void *customdata, void (*free)(void *customdata))
361{
362 /* Pending job? just free. */
363 if (wm_job->customdata) {
364 wm_job->free(wm_job->customdata);
365 }
366
367 wm_job->customdata = customdata;
368 wm_job->free = free;
369
370 if (wm_job->running) {
371 /* Signal job to end. */
372 wm_job->worker_status.stop = true;
373 }
374}
375
376void WM_jobs_timer(wmJob *wm_job, double time_step, uint note, uint endnote)
377{
378 wm_job->time_step = time_step;
379 wm_job->note = note;
380 wm_job->endnote = endnote;
381}
382
383void WM_jobs_delay_start(wmJob *wm_job, double delay_time)
384{
385 wm_job->start_delay_time = delay_time;
386}
387
389 wm_jobs_start_callback startjob,
390 void (*initjob)(void *),
391 void (*update)(void *),
392 void (*endjob)(void *))
393{
394 WM_jobs_callbacks_ex(wm_job, startjob, initjob, update, endjob, nullptr, nullptr);
395}
396
398 wm_jobs_start_callback startjob,
399 void (*initjob)(void *),
400 void (*update)(void *),
401 void (*endjob)(void *),
402 void (*completed)(void *),
403 void (*canceled)(void *))
404{
405 wm_job->startjob = startjob;
406 wm_job->initjob = initjob;
407 wm_job->update = update;
408 wm_job->endjob = endjob;
409 wm_job->completed = completed;
410 wm_job->canceled = canceled;
411}
412
417
418static void *do_job_thread(void *job_v)
419{
420 wmJob *wm_job = static_cast<wmJob *>(job_v);
421
422 wm_job->startjob(wm_job->run_customdata, &wm_job->worker_status);
423 wm_job->ready = true;
424
425 return nullptr;
426}
427
428/* Don't allow same startjob to be executed twice. */
430{
431 bool suspend = false;
432
433 /* Job added with suspend flag, we wait 1 timer step before activating it. */
434 if (test->start_delay_time > 0.0) {
435 suspend = true;
436 test->start_delay_time = 0.0;
437 }
438 else {
439 /* Check other jobs. */
440 LISTBASE_FOREACH (wmJob *, wm_job, &wm->runtime->jobs) {
441 /* Obvious case, no test needed. */
442 if (wm_job == test || !wm_job->running) {
443 continue;
444 }
445
446 /* If new job is not render, then check for same job type. */
447 if (0 == (test->flag & WM_JOB_EXCL_RENDER)) {
448 if (wm_job->job_type != test->job_type) {
449 continue;
450 }
451 }
452
453 /* If new job is render, any render job should be stopped. */
454 if (test->flag & WM_JOB_EXCL_RENDER) {
455 if (0 == (wm_job->flag & WM_JOB_EXCL_RENDER)) {
456 continue;
457 }
458 }
459
460 suspend = true;
461
462 /* If this job has higher priority, stop others. */
463 if (test->flag & WM_JOB_PRIORITY) {
464 wm_job->worker_status.stop = true;
465 // printf("job stopped: %s\n", wm_job->name);
466 }
467 }
468 }
469
470 /* Possible suspend ourselves, waiting for other jobs, or de-suspend. */
471 test->suspended = suspend;
472#if 0
473 if (suspend) {
474 printf("job suspended: %s\n", test->name);
475 }
476#endif
477}
478
480{
481 if (wm_job->running) {
482 /* Signal job to end and restart. */
483 wm_job->worker_status.stop = true;
484 // printf("job started a running job, ending... %s\n", wm_job->name);
485 }
486 else {
487
488 if (wm_job->customdata && wm_job->startjob) {
489 const double time_step = (wm_job->start_delay_time > 0.0) ? wm_job->start_delay_time :
490 wm_job->time_step;
491
492 wm_jobs_test_suspend_stop(wm, wm_job);
493
494 if (wm_job->suspended == false) {
495 /* Copy to ensure proper free in end. */
496 wm_job->run_customdata = wm_job->customdata;
497 wm_job->run_free = wm_job->free;
498 wm_job->free = nullptr;
499 wm_job->customdata = nullptr;
500 wm_job->running = true;
501
502 if (wm_job->initjob) {
503 wm_job->initjob(wm_job->run_customdata);
504 }
505
506 wm_job->worker_status.stop = false;
507 wm_job->ready = false;
508 wm_job->worker_status.progress = 0.0;
509
510 // printf("job started: %s\n", wm_job->name);
511
513 BLI_threadpool_insert(&wm_job->threads, wm_job);
514 }
515
516 /* Restarted job has timer already. */
517 if (wm_job->wt && (wm_job->wt->time_step > time_step)) {
518 WM_event_timer_remove(wm, wm_job->win, wm_job->wt);
519 wm_job->wt = WM_event_timer_add(wm, wm_job->win, TIMERJOBS, time_step);
520 }
521 if (wm_job->wt == nullptr) {
522 wm_job->wt = WM_event_timer_add(wm, wm_job->win, TIMERJOBS, time_step);
523 }
524
526 }
527 else {
528 printf("job fails, not initialized\n");
529 }
530 }
531}
532
533static void wm_job_end(wmWindowManager *wm, wmJob *wm_job)
534{
535 BLI_assert_msg(BLI_thread_is_main(), "wm_job_end should only be called from the main thread");
536 if (wm_job->endjob) {
537 wm_job->endjob(wm_job->run_customdata);
538 }
539
540 /* Do the final callback based on whether the job was run to completion or not.
541 * Not all jobs have the same way of signaling cancellation (i.e. rendering stops when
542 * `G.is_break == true`, but doesn't set any wm_job properties to cancel the WM job). */
543 const bool was_canceled = wm_job->worker_status.stop || G.is_break;
544 void (*final_callback)(void *) = (wm_job->ready && !was_canceled) ? wm_job->completed :
545 wm_job->canceled;
546 if (final_callback) {
547 final_callback(wm_job->run_customdata);
548 }
549
550 /* Ensure all reports have been moved to WM. */
551 wm_jobs_reports_update(wm, wm_job);
552}
553
554static void wm_job_free(wmWindowManager *wm, wmJob *wm_job)
555{
556 BLI_remlink(&wm->runtime->jobs, wm_job);
559
562 MEM_delete(wm_job->worker_status.reports);
563 MEM_freeN(wm_job);
564
566}
567
568/* Stop job, end thread, free data completely. */
569static void wm_jobs_kill_job(wmWindowManager *wm, wmJob *wm_job)
570{
571 bool update_progress = (wm_job->flag & WM_JOB_PROGRESS) != 0;
572
573 if (wm_job->running) {
574 /* Signal job to end. */
575 wm_job->worker_status.stop = true;
576
578 BLI_threadpool_end(&wm_job->threads);
580 wm_job_end(wm, wm_job);
581 }
582
583 if (wm_job->wt) {
584 WM_event_timer_remove(wm, wm_job->win, wm_job->wt);
585 }
586 if (wm_job->customdata) {
587 wm_job->free(wm_job->customdata);
588 }
589 if (wm_job->run_customdata) {
590 wm_job->run_free(wm_job->run_customdata);
591 }
592
593 /* Remove wm_job. */
594 wm_job_free(wm, wm_job);
595
596 /* Update progress bars in windows. */
597 if (update_progress) {
599 }
600}
601
603{
604 wmJob *wm_job;
605
606 while ((wm_job = static_cast<wmJob *>(wm->runtime->jobs.first))) {
607 wm_jobs_kill_job(wm, wm_job);
608 }
609
610 /* This job will be automatically restarted. */
612}
613
614void WM_jobs_kill_all_except(wmWindowManager *wm, const void *owner)
615{
616 LISTBASE_FOREACH_MUTABLE (wmJob *, wm_job, &wm->runtime->jobs) {
617 if (wm_job->owner != owner) {
618 wm_jobs_kill_job(wm, wm_job);
619 }
620 }
621}
622
623void WM_jobs_kill_type(wmWindowManager *wm, const void *owner, int job_type)
624{
625 BLI_assert(job_type != WM_JOB_TYPE_ANY);
626
627 LISTBASE_FOREACH_MUTABLE (wmJob *, wm_job, &wm->runtime->jobs) {
628 if (owner && wm_job->owner != owner) {
629 continue;
630 }
631
632 if (wm_job->job_type == job_type) {
633 wm_jobs_kill_job(wm, wm_job);
634 }
635 }
636}
637
639{
640 LISTBASE_FOREACH_MUTABLE (wmJob *, wm_job, &wm->runtime->jobs) {
641 if (wm_job->owner == owner) {
642 wm_jobs_kill_job(wm, wm_job);
643 }
644 }
645}
646
647void WM_jobs_stop_type(wmWindowManager *wm, const void *owner, eWM_JobType job_type)
648{
649 BLI_assert(job_type != WM_JOB_TYPE_ANY);
650
651 LISTBASE_FOREACH (wmJob *, wm_job, &wm->runtime->jobs) {
652 if (owner && wm_job->owner != owner) {
653 continue;
654 }
655 if (wm_job->job_type == job_type) {
656 if (wm_job->running) {
657 wm_job->worker_status.stop = true;
658 }
659 }
660 }
661}
662
664{
665 LISTBASE_FOREACH (wmJob *, wm_job, &wm->runtime->jobs) {
666 if (wm_job->owner == owner) {
667 if (wm_job->running) {
668 wm_job->worker_status.stop = true;
669 }
670 }
671 }
672}
673
675{
676 wmJob *wm_job = static_cast<wmJob *>(BLI_findptr(&wm->runtime->jobs, wt, offsetof(wmJob, wt)));
677 if (wm_job) {
678 wm_jobs_kill_job(wm, wm_job);
679 }
680}
681
683{
684 wmJob *wm_job = static_cast<wmJob *>(BLI_findptr(&wm->runtime->jobs, wt, offsetof(wmJob, wt)));
685
686 if (wm_job) {
687 /* Running threads. */
688 if (wm_job->threads.first) {
689 /* Let threads get temporary lock over main thread if needed. */
691
692 /* Always call note and update when ready. */
693 if (wm_job->worker_status.do_update || wm_job->ready) {
694 if (wm_job->update) {
695 wm_job->update(wm_job->run_customdata);
696 }
697 if (wm_job->note) {
698 WM_event_add_notifier_ex(wm, wm_job->win, wm_job->note, nullptr);
699 }
700
701 if (wm_job->flag & WM_JOB_PROGRESS) {
702 WM_event_add_notifier_ex(wm, wm_job->win, NC_WM | ND_JOB, nullptr);
703 }
704 wm_job->worker_status.do_update = false;
705 }
706
707 if (wm_job->ready) {
708 wm_job_end(wm, wm_job);
709
710 /* Free owned data. */
711 wm_job->run_free(wm_job->run_customdata);
712 wm_job->run_customdata = nullptr;
713 wm_job->run_free = nullptr;
714
715#if 0
716 if (wm_job->stop) {
717 printf("job ready but stopped %s\n", wm_job->name);
718 }
719 else {
720 printf("job finished %s\n", wm_job->name);
721 }
722#endif
723
724 if (G.debug & G_DEBUG_JOBS) {
725 printf("Job '%s' finished in %f seconds\n",
726 wm_job->name,
727 BLI_time_now_seconds() - wm_job->start_time);
728 }
729
730 wm_job->running = false;
731
733 BLI_threadpool_end(&wm_job->threads);
735
736 if (wm_job->endnote) {
737 WM_event_add_notifier_ex(wm, wm_job->win, wm_job->endnote, nullptr);
738 }
739
740 WM_event_add_notifier_ex(wm, wm_job->win, NC_WM | ND_JOB, nullptr);
741
742 /* New job added for wm_job? */
743 if (wm_job->customdata) {
744 // printf("job restarted with new data %s\n", wm_job->name);
745 WM_jobs_start(wm, wm_job);
746 }
747 else {
748 WM_event_timer_remove(wm, wm_job->win, wm_job->wt);
749 wm_job->wt = nullptr;
750
751 /* Remove wm_job. */
752 wm_job_free(wm, wm_job);
753 wm_job = nullptr;
754 }
755 }
756 }
757 else if (wm_job->suspended) {
758 WM_jobs_start(wm, wm_job);
759 }
760
761 /* Move pending reports generated by the worker thread to the WM main list. */
762 if (wm_job) {
763 wm_jobs_reports_update(wm, wm_job);
764 }
765 }
766
767 /* Update progress bars in windows. */
769}
770
772{
773 LISTBASE_FOREACH (const wmJob *, wm_job, &wm->runtime->jobs) {
774 if (wm_job->running) {
775 return true;
776 }
777 }
778
779 return false;
780}
781
782bool WM_jobs_has_running_type(const wmWindowManager *wm, int job_type)
783{
784 LISTBASE_FOREACH (wmJob *, wm_job, &wm->runtime->jobs) {
785 if (wm_job->running && wm_job->job_type == job_type) {
786 return true;
787 }
788 }
789 return false;
790}
@ G_DEBUG_JOBS
@ RPT_PRINT
Definition BKE_report.hh:55
@ RPT_STORE
Definition BKE_report.hh:56
@ RPT_WARNING
Definition BKE_report.hh:38
void BKE_reports_free(ReportList *reports)
Definition report.cc:97
void BKE_report_print_level_set(ReportList *reports, eReportType level)
Definition report.cc:265
void BKE_reports_init(ReportList *reports, int flag)
Definition report.cc:82
#define BLI_assert(a)
Definition BLI_assert.h:46
#define BLI_assert_msg(a, msg)
Definition BLI_assert.h:53
void BLI_kdtree_nd_ free(KDTree *tree)
#define LISTBASE_FOREACH(type, var, list)
BLI_INLINE bool BLI_listbase_is_empty(const ListBase *lb)
#define LISTBASE_FOREACH_MUTABLE(type, var, list)
void BLI_addtail(ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:111
void BLI_remlink(ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:131
void * BLI_findptr(const struct ListBase *listbase, const void *ptr, int offset) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
char * STRNCPY(char(&dst)[N], const char *src)
Definition BLI_string.h:693
unsigned int uint
TicketMutex * BLI_ticket_mutex_alloc(void)
Definition threads.cc:510
void BLI_ticket_mutex_unlock(TicketMutex *ticket)
Definition threads.cc:562
void BLI_threadpool_init(struct ListBase *threadbase, void *(*do_thread)(void *), int tot)
Definition threads.cc:121
void BLI_threadpool_end(struct ListBase *threadbase)
Definition threads.cc:234
void BLI_ticket_mutex_lock(TicketMutex *ticket)
Definition threads.cc:552
void BLI_ticket_mutex_free(TicketMutex *ticket)
Definition threads.cc:520
int BLI_thread_is_main(void)
Definition threads.cc:179
void BLI_threadpool_insert(struct ListBase *threadbase, void *callerdata)
Definition threads.cc:184
Platform independent time functions.
double BLI_time_now_seconds(void)
Definition time.cc:113
#define UNUSED_VARS(...)
#define ELEM(...)
Compatibility-like things for windows.
void BLI_windows_process_set_qos(QoSMode qos_mode, QoSPrecedence qos_precedence)
Read Guarded memory(de)allocation.
eWM_JobType
Definition WM_api.hh:1773
@ WM_JOB_TYPE_ANY
Definition WM_api.hh:1775
void(*)(void *custom_data, wmJobWorkerStatus *worker_status) wm_jobs_start_callback
Definition WM_api.hh:1848
eWM_JobFlag
Definition WM_api.hh:1759
@ WM_JOB_EXCL_RENDER
Definition WM_api.hh:1765
@ WM_JOB_PROGRESS
Definition WM_api.hh:1766
@ WM_JOB_PRIORITY
Definition WM_api.hh:1760
#define ND_JOB
Definition WM_types.hh:416
#define NC_WM
Definition WM_types.hh:374
#define offsetof(t, d)
#define printf(...)
void * MEM_callocN(size_t len, const char *str)
Definition mallocn.cc:118
void MEM_freeN(void *vmemh)
Definition mallocn.cc:113
#define G(x, y, z)
void prefetch_stop_all()
Definition prefetch.cc:300
static void update(bNodeTree *ntree)
const char * name
void * first
ListBase list
Definition BKE_report.hh:75
ReportList * reports
Definition WM_types.hh:1028
double time_step
Definition wm_jobs.cc:108
wm_jobs_start_callback startjob
Definition wm_jobs.cc:80
bool ready
Definition wm_jobs.cc:118
void(* update)(void *)
Definition wm_jobs.cc:85
void(* initjob)(void *)
Definition wm_jobs.cc:75
void(* completed)(void *)
Definition wm_jobs.cc:100
bool running
Definition wm_jobs.cc:118
void(* run_free)(void *)
Definition wm_jobs.cc:129
void * run_customdata
Definition wm_jobs.cc:128
uint endnote
Definition wm_jobs.cc:113
eWM_JobFlag flag
Definition wm_jobs.cc:117
wmJob * next
Definition wm_jobs.cc:64
void(* canceled)(void *)
Definition wm_jobs.cc:105
TicketMutex * main_thread_mutex
Definition wm_jobs.cc:140
void * customdata
Definition wm_jobs.cc:70
void(* free)(void *)
Definition wm_jobs.cc:90
bool suspended
Definition wm_jobs.cc:118
const void * owner
Definition wm_jobs.cc:116
ListBase threads
Definition wm_jobs.cc:132
eWM_JobType job_type
Definition wm_jobs.cc:119
char name[128]
Definition wm_jobs.cc:125
uint note
Definition wm_jobs.cc:113
wmJobWorkerStatus worker_status
Definition wm_jobs.cc:122
double start_time
Definition wm_jobs.cc:134
wmJob * prev
Definition wm_jobs.cc:64
double start_delay_time
Definition wm_jobs.cc:111
wmTimer * wt
Definition wm_jobs.cc:109
void(* endjob)(void *)
Definition wm_jobs.cc:95
wmWindow * win
Definition wm_jobs.cc:67
double time_step
Definition WM_types.hh:959
WindowManagerRuntimeHandle * runtime
void WM_event_add_notifier_ex(wmWindowManager *wm, const wmWindow *win, uint type, void *reference)
void WM_reports_from_reports_move(wmWindowManager *wm, ReportList *reports)
@ TIMERJOBS
static void wm_jobs_reports_update(wmWindowManager *wm, wmJob *wm_job)
Definition wm_jobs.cc:413
bool WM_jobs_has_running_type(const wmWindowManager *wm, int job_type)
Definition wm_jobs.cc:782
static void wm_job_free(wmWindowManager *wm, wmJob *wm_job)
Definition wm_jobs.cc:554
void WM_jobs_kill_all_from_owner(wmWindowManager *wm, const void *owner)
Definition wm_jobs.cc:638
bool WM_jobs_is_running(const wmJob *wm_job)
Definition wm_jobs.cc:341
static void wm_job_main_thread_yield(wmJob *wm_job)
Definition wm_jobs.cc:155
void WM_jobs_stop_type(wmWindowManager *wm, const void *owner, eWM_JobType job_type)
Definition wm_jobs.cc:647
void WM_jobs_timer(wmJob *wm_job, double time_step, uint note, uint endnote)
Definition wm_jobs.cc:376
void WM_jobs_stop_all_from_owner(wmWindowManager *wm, const void *owner)
Definition wm_jobs.cc:663
void WM_jobs_start(wmWindowManager *wm, wmJob *wm_job)
Definition wm_jobs.cc:479
const char * WM_jobs_name(const wmWindowManager *wm, const void *owner)
Definition wm_jobs.cc:319
static void wm_jobs_kill_job(wmWindowManager *wm, wmJob *wm_job)
Definition wm_jobs.cc:569
void wm_jobs_timer_end(wmWindowManager *wm, wmTimer *wt)
Definition wm_jobs.cc:674
static void wm_jobs_update_qos(const wmWindowManager *wm)
Definition wm_jobs.cc:163
void WM_jobs_kill_type(wmWindowManager *wm, const void *owner, int job_type)
Definition wm_jobs.cc:623
bool WM_jobs_has_running(const wmWindowManager *wm)
Definition wm_jobs.cc:771
bool WM_jobs_is_stopped(const wmWindowManager *wm, const void *owner)
Definition wm_jobs.cc:346
static void wm_jobs_test_suspend_stop(wmWindowManager *wm, wmJob *test)
Definition wm_jobs.cc:429
void * WM_jobs_customdata_get(wmJob *wm_job)
Definition wm_jobs.cc:352
void WM_jobs_kill_all(wmWindowManager *wm)
Definition wm_jobs.cc:602
void WM_jobs_delay_start(wmJob *wm_job, double delay_time)
Definition wm_jobs.cc:383
float WM_jobs_progress(const wmWindowManager *wm, const void *owner)
Definition wm_jobs.cc:267
static void wm_job_end(wmWindowManager *wm, wmJob *wm_job)
Definition wm_jobs.cc:533
wmJob * WM_jobs_get(wmWindowManager *wm, wmWindow *win, const void *owner, const char *name, const eWM_JobFlag flag, const eWM_JobType job_type)
Definition wm_jobs.cc:211
static void wm_jobs_update_progress_bars(wmWindowManager *wm)
Definition wm_jobs.cc:278
double WM_jobs_starttime(const wmWindowManager *wm, const void *owner)
Definition wm_jobs.cc:308
void WM_jobs_callbacks(wmJob *wm_job, wm_jobs_start_callback startjob, void(*initjob)(void *), void(*update)(void *), void(*endjob)(void *))
Definition wm_jobs.cc:388
void wm_jobs_timer(wmWindowManager *wm, wmTimer *wt)
Definition wm_jobs.cc:682
void WM_jobs_callbacks_ex(wmJob *wm_job, wm_jobs_start_callback startjob, void(*initjob)(void *), void(*update)(void *), void(*endjob)(void *), void(*completed)(void *), void(*canceled)(void *))
Definition wm_jobs.cc:397
void WM_jobs_kill_all_except(wmWindowManager *wm, const void *owner)
Definition wm_jobs.cc:614
bool WM_jobs_test(const wmWindowManager *wm, const void *owner, int job_type)
Definition wm_jobs.cc:247
void WM_job_main_thread_lock_acquire(wmJob *wm_job)
Definition wm_jobs.cc:145
void WM_jobs_customdata_set(wmJob *wm_job, void *customdata, void(*free)(void *customdata))
Definition wm_jobs.cc:360
void WM_job_main_thread_lock_release(wmJob *wm_job)
Definition wm_jobs.cc:150
static wmJob * wm_job_find(const wmWindowManager *wm, const void *owner, const eWM_JobType job_type)
Definition wm_jobs.cc:182
static void * do_job_thread(void *job_v)
Definition wm_jobs.cc:418
void * WM_jobs_customdata_from_type(wmWindowManager *wm, const void *owner, int job_type)
Definition wm_jobs.cc:330
wmTimer * WM_event_timer_add(wmWindowManager *wm, wmWindow *win, const wmEventType event_type, const double time_step)
void WM_progress_clear(wmWindow *win)
void WM_progress_set(wmWindow *win, float progress)
void WM_event_timer_remove(wmWindowManager *wm, wmWindow *, wmTimer *timer)
uint8_t flag
Definition wm_window.cc:145