libclod
C library for interacting with NBTs, region files, LOD data and other things.
Loading...
Searching...
No Matches
atomic.h
1#ifndef LIBCLOD_ATOMIC_H
2#define LIBCLOD_ATOMIC_H
3
4#if defined(__GNUC__)
5
6#include "endian_big.h"
7#include <assert.h>
8#include <stdint.h>
9
10static_assert(__GCC_ATOMIC_INT_LOCK_FREE == 2, "Locking alternatives are not portable across languages.");
11
12static inline uint32_t atomic_beu32_load(const uint8_t *ptr) {
13 assert((uintptr_t)ptr % 4 == 0);
14 uint32_t val = __atomic_load_n((uint32_t*)ptr, __ATOMIC_SEQ_CST);
15 return beu32_dec((uint8_t*)&val);
16}
17
18static inline void atomic_beu32_store(uint8_t *ptr, uint32_t val) {
19 assert((uintptr_t)ptr % 4 == 0);
20 uint32_t be;
21 beu32_enc((uint8_t*)&be, val);
22 __atomic_store_n((uint32_t*)ptr, be, __ATOMIC_SEQ_CST);
23}
24
25static inline bool atomic_beu32_cas(uint8_t *ptr, uint32_t *expected, uint32_t desired) {
26 assert((uintptr_t)ptr % 4 == 0);
27 uint32_t expected_be, desired_be;
28 beu32_enc((uint8_t*)&expected_be, *expected);
29 beu32_enc((uint8_t*)&desired_be, desired);
30 const bool success = __atomic_compare_exchange_n((uint32_t*)ptr, &expected_be, desired_be, false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST);
31 if (!success) {
32 *expected = beu32_dec((uint8_t*)&expected_be);
33 }
34 return success;
35}
36
37static inline uint32_t atomic_beu32_add(uint8_t *ptr, uint32_t delta) {
38 assert((uintptr_t)ptr % 4 == 0);
39 uint32_t val = atomic_beu32_load(ptr);
40 while (!atomic_beu32_cas(ptr, &val, val + delta)) {}
41 return val;
42}
43
44static inline uint32_t atomic_beu32_sub(uint8_t *ptr, uint32_t delta) {
45 assert((uintptr_t)ptr % 4 == 0);
46 uint32_t val = atomic_beu32_load(ptr);
47 while (!atomic_beu32_cas(ptr, &val, val - delta)) {}
48 return val;
49}
50
51#else
52#error "Atomic methods not implemented for this compiler"
53#endif
54
55#endif