Skip to content

Instantly share code, notes, and snippets.

@imaami
Created April 8, 2023 12:45
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save imaami/49e1e41371c186e9faae62fdf80a98c9 to your computer and use it in GitHub Desktop.
Save imaami/49e1e41371c186e9faae62fdf80a98c9 to your computer and use it in GitHub Desktop.
Atomic transaction lock in C w/ compile-time magic
#include <stdatomic.h>
#include <stdbool.h>
#include <stdlib.h>
#define TRANSACTION(name, ptr, lock, expect, desire) \
struct { \
union { \
atomic_ulong *state; \
struct { \
char lock_bit[(lock)]; \
char expected[(expect)]; \
char desired[(desire)]; \
} *T; \
}; \
unsigned long actual; \
} name = { \
.state = (ptr), .actual = sizeof(name.T->expected) \
}; do { if (!atomic_compare_exchange_strong_explicit( \
name.state, &name.actual, sizeof(name.T->desired) \
| sizeof(name.T->lock_bit), memory_order_release, \
memory_order_acquire)) { name.state = NULL; }} while (0)
#define transaction_commit(name) \
do { \
name.actual = atomic_exchange_explicit(name.state, \
sizeof(name.T->desired), memory_order_release); \
name.state = NULL; \
} while (0)
#define transaction_revert(name) \
do { \
name.actual = atomic_exchange_explicit(name.state, \
sizeof(name.T->expected), memory_order_release); \
name.state = NULL; \
} while (0)
#define transaction_active(name) (!!name.state)
#define transaction_commit_ok(name) \
(name.actual == (sizeof(name.T->desired) | sizeof(name.T->lock_bit)))
enum {
STATE_WAIT = 2,
STATE_WORK = 3,
STATE_LOCK = 1 << 30
};
bool begin_work(atomic_ulong *state_flags, void (*prepare_work)(void))
{
TRANSACTION(xact, state_flags, STATE_LOCK, STATE_WAIT, STATE_WORK);
if (!transaction_active(xact))
return false;
prepare_work();
transaction_commit(xact);
return true;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment