You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Monotonicity state moved into GenerationOptions instance making the state not globally shared (#63)
* Monotonicity state moved into `GenerationOptions` instance. Identical performance.
* Monotonic generation tests simplified as state is now held inside the GenerationOptions instance.
ULIDs (Universally Unique Lexicographically Sortable Identifiers) offer a modern, human-readable alternative to traditional GUIDs, optimized specifically for distributed systems and time-ordered data. **ByteAether.Ulid** delivers a high-performance, specification-compliant .NET implementation engineered to resolve critical concurrency and persistence edge cases left unaddressed by alternative libraries.
28
+
ULIDs (Universally Unique Lexicographically Sortable Identifiers) offer a modern, human-readable alternative to traditional GUIDs, optimized specifically for distributed systems and time-ordered data. **ByteAether.Ulid** delivers a high-performance, specification-compliant .NET implementation engineered to resolve critical concurrency and persistence edge cases unaddressed by alternative libraries.
@@ -150,7 +150,11 @@ You can customize ULID generation by providing `GenerationOptions`. This allows
150
150
151
151
#### Example: Monotonic ULID with Random Increments
152
152
153
-
To generate ULIDs that are monotonically increasing with a random increment, you can specify the `Monotonicity` option.
153
+
The monotonicity state (last generated timestamp and 80-bit random payload) is bound directly to the lifecycle of the `GenerationOptions` instance.
154
+
155
+
***Instance Reuse (Recommended for Sequences):** Reusing a single `GenerationOptions` instance across calls guarantees strict, cross-thread monotonic ordering via lock-free atomic compare-and-exchange (CAS) operations.
156
+
***Instance Isolation:** Passing a new `GenerationOptions` instance on each call isolates state, disabling monotonic sequence tracking between calls and eliminating CAS contention.
157
+
154
158
```csharp
155
159
usingSystem;
156
160
usingByteAether.Ulid;
@@ -241,13 +245,13 @@ The `Ulid` implementation provides the following properties and methods:
241
245
### Properties
242
246
243
247
-`Ulid.MinValue`\
244
-
Represents an empty ULID, equivalent to `default(Ulid)`and`Ulid.New(new byte[16])`.
248
+
Represents an empty ULID, equivalent to `default(Ulid)`or`Ulid.New(new byte[16])`.
245
249
-`Ulid.MaxValue`\
246
250
Represents the maximum possible value for a ULID (all bytes set to `0xFF`).
247
251
-`Ulid.Empty`\
248
252
Alias for `Ulid.MinValue`.
249
253
-`Ulid.DefaultGenerationOptions`\
250
-
Default configuration for ULID generation when no options are provided by the `Ulid.New(...)` call.
254
+
Gets or sets the global default `GenerationOptions` configuration for ULID generation when no options are provided by the `Ulid.New(...)` call.
251
255
-`.Time`\
252
256
Gets the timestamp component of the ULID as a `DateTimeOffset`.
253
257
-`.TimeBytes`\
@@ -278,10 +282,15 @@ The `Ulid` implementation provides the following properties and methods:
278
282
279
283
### GenerationOptions
280
284
281
-
The `GenerationOptions` class provides detailed configuration for ULID generation, with the following key properties:
285
+
The `GenerationOptions` class encapsulates generation strategy, state retention, and lock-free thread synchronization for monotonic ULID generation.
286
+
287
+
Configurable properties:
282
288
283
289
-`Monotonicity`\
284
-
Controls the behavior of ULID generation when multiple identifiers are created within the same millisecond. It determines whether ULIDs are strictly increasing or allow for random ordering within that millisecond. Available options include: `NonMonotonic`, `MonotonicIncrement` (default), `MonotonicRandom1Byte`, `MonotonicRandom2Byte`, `MonotonicRandom3Byte`, `MonotonicRandom4Byte`.
290
+
Defines the monotonic strategy when generating multiple ULIDs within the same millisecond. Each instance maintains an atomic state machine using lock-free Compare-And-Swap (CAS) primitives to guarantee strict sequential ordering without mutex locking. Options include:
291
+
-`NonMonotonic`: Generates fully random 80-bit payloads without state tracking.
292
+
-`MonotonicIncrement` (Default): Increments the least significant bit of the random payload upon sub-millisecond collisions.
293
+
-`MonotonicRandom1Byte`, `MonotonicRandom2Byte`, `MonotonicRandom3Byte`, `MonotonicRandom4Byte`: Adds a random integer increment within the specified byte range to the payload, strengthening entropy against enumeration attacks while maintaining monotonicity.
285
294
286
295
-`InitialRandomSource`\
287
296
An `IRandomProvider` for generating the random bytes of a ULID. The default `CryptographicallySecureRandomProvider` ensures robust, unpredictable ULIDs using a cryptographically secure generator.
0 commit comments