Skip to content

Commit

Permalink
data.ulid - Use internal random source for default
Browse files Browse the repository at this point in the history
Using default-random-source causes ULID conflict for multiple runs of
the program when the user doesn't randomize it.
Cf. #873
  • Loading branch information
shirok committed Jan 23, 2023
1 parent 92baed5 commit 85c403a
Show file tree
Hide file tree
Showing 3 changed files with 14 additions and 2 deletions.
8 changes: 8 additions & 0 deletions ChangeLog
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
2023-01-22 Shiro Kawai <shiro@acm.org>

* lib/data/ulid.scm (make-ulid-generator): Use internal random source
when random-source argument is omitted. Using default-random-source
causes ULID conflict for multiple runs if the user didn't randomize
it beforehand.
https://github.com/shirok/Gauche/issues/873

2023-01-20 Shiro Kawai <shiro@acm.org>

* src/compile-1.scm (pass1/body-rec): Make duplicate internal
Expand Down
2 changes: 1 addition & 1 deletion doc/modutil.texi
Original file line number Diff line number Diff line change
Expand Up @@ -7439,7 +7439,7 @@ Creates and returns a generator that yields a fresh ULID object
every time it is called. The optional @var{random-source} argument
is a SRFI-27 random source (@pxref{Sources of random bits})
to be used for the random part of ULID. When omitted,
SRFI-27's @code{default-random-source} is used.
an internal random source is used.

To guarantee uniqueness and monotonicity, a ULID generator needs to
keep internal state. If you want to share the generator among multiple threads,
Expand Down
6 changes: 5 additions & 1 deletion lib/data/ulid.scm
Original file line number Diff line number Diff line change
Expand Up @@ -63,12 +63,16 @@
(timestamp ulid-timestamp)
(randomness ulid-randomness))

(define ulid-random-source
(rlet1 s (make-random-source)
(random-source-randomize! s)))

;; API
;; NB: The ULID spec says ULID generation may fail if randomness is very close
;; to 2^80 and lots of ULIDs are generated in the same millisecond, causing
;; randomness field to overflow. We can, however, wait just one millisecond
;; to overcome that situation.
(define (make-ulid-generator :optional (random-source default-random-source))
(define (make-ulid-generator :optional (random-source ulid-random-source))
(let ((randomness (random-source-make-integers random-source))
(last-ts 0)
(last-rn 0))
Expand Down

0 comments on commit 85c403a

Please sign in to comment.