| 1 | /* |
| 2 | jobs.h: work for background threads (network calls, image decoding). |
| 3 |
|
| 4 | The main loop makes a job, posts it and checks job->done each frame. When it |
| 5 | no longer wants the result it calls job_release(); the job is freed once both |
| 6 | sides are finished with it. |
| 7 | */ |
| 8 | #ifndef JOBS_H |
| 9 | #define JOBS_H |
| 10 |
|
| 11 | enum { LANE_API, LANE_ART, LANE_DL, NUM_LANES }; // DL: downloads, one at a time |
| 12 |
|
| 13 | typedef struct job job_t; |
| 14 | struct job { |
| 15 | void (*run)(job_t *j); // on a worker thread |
| 16 | void (*cleanup)(job_t *j); // frees what run made (results), on whichever side frees it |
| 17 | volatile int done; |
| 18 | volatile int cancel; // a hint for run |
| 19 | volatile int refs; |
| 20 | job_t *next; |
| 21 | // what the job is about and what it found: for run and its poster |
| 22 | void *arg; |
| 23 | void *result; |
| 24 | int ok; |
| 25 | int ival; |
| 26 | long long lval; |
| 27 | char sval[512]; |
| 28 | char err[160]; |
| 29 | }; |
| 30 |
|
| 31 | // the poster's check: has run finished? An acquire load, so on the PPU (weakly |
| 32 | // ordered) everything run wrote is visible once this says yes |
| 33 | static inline int job_done(job_t *j) { return j && __atomic_load_n(&j->done, __ATOMIC_ACQUIRE); } |
| 34 |
|
| 35 | void jobs_init(void); |
| 36 | job_t *job_new(void (*run)(job_t *), void (*cleanup)(job_t *)); // main thread only |
| 37 | // LANE_ART runs newest first (the icons on screen now matter most) |
| 38 | void job_post(job_t *j, int lane); |
| 39 | void job_detach(job_t *j); // the poster is done and the job should still run |
| 40 | void job_release(job_t *j); // the poster is done with it |
| 41 | void jobs_cancel_lane(int lane); // drops what hasn't started |
| 42 | void jobs_wait_lane(int lane, unsigned max_us); // until it's empty, or max_us |
| 43 |
|
| 44 | #endif |