#pragma once #include #ifdef __cplusplus struct __attribute__((__visibility__("default"))) ConflictSet { enum Result { /** The result of a check which does not intersect any conflicting writes */ Commit, /** The result of a check which intersects a write at a version > readVersion */ Conflict, /** The result of a check with a readVersion older than the highest call to `setOldestVersion` */ TooOld }; /** Bytes ordered lexicographically */ struct Key { const uint8_t *p; int len; }; /** Denotes a set of keys to be checked for conflicts */ struct ReadRange { Key begin; /** `end` having length 0 denotes that this range is the single key {begin}. * Otherwise this denotes the range [begin, end) */ Key end; int64_t readVersion; }; /** Denotes a set of keys to be considered written at `writeVersion` */ struct WriteRange { Key begin; /** `end` having length 0 denotes that this range is the single key {begin}. * Otherwise this denotes the range [begin, end) */ Key end; /** Write version must be greater than all write versions in all previous * calls to `addWrites` */ int64_t writeVersion; }; /** `reads` must be sorted ascending, and must not have adjacent or * overlapping ranges. The result of checking reads[i] is written in * results[i]. */ void check(const ReadRange *reads, Result *results, int count) const; /** `writes` must be sorted ascending, and must not have adjacent or * overlapping ranges. Reads intersecting writes where readVersion < * writeVersion will result in `Conflict` (or `TooOld`, eventually) */ void addWrites(const WriteRange *writes, int count); /** Reads where readVersion < oldestVersion will result in `TooOld`. Must be * greater than any previous oldestVersion. */ void setOldestVersion(int64_t oldestVersion); /** Reads where readVersion < oldestVersion will result in `TooOld`. There are * no writes initially. */ explicit ConflictSet(int64_t oldestVersion); ~ConflictSet(); #if __cplusplus > 199711L ConflictSet(ConflictSet &&) noexcept; ConflictSet &operator=(ConflictSet &&) noexcept; ConflictSet(const ConflictSet &) = delete; ConflictSet &operator=(const ConflictSet &) = delete; #endif /** @private */ struct Impl; private: Impl *impl; }; #else typedef struct ConflictSet ConflictSet; typedef enum { /** The result of a check which does not intersect any conflicting writes */ ConflictSet_Commit, /** The result of a check which intersects a write at a version > readVersion */ ConflictSet_Conflict, /** The result of a check with a readVersion older than the highest call to `setOldestVersion` */ ConflictSet_TooOld } ConflictSet_Result; /** Bytes ordered lexicographically */ typedef struct { const uint8_t *p; int len; } ConflictSet_Key; /** Denotes a set of keys to be checked for conflicts */ typedef struct { ConflictSet_Key begin; /** `end` having length 0 denotes that this range is the single key {begin}. * Otherwise this denotes the range [begin, end) */ ConflictSet_Key end; int64_t readVersion; } ConflictSet_ReadRange; /** Denotes a set of keys to be considered written at `writeVersion` */ typedef struct { ConflictSet_Key begin; /** `end` having length 0 denotes that this range is the single key {begin}. * Otherwise this denotes the range [begin, end) */ ConflictSet_Key end; /** Write version must be greater than all write versions in all previous * calls to `addWrites` */ int64_t writeVersion; } ConflictSet_WriteRange; /** `reads` must be sorted ascending, and must not have adjacent or overlapping * ranges. The result of checking reads[i] is written in results[i]. */ void ConflictSet_check(ConflictSet *cs, const ConflictSet_ReadRange *reads, ConflictSet_Result *results, int count); /** `writes` must be sorted ascending, and must not have adjacent or overlapping * ranges. Reads intersecting writes where readVersion < writeVersion will * result in `Conflict` (or `TooOld`, eventually) */ void ConflictSet_addWrites(ConflictSet *cs, const ConflictSet_WriteRange *writes, int count); /** Reads where readVersion < oldestVersion will result in `TooOld`. Must be * greater than any previous oldestVersion. */ void ConflictSet_setOldestVersion(ConflictSet *cs, int64_t oldestVersion); /** Reads where readVersion < oldestVersion will result in `TooOld`. There are * no writes initially. */ ConflictSet *ConflictSet_create(int64_t oldestVersion); void ConflictSet_destroy(ConflictSet *cs); #endif