summaryrefslogtreecommitdiffstats
path: root/misc/thread_tools.h
blob: a734ac85b04e704ea3039d823a7d900dc749983a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
#pragma once

#include <stdint.h>
#include <stdbool.h>
#include <pthread.h>

// This is basically a single-shot semaphore, intended as light-weight solution
// for just making a thread wait for another thread.
struct mp_waiter {
    // All fields are considered private. Use MP_WAITER_INITIALIZER to init.
    pthread_mutex_t lock;
    pthread_cond_t wakeup;
    bool done;
    uintptr_t value;
};

// Initialize a mp_waiter object for use with mp_waiter_*().
#define MP_WAITER_INITIALIZER { \
    .lock = PTHREAD_MUTEX_INITIALIZER, \
    .wakeup = PTHREAD_COND_INITIALIZER, \
    }

// Block until some other thread calls mp_waiter_wakeup(). The function returns
// the value argument of that wakeup call. After this, the waiter object must
// not be used anymore. Although you can reinit it with MP_WAITER_INITIALIZER
// (then you must make sure nothing calls mp_waiter_wakeup() before this).
uintptr_t mp_waiter_wait(struct mp_waiter *waiter);

// Unblock the thread waiting with mp_waiter_wait(), and make it return the
// provided value. If the other thread did not enter that call yet, it will
// return immediately once it does (mp_waiter_wakeup() always returns
// immediately). Calling this more than once is not allowed.
void mp_waiter_wakeup(struct mp_waiter *waiter, uintptr_t value);

// Query whether the waiter was woken up. If true, mp_waiter_wait() will return
// immediately. This is useful if you want to use another way to block and
// wakeup (in parallel to mp_waiter).
// You still need to call mp_waiter_wait() to free resources.
bool mp_waiter_poll(struct mp_waiter *waiter);

// Basically a binary semaphore that supports signaling the semaphore value to
// a bunch of other complicated mechanisms (such as wakeup pipes). It was made
// for aborting I/O and thus has according naming.
struct mp_cancel;

struct mp_cancel *mp_cancel_new(void *talloc_ctx);

// Request abort.
void mp_cancel_trigger(struct mp_cancel *c);

// Return whether the caller should abort.
// For convenience, c==NULL is allowed.
bool mp_cancel_test(struct mp_cancel *c);

// Wait until the even is signaled. If the timeout (in seconds) expires, return
// false. timeout==0 polls, timeout<0 waits forever.
bool mp_cancel_wait(struct mp_cancel *c, double timeout);

// Restore original state. (Allows reusing a mp_cancel.)
void mp_cancel_reset(struct mp_cancel *c);

// win32 "Event" HANDLE that indicates the current mp_cancel state.
void *mp_cancel_get_event(struct mp_cancel *c);

// The FD becomes readable if mp_cancel_test() would return true.
// Don't actually read from it, just use it for poll().
int mp_cancel_get_fd(struct mp_cancel *c);