From 80c7cdbdd2fbf3e0ad0afe098fd7b4fed4f0e88f Mon Sep 17 00:00:00 2001 From: Patrick Pelissier Date: Sat, 17 Feb 2018 12:00:45 +0100 Subject: [PATCH] Rename snapshot_def as snapshot_srsw_def --- README.md | 2 +- m-snapshot.h | 133 ++++++++++++++++++++++++++------------------------- 2 files changed, 69 insertions(+), 66 deletions(-) diff --git a/README.md b/README.md index be08b185..eaa85ba7 100644 --- a/README.md +++ b/README.md @@ -2075,7 +2075,7 @@ using atomic_load and atomic_store is a much more efficient and simple way to do even in the case of MRMW. -#### SNAPSHOT\_DEF(name, type[, oplist]) +#### SNAPSHOT\_SRSW\_DEF(name, type[, oplist]) Define the snapshot 'name##\_t' and its associated methods as "static inline" functions. Only a single reader thread and a single writer thread are supported. diff --git a/m-snapshot.h b/m-snapshot.h index f19b7ee0..46839f01 100644 --- a/m-snapshot.h +++ b/m-snapshot.h @@ -28,10 +28,13 @@ #include "m-atomic.h" #include "m-core.h" +// For compatibility with previous version +#define SNAPSHOT_DEF SNAPSHOT_SRSW_DEF + /* Define a snapshot and it function - USAGE: SNAPSHOT_DEF(name, type[, oplist]) */ -#define SNAPSHOT_DEF(name, ...) \ - SNAPSHOTI_DEF(M_IF_NARGS_EQ1(__VA_ARGS__) \ + USAGE: SNAPSHOT_SRSW_DEF(name, type[, oplist]) */ +#define SNAPSHOT_SRSW_DEF(name, ...) \ + SNAPSHOTI_SRSW_DEF(M_IF_NARGS_EQ1(__VA_ARGS__) \ ((name, __VA_ARGS__, M_GLOBAL_OPLIST_OR_DEF(__VA_ARGS__) ), \ (name, __VA_ARGS__ ))) @@ -67,38 +70,38 @@ * - f: Next index of the write buffer when a shot is taken Range [0..2] * - b: Boolean indicating that the read buffer shall be updated */ -#define SNAPSHOTI_FLAG(r, w, f, b) \ +#define SNAPSHOTI_SRSW_FLAG(r, w, f, b) \ ((unsigned char)( ( (r) << 4) | ((w) << 2) | ((f)) | ((b) << 6))) -#define SNAPSHOTI_R(flags) \ +#define SNAPSHOTI_SRSW_R(flags) \ (((flags) >> 4) & 0x03u) -#define SNAPSHOTI_W(flags) \ +#define SNAPSHOTI_SRSW_W(flags) \ (((flags) >> 2) & 0x03u) -#define SNAPSHOTI_F(flags) \ +#define SNAPSHOTI_SRSW_F(flags) \ (((flags) >> 0) & 0x03u) -#define SNAPSHOTI_B(flags) \ +#define SNAPSHOTI_SRSW_B(flags) \ (((flags) >> 6) & 0x01u) /* NOTE: Due to atomic_load only accepting non-const pointer, we can't have any const in the interface. */ -#define SNAPSHOTI_FLAGS_CONTRACT(flags) \ - assert(SNAPSHOTI_R(flags) != SNAPSHOTI_W(flags) \ - && SNAPSHOTI_R(flags) != SNAPSHOTI_F(flags) \ - && SNAPSHOTI_W(flags) != SNAPSHOTI_F(flags)) -#define SNAPSHOTI_CONTRACT(snap) do { \ +#define SNAPSHOTI_SRSW_FLAGS_CONTRACT(flags) \ + assert(SNAPSHOTI_SRSW_R(flags) != SNAPSHOTI_SRSW_W(flags) \ + && SNAPSHOTI_SRSW_R(flags) != SNAPSHOTI_SRSW_F(flags) \ + && SNAPSHOTI_SRSW_W(flags) != SNAPSHOTI_SRSW_F(flags)) +#define SNAPSHOTI_SRSW_CONTRACT(snap) do { \ assert((snap) != NULL); \ unsigned char f = atomic_load (&(snap)->flags); \ - SNAPSHOTI_FLAGS_CONTRACT(f); \ + SNAPSHOTI_SRSW_FLAGS_CONTRACT(f); \ } while (0) // Defered evaluation (TBC if it really helps). -#define SNAPSHOTI_DEF(arg) SNAPSHOTI_DEF2 arg +#define SNAPSHOTI_SRSW_DEF(arg) SNAPSHOTI_SRSW_DEF2 arg // This is basically an atomic triple buffer (Lock Free) // between a produced thread and a consummer thread. -#define SNAPSHOTI_MAX_BUFFER 3 +#define SNAPSHOTI_SRSW_MAX_BUFFER 3 -#define SNAPSHOTI_DEF2(name, type, oplist) \ - \ +#define SNAPSHOTI_SRSW_DEF2(name, type, oplist) \ + \ /* Create an aligned type to avoid false sharing between threads */ \ typedef struct M_C(name, _aligned_type_s) { \ type x; \ @@ -106,7 +109,7 @@ } M_C(name, _aligned_type_t); \ \ typedef struct M_C(name, _s) { \ - M_C(name, _aligned_type_t) data[SNAPSHOTI_MAX_BUFFER]; \ + M_C(name, _aligned_type_t) data[SNAPSHOTI_SRSW_MAX_BUFFER]; \ atomic_uchar flags; \ } M_C(name, _t)[1]; \ \ @@ -115,17 +118,17 @@ static inline void M_C(name, _init)(M_C(name, _t) snap) \ { \ assert(snap != NULL); \ - for(int i = 0; i < SNAPSHOTI_MAX_BUFFER; i++) { \ + for(int i = 0; i < SNAPSHOTI_SRSW_MAX_BUFFER; i++) { \ M_GET_INIT oplist(snap->data[i].x); \ } \ - atomic_init (&snap->flags, SNAPSHOTI_FLAG(0, 1, 2, 0)); \ - SNAPSHOTI_CONTRACT(snap); \ + atomic_init (&snap->flags, SNAPSHOTI_SRSW_FLAG(0, 1, 2, 0)); \ + SNAPSHOTI_SRSW_CONTRACT(snap); \ } \ - \ + \ static inline void M_C(name, _clear)(M_C(name, _t) snap) \ { \ - SNAPSHOTI_CONTRACT(snap); \ - for(int i = 0; i < SNAPSHOTI_MAX_BUFFER; i++) { \ + SNAPSHOTI_SRSW_CONTRACT(snap); \ + for(int i = 0; i < SNAPSHOTI_SRSW_MAX_BUFFER; i++) { \ M_GET_CLEAR oplist(snap->data[i].x); \ } \ } \ @@ -133,119 +136,119 @@ static inline void M_C(name, _init_set)(M_C(name, _t) snap, \ M_C(name, _t) org) \ { \ - SNAPSHOTI_CONTRACT(org); \ + SNAPSHOTI_SRSW_CONTRACT(org); \ assert(snap != NULL && snap != org); \ - for(int i = 0; i < SNAPSHOTI_MAX_BUFFER; i++) { \ + for(int i = 0; i < SNAPSHOTI_SRSW_MAX_BUFFER; i++) { \ M_GET_INIT_SET oplist(snap->data[i].x, org->data[i].x); \ } \ atomic_init (&snap->flags, atomic_load(&org->flags)); \ - SNAPSHOTI_CONTRACT(snap); \ + SNAPSHOTI_SRSW_CONTRACT(snap); \ } \ - \ + \ static inline void M_C(name, _set)(M_C(name, _t) snap, \ M_C(name, _t) org) \ { \ - SNAPSHOTI_CONTRACT(snap); \ - SNAPSHOTI_CONTRACT(org); \ - for(int i = 0; i < SNAPSHOTI_MAX_BUFFER; i++) { \ + SNAPSHOTI_SRSW_CONTRACT(snap); \ + SNAPSHOTI_SRSW_CONTRACT(org); \ + for(int i = 0; i < SNAPSHOTI_SRSW_MAX_BUFFER; i++) { \ M_GET_SET oplist(snap->data[i].x, org->data[i].x); \ } \ atomic_init (&snap->flags, atomic_load(&org->flags)); \ - SNAPSHOTI_CONTRACT(snap); \ + SNAPSHOTI_SRSW_CONTRACT(snap); \ } \ - \ + \ M_IF_METHOD(INIT_MOVE, oplist)( \ static inline void M_C(name, _init_move)(M_C(name, _t) snap, \ M_C(name, _t) org) \ { \ - SNAPSHOTI_CONTRACT(org); \ + SNAPSHOTI_SRSW_CONTRACT(org); \ assert(snap != NULL && snap != org); \ - for(int i = 0; i < SNAPSHOTI_MAX_BUFFER; i++) { \ + for(int i = 0; i < SNAPSHOTI_SRSW_MAX_BUFFER; i++) { \ M_GET_INIT_MOVE oplist(snap->data[i].x, org->data[i].x); \ } \ atomic_store (&snap->flags, atomic_load(&org->flags)); \ - atomic_store (&org->flags, SNAPSHOTI_FLAG(0,0,0,0) ); \ - SNAPSHOTI_CONTRACT(snap); \ + atomic_store (&org->flags, SNAPSHOTI_SRSW_FLAG(0,0,0,0) ); \ + SNAPSHOTI_SRSW_CONTRACT(snap); \ } \ ,) /* IF_METHOD (INIT_MOVE) */ \ - \ + \ M_IF_METHOD(MOVE, oplist)( \ static inline void M_C(name, _move)(M_C(name, _t) snap, \ M_C(name, _t) org) \ { \ - SNAPSHOTI_CONTRACT(snap); \ - SNAPSHOTI_CONTRACT(org); \ + SNAPSHOTI_SRSW_CONTRACT(snap); \ + SNAPSHOTI_SRSW_CONTRACT(org); \ assert(snap != org); \ - for(int i = 0; i < SNAPSHOTI_MAX_BUFFER; i++) { \ + for(int i = 0; i < SNAPSHOTI_SRSW_MAX_BUFFER; i++) { \ M_GET_MOVE oplist(snap->data[i].x, org->data[i].x); \ } \ atomic_store (&snap->flags, atomic_load(&org->flags)); \ - atomic_store (&org->flags, SNAPSHOTI_FLAG(0,0,0,0) ); \ - SNAPSHOTI_CONTRACT(snap); \ + atomic_store (&org->flags, SNAPSHOTI_SRSW_FLAG(0,0,0,0) ); \ + SNAPSHOTI_SRSW_CONTRACT(snap); \ } \ ,) /* IF_METHOD (MOVE) */ \ - \ + \ \ static inline type *M_C(name, _write)(M_C(name, _t) snap) \ { \ - SNAPSHOTI_CONTRACT(snap); \ + SNAPSHOTI_SRSW_CONTRACT(snap); \ unsigned char nextFlags, origFlags = atomic_load (&snap->flags); \ /* Atomic CAS operation */ \ do { \ /* Swap F and W buffer, setting exchange flag */ \ - nextFlags = SNAPSHOTI_FLAG(SNAPSHOTI_R(origFlags), \ - SNAPSHOTI_F(origFlags), \ - SNAPSHOTI_W(origFlags), 1); \ + nextFlags = SNAPSHOTI_SRSW_FLAG(SNAPSHOTI_SRSW_R(origFlags), \ + SNAPSHOTI_SRSW_F(origFlags), \ + SNAPSHOTI_SRSW_W(origFlags), 1); \ /* exponential backoff is not needed as there can't be more \ than 2 threads which try to update the data. */ \ } while (!atomic_compare_exchange_weak (&snap->flags, &origFlags, \ nextFlags)); \ /* Return new write buffer for new updating */ \ - return &snap->data[SNAPSHOTI_W(nextFlags)].x; \ + return &snap->data[SNAPSHOTI_SRSW_W(nextFlags)].x; \ } \ - \ + \ static inline const type *M_C(name, _read)(M_C(name, _t) snap) \ { \ - SNAPSHOTI_CONTRACT(snap); \ + SNAPSHOTI_SRSW_CONTRACT(snap); \ unsigned char nextFlags, origFlags = atomic_load (&snap->flags); \ /* Atomic CAS operation */ \ do { \ /* If no exchange registered, do nothing and keep the same */ \ - if (!SNAPSHOTI_B(origFlags)) { \ + if (!SNAPSHOTI_SRSW_B(origFlags)) { \ nextFlags = origFlags; \ break; \ } \ /* Swap R and F buffer, clearing exchange flag */ \ - nextFlags = SNAPSHOTI_FLAG(SNAPSHOTI_F(origFlags), \ - SNAPSHOTI_W(origFlags), \ - SNAPSHOTI_R(origFlags), 0); \ + nextFlags = SNAPSHOTI_SRSW_FLAG(SNAPSHOTI_SRSW_F(origFlags), \ + SNAPSHOTI_SRSW_W(origFlags), \ + SNAPSHOTI_SRSW_R(origFlags), 0); \ /* exponential backoff is not needed as there can't be more \ than 2 threads which try to update the data. */ \ } while (!atomic_compare_exchange_weak (&snap->flags, &origFlags, \ nextFlags)); \ /* Return current read buffer */ \ - return M_CONST_CAST(type, &snap->data[SNAPSHOTI_R(nextFlags)].x); \ + return M_CONST_CAST(type, &snap->data[SNAPSHOTI_SRSW_R(nextFlags)].x); \ } \ - \ + \ static inline bool M_C(name, _updated_p)(M_C(name, _t) snap) \ { \ - SNAPSHOTI_CONTRACT(snap); \ + SNAPSHOTI_SRSW_CONTRACT(snap); \ unsigned char flags = atomic_load (&snap->flags); \ - return SNAPSHOTI_B(flags); \ + return SNAPSHOTI_SRSW_B(flags); \ } \ \ static inline type *M_C(name, _get_write_buffer)(M_C(name, _t) snap) \ { \ - SNAPSHOTI_CONTRACT(snap); \ + SNAPSHOTI_SRSW_CONTRACT(snap); \ unsigned char flags = atomic_load(&snap->flags); \ - return &snap->data[SNAPSHOTI_W(flags)].x; \ + return &snap->data[SNAPSHOTI_SRSW_W(flags)].x; \ } \ - \ + \ static inline const type *M_C(name, _get_read_buffer)(M_C(name, _t) snap) \ { \ - SNAPSHOTI_CONTRACT(snap); \ + SNAPSHOTI_SRSW_CONTRACT(snap); \ unsigned char flags = atomic_load(&snap->flags); \ - return M_CONST_CAST(type, &snap->data[SNAPSHOTI_R(flags)].x); \ + return M_CONST_CAST(type, &snap->data[SNAPSHOTI_SRSW_R(flags)].x); \ } \ // FIXME: Method SWAP ?