...
This compliant solution protects all accesses of the flags with a mutex, thereby preventing any data races. Finally, the flags are embedded in a union alongside a long
, and a static assertion guarantees that the flags do not occupy more space than the long
. This technique prevents any data not checked by the mutex from being accessed or modified with the bit-fields on platforms that do not comply with C11 memory semantics.
Code Block | ||||
---|---|---|---|---|
| ||||
#include <threads.h> #include <assert.h> struct multi_threaded_flags { unsigned int flag1 : 2; unsigned int flag2 : 2; }; static_assert( sizeof(long) >= sizeof(struct multi_threaded_flags), "A long type will not hold the flags on this architecture." ); union mtf_protectmutex { struct multi_threaded_flags s; long padding; }; struct mtf_mutex { union mtf_protect u; mtx_t mutex; }; struct mtf_mutex flags; int thread1(void *arg) { if (thrd_success != mtx_lock(&flags.mutex)) { /* Handle error */ } flags.u.s.flag1 = 1; if (thrd_success != mtx_unlock(&flags.mutex)) { /* Handle error */ } return 0; } int thread2(void *arg) { if (thrd_success != mtx_lock(&flags.mutex)) { /* Handle error */ } flags.u.s.flag2 = 2; if (thrd_success != mtx_unlock(&flags.mutex)) { /* Handle error */ } return 0; } |
...