Use doxygen pre/post tags and make public api more precise

This commit is contained in:
andrew committed 2026-10-09 15:09:58 -04:00
1 parent 6a6e36909f
commit 2f9f49c692
1 file changed
+71 -36
+71 -36
View File
@@ -21,7 +21,12 @@ limitations under the License.
#ifdef __cplusplus #ifdef __cplusplus
namespace weaselab { namespace weaselab {
/** A data structure for optimistic concurrency control on ranges of /** A data structure for optimistic concurrency control on ranges of
* bitwise-lexicographically-ordered keys. All versions must be >= 0. * bitwise-lexicographically-ordered keys.
*
* All versions are >= 0. `oldestVersion` is the smallest version a subsequent
* `check` can read and `newestVersion` is the largest version passed to
* `addWrites` or the constructor. `oldestVersion <= newestVersion`, and
* `oldestVersion >= newestVersion - two billion`.
* *
* Thread safety: * Thread safety:
* - It's safe to operate on two different ConflictSets in two different * - It's safe to operate on two different ConflictSets in two different
@@ -36,8 +41,7 @@ struct __attribute__((__visibility__("default"))) ConflictSet {
/** The result of a check which intersects a write at a version > /** The result of a check which intersects a write at a version >
readVersion */ readVersion */
Conflict, Conflict,
/** The result of a check with a readVersion older than the highest call to /** The result of a check with a readVersion older than `oldestVersion` */
`setOldestVersion` */
TooOld TooOld
}; };
@@ -54,9 +58,6 @@ struct __attribute__((__visibility__("default"))) ConflictSet {
/** `end` having length 0 denotes that this range is the single key {begin}. /** `end` having length 0 denotes that this range is the single key {begin}.
* Otherwise this denotes the range [begin, end), and begin must be < end */ * Otherwise this denotes the range [begin, end), and begin must be < end */
Key end; Key end;
/** `readVersion` older than the oldestVersion or the version of the
* latest call to `addWrites` minus two billion will result in `TooOld`.
* Must be <= the version of the latest call to `addWrites` */
int64_t readVersion; int64_t readVersion;
}; };
@@ -68,23 +69,39 @@ struct __attribute__((__visibility__("default"))) ConflictSet {
Key end; Key end;
}; };
/** The result of checking reads[i] is written in results[i] */ /** The result of checking reads[i] is written in results[i].
* @pre `reads` and `results` each hold at least `count` elements; each
* `reads[i]` is a valid `ReadRange` (see its field documentation); each
* `reads[i].readVersion <= newestVersion`.
* @post For every i < count, `results[i]` is `TooOld` if
* `reads[i].readVersion < oldestVersion`; `Conflict` if any write at a
* version greater than `reads[i].readVersion` intersects the range
* `reads[i]`; and `Commit` otherwise. */
void check(const ReadRange *reads, Result *results, int count) const; void check(const ReadRange *reads, Result *results, int count) const;
/** Reads intersecting writes where readVersion < `writeVersion` will result /** Records writes at `writeVersion`, making them visible to `check`.
* in `Conflict` (or `TooOld`, eventually). `writeVersion` must be greater * @pre `writes` holds at least `count` elements; every `writes[i]` is a valid
* than or equal to all previous write versions. Call `addWrites` with `count` * `WriteRange` (see its field documentation); `count >= 0`; `writeVersion >=
* zero to only advance the version. */ * newestVersion`.
* @post Writes (writes[i], writeVersion) are recorded for every i < count,
* and `newestVersion` becomes `writeVersion`. `oldestVersion` advances as
* needed so that `oldestVersion >= newestVersion - two billion`;
* `oldestVersion <= newestVersion` is preserved. Calling with `count == 0`
* adds no write; `newestVersion` (and possibly `oldestVersion`) still
* advance. */
void addWrites(const WriteRange *writes, int count, int64_t writeVersion); void addWrites(const WriteRange *writes, int count, int64_t writeVersion);
/** Reads where readVersion < `oldestVersion` will result in `TooOld`. Must be /** Reads where readVersion < `oldestVersion` will result in `TooOld`.
* greater than or equal to all previous oldest versions. Must be <= the * @pre `oldestVersion >= 0` and `oldestVersion <= newestVersion`.
* version of the latest call to `addWrites` */ * @post `oldestVersion` becomes the maximum of its previous value and the
* argument; `newestVersion` is unchanged. */
void setOldestVersion(int64_t oldestVersion); void setOldestVersion(int64_t oldestVersion);
/** Reads where readVersion < oldestVersion will result in `TooOld`. There are /** Reads where readVersion < `oldestVersion` will result in `TooOld`.
* no writes initially */ * @pre `version >= 0`.
explicit ConflictSet(int64_t oldestVersion); * @post No writes are recorded, and `oldestVersion == newestVersion ==
* version`. */
explicit ConflictSet(int64_t version);
~ConflictSet(); ~ConflictSet();
@@ -146,7 +163,12 @@ private:
#else #else
/** A data structure for optimistic concurrency control on ranges of /** A data structure for optimistic concurrency control on ranges of
* bitwise-lexicographically-ordered keys. All versions must be >= 0. * bitwise-lexicographically-ordered keys.
*
* All versions are >= 0. `oldestVersion` is the smallest version a subsequent
* `check` can read and `newestVersion` is the largest version passed to
* `addWrites` or the constructor. `oldestVersion <= newestVersion`, and
* `oldestVersion >= newestVersion - two billion`.
* *
* Thread safety: * Thread safety:
* - It's safe to operate on two different ConflictSets in two different * - It's safe to operate on two different ConflictSets in two different
@@ -160,11 +182,10 @@ typedef struct ConflictSet ConflictSet;
typedef enum { typedef enum {
/** The result of a check which does not intersect any conflicting writes */ /** The result of a check which does not intersect any conflicting writes */
ConflictSet_Commit, ConflictSet_Commit,
/** The result of a check which intersects a write at a version > readVersion /** The result of a check which intersects a write at a version >
*/ readVersion */
ConflictSet_Conflict, ConflictSet_Conflict,
/** The result of a check with a readVersion older than the highest call to /** The result of a check with a readVersion older than `oldestVersion` */
`setOldestVersion` */
ConflictSet_TooOld ConflictSet_TooOld
} ConflictSet_Result; } ConflictSet_Result;
@@ -181,9 +202,6 @@ typedef struct {
/** `end` having length 0 denotes that this range is the single key {begin}. /** `end` having length 0 denotes that this range is the single key {begin}.
* Otherwise this denotes the range [begin, end), and begin must be < end */ * Otherwise this denotes the range [begin, end), and begin must be < end */
ConflictSet_Key end; ConflictSet_Key end;
/** `readVersion` older than the oldestVersion or the version of the
* latest call to `addWrites` minus two billion will result in `TooOld`.
* Must be <= the version of the latest call to `addWrites` */
int64_t readVersion; int64_t readVersion;
} ConflictSet_ReadRange; } ConflictSet_ReadRange;
@@ -195,27 +213,44 @@ typedef struct {
ConflictSet_Key end; ConflictSet_Key end;
} ConflictSet_WriteRange; } ConflictSet_WriteRange;
/** The result of checking reads[i] is written in results[i] */ /** The result of checking reads[i] is written in results[i].
* @pre `reads` and `results` each hold at least `count` elements; each
* `reads[i]` is a valid `ConflictSet_ReadRange` (see its field documentation);
* each `reads[i].readVersion <= newestVersion`.
* @post For every i < count, `results[i]` is `ConflictSet_TooOld` if
* `reads[i].readVersion < oldestVersion`; `ConflictSet_Conflict` if any write
* at a version greater than `reads[i].readVersion` intersects the range
* `reads[i]`; and `ConflictSet_Commit` otherwise. */
void ConflictSet_check(const ConflictSet *cs, void ConflictSet_check(const ConflictSet *cs,
const ConflictSet_ReadRange *reads, const ConflictSet_ReadRange *reads,
ConflictSet_Result *results, int count); ConflictSet_Result *results, int count);
/** Reads intersecting writes where readVersion < `writeVersion` will result /** Records writes at `writeVersion`, making them visible to
* in `Conflict` (or `TooOld`, eventually). `writeVersion` must be greater * `ConflictSet_check`.
* than or equal to all previous write versions. Call `addWrites` with `count` * @pre `writes` holds at least `count` elements; every `writes[i]` is a valid
* zero to only advance the version. */ * `ConflictSet_WriteRange` (see its field documentation); `count >= 0`;
* `writeVersion >= newestVersion`.
* @post Writes (writes[i], writeVersion) are recorded for every i < count,
* and `newestVersion` becomes `writeVersion`. `oldestVersion` advances as
* needed so that `oldestVersion >= newestVersion - two billion`;
* `oldestVersion <= newestVersion` is preserved. Calling with `count == 0`
* adds no write; `newestVersion` (and possibly `oldestVersion`) still
* advance. */
void ConflictSet_addWrites(ConflictSet *cs, void ConflictSet_addWrites(ConflictSet *cs,
const ConflictSet_WriteRange *writes, int count, const ConflictSet_WriteRange *writes, int count,
int64_t writeVersion); int64_t writeVersion);
/** Reads where readVersion < `oldestVersion` will result in `TooOld`. Must be /** Reads where readVersion < `oldestVersion` will result in `TooOld`.
* greater than or equal to all previous oldest versions. Must be <= the * @pre `oldestVersion >= 0` and `oldestVersion <= newestVersion`.
* version of the latest call to `addWrites` */ * @post `oldestVersion` becomes the maximum of its previous value and the
* argument; `newestVersion` is unchanged. */
void ConflictSet_setOldestVersion(ConflictSet *cs, int64_t oldestVersion); void ConflictSet_setOldestVersion(ConflictSet *cs, int64_t oldestVersion);
/** Reads where readVersion < oldestVersion will result in `TooOld`. There are /** Reads where readVersion < `oldestVersion` will result in `TooOld`.
* no writes initially */ * @pre `version >= 0`.
ConflictSet *ConflictSet_create(int64_t oldestVersion); * @post No writes are recorded, and `oldestVersion == newestVersion ==
* version`. */
ConflictSet *ConflictSet_create(int64_t version);
void ConflictSet_destroy(ConflictSet *cs); void ConflictSet_destroy(ConflictSet *cs);