Skip to content

Commit

Permalink
Avoid a deadlock when running MT
Browse files Browse the repository at this point in the history
This fix may be better as a reentrant mutex that is conditionally applied only to mt_preview compiled code, but I like the fact that spinlocks become no-ops unless running multithreaded, and they are very simple.
Also bump the version for a new release, and made a couple code cleanliness tweaks.
  • Loading branch information
wyhaines committed May 21, 2024
1 parent a4cf961 commit b71cf5c
Show file tree
Hide file tree
Showing 3 changed files with 9 additions and 8 deletions.
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1.0.0
1.0.1
4 changes: 2 additions & 2 deletions shard.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name: csuuid
version: 1.0.0
version: 1.0.1

authors:
- Kirk Haines <[email protected]>
Expand All @@ -18,4 +18,4 @@ dependencies:
development_dependencies:
ameba:
github: crystal-ameba/ameba
version: ~> 1.5
version: ~> 1.6
11 changes: 6 additions & 5 deletions src/csuuid.cr
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ struct CSUUID
# It defaults to `Random::ISAAC`.
class_property prng : Random = Random::ISAAC.new
@@mutex = Crystal::SpinLock.new
@@isaac_mutex = Crystal::SpinLock.new
@@unique_identifier : Slice(UInt8) = Slice(UInt8).new(6, 0)
@@unique_seconds_and_nanoseconds : Tuple(Int64, Int32) = {0_i64, 0_i32}

Expand Down Expand Up @@ -153,11 +154,11 @@ struct CSUUID

IO::ByteFormat::BigEndian.encode(seconds, @bytes[2, 8])
IO::ByteFormat::BigEndian.encode(nanoseconds, @bytes[0, 4])
@@mutex.sync do
@@isaac_mutex.sync do
# Random::ISAAC.random_bytes doesn't appear to be threadsafe.
# It sometimes dies ugly in multithreaded code, so we need a
# lock in this one tiny little space to avoid that.
# TODO: Check if this is still the case post Crystal 1.4.0,
# Check if this is still the case post Crystal 1.4.0,
# and if it is, fix Crypt::ISAAC and send in a PR.
@bytes[10, 6].copy_from(id || CSUUID.prng.random_bytes(6))
end
Expand Down Expand Up @@ -201,16 +202,16 @@ struct CSUUID

# Compare two CSUUID objects, returning -1 if the first is less than the second,
# 0 if they are equal, and 1 if the first is greater than the second.
def <=>(val : CSUUID)
def <=>(other : CSUUID)
s, ns = seconds_and_nanoseconds
s_val, ns_val = val.seconds_and_nanoseconds
s_val, ns_val = other.seconds_and_nanoseconds
r = s <=> s_val
return r unless r == 0

r = ns <=> ns_val
return r unless r == 0

to_s <=> val.to_s
to_s <=> other.to_s
end

# Returns `true` if `self` is less than *other*.
Expand Down

0 comments on commit b71cf5c

Please sign in to comment.