Rename snapshot_def as snapshot_srsw_def
This commit is contained in:
1 parent
9c7b453732
commit
80c7cdbdd2
2 files changed
+69
-66
No files matched your search
@@ -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.
|
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.
|
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.
|
Only a single reader thread and a single writer thread are supported.
|
||||||
|
|||||||
+68
-65
@@ -28,10 +28,13 @@
|
|||||||
#include "m-atomic.h"
|
#include "m-atomic.h"
|
||||||
#include "m-core.h"
|
#include "m-core.h"
|
||||||
|
|
||||||
|
// For compatibility with previous version
|
||||||
|
#define SNAPSHOT_DEF SNAPSHOT_SRSW_DEF
|
||||||
|
|
||||||
/* Define a snapshot and it function
|
/* Define a snapshot and it function
|
||||||
USAGE: SNAPSHOT_DEF(name, type[, oplist]) */
|
USAGE: SNAPSHOT_SRSW_DEF(name, type[, oplist]) */
|
||||||
#define SNAPSHOT_DEF(name, ...) \
|
#define SNAPSHOT_SRSW_DEF(name, ...) \
|
||||||
SNAPSHOTI_DEF(M_IF_NARGS_EQ1(__VA_ARGS__) \
|
SNAPSHOTI_SRSW_DEF(M_IF_NARGS_EQ1(__VA_ARGS__) \
|
||||||
((name, __VA_ARGS__, M_GLOBAL_OPLIST_OR_DEF(__VA_ARGS__) ), \
|
((name, __VA_ARGS__, M_GLOBAL_OPLIST_OR_DEF(__VA_ARGS__) ), \
|
||||||
(name, __VA_ARGS__ )))
|
(name, __VA_ARGS__ )))
|
||||||
|
|
||||||
@@ -67,38 +70,38 @@
|
|||||||
* - f: Next index of the write buffer when a shot is taken Range [0..2]
|
* - 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
|
* - 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)))
|
((unsigned char)( ( (r) << 4) | ((w) << 2) | ((f)) | ((b) << 6)))
|
||||||
#define SNAPSHOTI_R(flags) \
|
#define SNAPSHOTI_SRSW_R(flags) \
|
||||||
(((flags) >> 4) & 0x03u)
|
(((flags) >> 4) & 0x03u)
|
||||||
#define SNAPSHOTI_W(flags) \
|
#define SNAPSHOTI_SRSW_W(flags) \
|
||||||
(((flags) >> 2) & 0x03u)
|
(((flags) >> 2) & 0x03u)
|
||||||
#define SNAPSHOTI_F(flags) \
|
#define SNAPSHOTI_SRSW_F(flags) \
|
||||||
(((flags) >> 0) & 0x03u)
|
(((flags) >> 0) & 0x03u)
|
||||||
#define SNAPSHOTI_B(flags) \
|
#define SNAPSHOTI_SRSW_B(flags) \
|
||||||
(((flags) >> 6) & 0x01u)
|
(((flags) >> 6) & 0x01u)
|
||||||
|
|
||||||
/* NOTE: Due to atomic_load only accepting non-const pointer,
|
/* NOTE: Due to atomic_load only accepting non-const pointer,
|
||||||
we can't have any const in the interface. */
|
we can't have any const in the interface. */
|
||||||
#define SNAPSHOTI_FLAGS_CONTRACT(flags) \
|
#define SNAPSHOTI_SRSW_FLAGS_CONTRACT(flags) \
|
||||||
assert(SNAPSHOTI_R(flags) != SNAPSHOTI_W(flags) \
|
assert(SNAPSHOTI_SRSW_R(flags) != SNAPSHOTI_SRSW_W(flags) \
|
||||||
&& SNAPSHOTI_R(flags) != SNAPSHOTI_F(flags) \
|
&& SNAPSHOTI_SRSW_R(flags) != SNAPSHOTI_SRSW_F(flags) \
|
||||||
&& SNAPSHOTI_W(flags) != SNAPSHOTI_F(flags))
|
&& SNAPSHOTI_SRSW_W(flags) != SNAPSHOTI_SRSW_F(flags))
|
||||||
#define SNAPSHOTI_CONTRACT(snap) do { \
|
#define SNAPSHOTI_SRSW_CONTRACT(snap) do { \
|
||||||
assert((snap) != NULL); \
|
assert((snap) != NULL); \
|
||||||
unsigned char f = atomic_load (&(snap)->flags); \
|
unsigned char f = atomic_load (&(snap)->flags); \
|
||||||
SNAPSHOTI_FLAGS_CONTRACT(f); \
|
SNAPSHOTI_SRSW_FLAGS_CONTRACT(f); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
// Defered evaluation (TBC if it really helps).
|
// 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)
|
// This is basically an atomic triple buffer (Lock Free)
|
||||||
// between a produced thread and a consummer thread.
|
// 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 */ \
|
/* Create an aligned type to avoid false sharing between threads */ \
|
||||||
typedef struct M_C(name, _aligned_type_s) { \
|
typedef struct M_C(name, _aligned_type_s) { \
|
||||||
type x; \
|
type x; \
|
||||||
@@ -106,7 +109,7 @@
|
|||||||
} M_C(name, _aligned_type_t); \
|
} M_C(name, _aligned_type_t); \
|
||||||
\
|
\
|
||||||
typedef struct M_C(name, _s) { \
|
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; \
|
atomic_uchar flags; \
|
||||||
} M_C(name, _t)[1]; \
|
} M_C(name, _t)[1]; \
|
||||||
\
|
\
|
||||||
@@ -115,17 +118,17 @@
|
|||||||
static inline void M_C(name, _init)(M_C(name, _t) snap) \
|
static inline void M_C(name, _init)(M_C(name, _t) snap) \
|
||||||
{ \
|
{ \
|
||||||
assert(snap != NULL); \
|
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); \
|
M_GET_INIT oplist(snap->data[i].x); \
|
||||||
} \
|
} \
|
||||||
atomic_init (&snap->flags, SNAPSHOTI_FLAG(0, 1, 2, 0)); \
|
atomic_init (&snap->flags, SNAPSHOTI_SRSW_FLAG(0, 1, 2, 0)); \
|
||||||
SNAPSHOTI_CONTRACT(snap); \
|
SNAPSHOTI_SRSW_CONTRACT(snap); \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
static inline void M_C(name, _clear)(M_C(name, _t) snap) \
|
static inline void M_C(name, _clear)(M_C(name, _t) snap) \
|
||||||
{ \
|
{ \
|
||||||
SNAPSHOTI_CONTRACT(snap); \
|
SNAPSHOTI_SRSW_CONTRACT(snap); \
|
||||||
for(int i = 0; i < SNAPSHOTI_MAX_BUFFER; i++) { \
|
for(int i = 0; i < SNAPSHOTI_SRSW_MAX_BUFFER; i++) { \
|
||||||
M_GET_CLEAR oplist(snap->data[i].x); \
|
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, \
|
static inline void M_C(name, _init_set)(M_C(name, _t) snap, \
|
||||||
M_C(name, _t) org) \
|
M_C(name, _t) org) \
|
||||||
{ \
|
{ \
|
||||||
SNAPSHOTI_CONTRACT(org); \
|
SNAPSHOTI_SRSW_CONTRACT(org); \
|
||||||
assert(snap != NULL && snap != 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); \
|
M_GET_INIT_SET oplist(snap->data[i].x, org->data[i].x); \
|
||||||
} \
|
} \
|
||||||
atomic_init (&snap->flags, atomic_load(&org->flags)); \
|
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, \
|
static inline void M_C(name, _set)(M_C(name, _t) snap, \
|
||||||
M_C(name, _t) org) \
|
M_C(name, _t) org) \
|
||||||
{ \
|
{ \
|
||||||
SNAPSHOTI_CONTRACT(snap); \
|
SNAPSHOTI_SRSW_CONTRACT(snap); \
|
||||||
SNAPSHOTI_CONTRACT(org); \
|
SNAPSHOTI_SRSW_CONTRACT(org); \
|
||||||
for(int i = 0; i < SNAPSHOTI_MAX_BUFFER; i++) { \
|
for(int i = 0; i < SNAPSHOTI_SRSW_MAX_BUFFER; i++) { \
|
||||||
M_GET_SET oplist(snap->data[i].x, org->data[i].x); \
|
M_GET_SET oplist(snap->data[i].x, org->data[i].x); \
|
||||||
} \
|
} \
|
||||||
atomic_init (&snap->flags, atomic_load(&org->flags)); \
|
atomic_init (&snap->flags, atomic_load(&org->flags)); \
|
||||||
SNAPSHOTI_CONTRACT(snap); \
|
SNAPSHOTI_SRSW_CONTRACT(snap); \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
M_IF_METHOD(INIT_MOVE, oplist)( \
|
M_IF_METHOD(INIT_MOVE, oplist)( \
|
||||||
static inline void M_C(name, _init_move)(M_C(name, _t) snap, \
|
static inline void M_C(name, _init_move)(M_C(name, _t) snap, \
|
||||||
M_C(name, _t) org) \
|
M_C(name, _t) org) \
|
||||||
{ \
|
{ \
|
||||||
SNAPSHOTI_CONTRACT(org); \
|
SNAPSHOTI_SRSW_CONTRACT(org); \
|
||||||
assert(snap != NULL && snap != 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); \
|
M_GET_INIT_MOVE oplist(snap->data[i].x, org->data[i].x); \
|
||||||
} \
|
} \
|
||||||
atomic_store (&snap->flags, atomic_load(&org->flags)); \
|
atomic_store (&snap->flags, atomic_load(&org->flags)); \
|
||||||
atomic_store (&org->flags, SNAPSHOTI_FLAG(0,0,0,0) ); \
|
atomic_store (&org->flags, SNAPSHOTI_SRSW_FLAG(0,0,0,0) ); \
|
||||||
SNAPSHOTI_CONTRACT(snap); \
|
SNAPSHOTI_SRSW_CONTRACT(snap); \
|
||||||
} \
|
} \
|
||||||
,) /* IF_METHOD (INIT_MOVE) */ \
|
,) /* IF_METHOD (INIT_MOVE) */ \
|
||||||
\
|
\
|
||||||
M_IF_METHOD(MOVE, oplist)( \
|
M_IF_METHOD(MOVE, oplist)( \
|
||||||
static inline void M_C(name, _move)(M_C(name, _t) snap, \
|
static inline void M_C(name, _move)(M_C(name, _t) snap, \
|
||||||
M_C(name, _t) org) \
|
M_C(name, _t) org) \
|
||||||
{ \
|
{ \
|
||||||
SNAPSHOTI_CONTRACT(snap); \
|
SNAPSHOTI_SRSW_CONTRACT(snap); \
|
||||||
SNAPSHOTI_CONTRACT(org); \
|
SNAPSHOTI_SRSW_CONTRACT(org); \
|
||||||
assert(snap != 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); \
|
M_GET_MOVE oplist(snap->data[i].x, org->data[i].x); \
|
||||||
} \
|
} \
|
||||||
atomic_store (&snap->flags, atomic_load(&org->flags)); \
|
atomic_store (&snap->flags, atomic_load(&org->flags)); \
|
||||||
atomic_store (&org->flags, SNAPSHOTI_FLAG(0,0,0,0) ); \
|
atomic_store (&org->flags, SNAPSHOTI_SRSW_FLAG(0,0,0,0) ); \
|
||||||
SNAPSHOTI_CONTRACT(snap); \
|
SNAPSHOTI_SRSW_CONTRACT(snap); \
|
||||||
} \
|
} \
|
||||||
,) /* IF_METHOD (MOVE) */ \
|
,) /* IF_METHOD (MOVE) */ \
|
||||||
\
|
\
|
||||||
\
|
\
|
||||||
static inline type *M_C(name, _write)(M_C(name, _t) snap) \
|
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); \
|
unsigned char nextFlags, origFlags = atomic_load (&snap->flags); \
|
||||||
/* Atomic CAS operation */ \
|
/* Atomic CAS operation */ \
|
||||||
do { \
|
do { \
|
||||||
/* Swap F and W buffer, setting exchange flag */ \
|
/* Swap F and W buffer, setting exchange flag */ \
|
||||||
nextFlags = SNAPSHOTI_FLAG(SNAPSHOTI_R(origFlags), \
|
nextFlags = SNAPSHOTI_SRSW_FLAG(SNAPSHOTI_SRSW_R(origFlags), \
|
||||||
SNAPSHOTI_F(origFlags), \
|
SNAPSHOTI_SRSW_F(origFlags), \
|
||||||
SNAPSHOTI_W(origFlags), 1); \
|
SNAPSHOTI_SRSW_W(origFlags), 1); \
|
||||||
/* exponential backoff is not needed as there can't be more \
|
/* exponential backoff is not needed as there can't be more \
|
||||||
than 2 threads which try to update the data. */ \
|
than 2 threads which try to update the data. */ \
|
||||||
} while (!atomic_compare_exchange_weak (&snap->flags, &origFlags, \
|
} while (!atomic_compare_exchange_weak (&snap->flags, &origFlags, \
|
||||||
nextFlags)); \
|
nextFlags)); \
|
||||||
/* Return new write buffer for new updating */ \
|
/* 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) \
|
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); \
|
unsigned char nextFlags, origFlags = atomic_load (&snap->flags); \
|
||||||
/* Atomic CAS operation */ \
|
/* Atomic CAS operation */ \
|
||||||
do { \
|
do { \
|
||||||
/* If no exchange registered, do nothing and keep the same */ \
|
/* If no exchange registered, do nothing and keep the same */ \
|
||||||
if (!SNAPSHOTI_B(origFlags)) { \
|
if (!SNAPSHOTI_SRSW_B(origFlags)) { \
|
||||||
nextFlags = origFlags; \
|
nextFlags = origFlags; \
|
||||||
break; \
|
break; \
|
||||||
} \
|
} \
|
||||||
/* Swap R and F buffer, clearing exchange flag */ \
|
/* Swap R and F buffer, clearing exchange flag */ \
|
||||||
nextFlags = SNAPSHOTI_FLAG(SNAPSHOTI_F(origFlags), \
|
nextFlags = SNAPSHOTI_SRSW_FLAG(SNAPSHOTI_SRSW_F(origFlags), \
|
||||||
SNAPSHOTI_W(origFlags), \
|
SNAPSHOTI_SRSW_W(origFlags), \
|
||||||
SNAPSHOTI_R(origFlags), 0); \
|
SNAPSHOTI_SRSW_R(origFlags), 0); \
|
||||||
/* exponential backoff is not needed as there can't be more \
|
/* exponential backoff is not needed as there can't be more \
|
||||||
than 2 threads which try to update the data. */ \
|
than 2 threads which try to update the data. */ \
|
||||||
} while (!atomic_compare_exchange_weak (&snap->flags, &origFlags, \
|
} while (!atomic_compare_exchange_weak (&snap->flags, &origFlags, \
|
||||||
nextFlags)); \
|
nextFlags)); \
|
||||||
/* Return current read buffer */ \
|
/* 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) \
|
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); \
|
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) \
|
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); \
|
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) \
|
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); \
|
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 ?
|
// FIXME: Method SWAP ?
|
||||||
|
|||||||
Reference in new issue
Block a user