• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

JuliaLang / julia / #37832

07 Jul 2024 09:07PM UTC coverage: 86.717% (-0.8%) from 87.5%
#37832

push

local

web-flow
add support for indexing in `@atomic` macro (#54707)

Following the discussion in #54642

Implemented:
- [x] `modifyindex_atomic!`, `swapindex_atomic!`, `replaceindex_atomic!`
for `GenericMemory`
- [x] `getindex_atomic`, `setindex_atomic!`, `setindexonce_atomic!` for
`GenericMemory`
- [x] add support for references in `@atomic` macros
- [x] add support for vararg indices in `@atomic` macros 
- [x] tests
- [x] update docstrings with example usage
- ~[ ] update Atomics section of the manual (?)~
- [x] news

@oscardssmith @vtjnash 

# New `@atomic` transformations implemented here:
```julia
julia> @macroexpand (@atomic a[i1,i2])
:(Base.getindex_atomic(a, :sequentially_consistent, i1, i2))

julia> @macroexpand (@atomic order a[i1,i2])
:(Base.getindex_atomic(a, order, i1, i2))

julia> @macroexpand (@atomic a[i1,i2] = 2.0)
:(Base.setindex_atomic!(a, :sequentially_consistent, 2.0, i1, i2))

julia> @macroexpand (@atomic order a[i1,i2] = 2.0)
:(Base.setindex_atomic!(a, order, 2.0, i1, i2))

julia> @macroexpand (@atomicswap a[i1,i2] = 2.0)
:(Base.swapindex_atomic!(a, :sequentially_consistent, 2.0, i1, i2))

julia> @macroexpand (@atomicswap order a[i1,i2] = 2.0)
:(Base.swapindex_atomic!(a, order, 2.0, i1, i2))

julia> @macroexpand (@atomic a[i1,i2] += 2.0)
:((Base.modifyindex_atomic!(a, :sequentially_consistent, +, 2.0, i1, i2))[2])

julia> @macroexpand (@atomic order a[i1,i2] += 2.0)
:((Base.modifyindex_atomic!(a, order, +, 2.0, i1, i2))[2])

julia> @macroexpand (@atomiconce a[i1,i2] = 2.0)
:(Base.setindexonce_atomic!(a, :sequentially_consistent, :sequentially_consistent, 2.0, i1, i2))

julia> @macroexpand (@atomiconce o1 o2 a[i1,i2] = 2.0)
:(Base.setindexonce_atomic!(a, o1, o2, 2.0, i1, i2))

julia> @macroexpand (@atomicreplace a[i1,i2] (2.0=>3.0))
:(Base.replaceindex_atomic!(a, :sequentially_consistent, :sequentially_consistent, 2.0, 3.0, i1, i2))

julia> @macroexpand (@atomicreplace o1 o2 a[i1,i2] (2.0=>3.0)... (continued)

66 of 73 new or added lines in 3 files covered. (90.41%)

879 existing lines in 26 files now uncovered.

76630 of 88368 relevant lines covered (86.72%)

15209469.38 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

10.26
/stdlib/UUIDs/src/UUIDs.jl
1
# This file is a part of Julia. License is MIT: https://julialang.org/license
2

3
"""
4
This module provides universally unique identifiers (UUIDs),
5
along with functions creating the different variants.
6
"""
7
module UUIDs
8

9
using Random
10

11
import SHA
12

13
export UUID, uuid1, uuid4, uuid5, uuid7, uuid_version
14

15
import Base: UUID
16

17
"""
18
    uuid_version(u::UUID) -> Int
19

20
Inspects the given UUID and returns its version
21
(see [RFC 4122](https://www.ietf.org/rfc/rfc4122)).
22

23
# Examples
24
```jldoctest
25
julia> uuid_version(uuid4())
26
4
27
```
28
"""
UNCOV
29
uuid_version(u::UUID) = Int((u.value >> 76) & 0xf)
×
30

31
# Some UUID namespaces provided in the appendix of RFC 4122
32
# https://tools.ietf.org/html/rfc4122.html#appendix-C
33
const namespace_dns  = UUID(0x6ba7b8109dad11d180b400c04fd430c8) # 6ba7b810-9dad-11d1-80b4-00c04fd430c8
34
const namespace_url  = UUID(0x6ba7b8119dad11d180b400c04fd430c8) # 6ba7b811-9dad-11d1-80b4-00c04fd430c8
35
const namespace_oid  = UUID(0x6ba7b8129dad11d180b400c04fd430c8) # 6ba7b812-9dad-11d1-80b4-00c04fd430c8
36
const namespace_x500 = UUID(0x6ba7b8149dad11d180b400c04fd430c8) # 6ba7b814-9dad-11d1-80b4-00c04fd430c8
37

38
"""
39
    uuid1([rng::AbstractRNG]) -> UUID
40

41
Generates a version 1 (time-based) universally unique identifier (UUID), as specified
42
by RFC 4122. Note that the Node ID is randomly generated (does not identify the host)
43
according to section 4.5 of the RFC.
44

45
The default rng used by `uuid1` is not `Random.default_rng()` and every invocation of `uuid1()` without
46
an argument should be expected to return a unique identifier. Importantly, the outputs of
47
`uuid1` do not repeat even when `Random.seed!(seed)` is called. Currently (as of Julia 1.6),
48
`uuid1` uses `Random.RandomDevice` as the default rng. However, this is an implementation
49
detail that may change in the future.
50

51
!!! compat "Julia 1.6"
52
    The output of `uuid1` does not depend on `Random.default_rng()` as of Julia 1.6.
53

54
# Examples
55
```jldoctest; filter = r"[a-z0-9]{8}-([a-z0-9]{4}-){3}[a-z0-9]{12}"
56
julia> using Random
57

58
julia> rng = MersenneTwister(1234);
59

60
julia> uuid1(rng)
61
UUID("cfc395e8-590f-11e8-1f13-43a2532b2fa8")
62
```
63
"""
UNCOV
64
function uuid1(rng::AbstractRNG=Random.RandomDevice())
×
UNCOV
65
    u = rand(rng, UInt128)
×
66

67
    # mask off clock sequence and node
UNCOV
68
    u &= 0x00000000000000003fffffffffffffff
×
69

70
    # set the unicast/multicast bit and version
UNCOV
71
    u |= 0x00000000000010000000010000000000
×
72

73
    # 0x01b21dd213814000 is the number of 100 nanosecond intervals
74
    # between the UUID epoch and Unix epoch
UNCOV
75
    timestamp = round(UInt64, time() * 1e7) + 0x01b21dd213814000
×
UNCOV
76
    ts_low = timestamp & typemax(UInt32)
×
UNCOV
77
    ts_mid = (timestamp >> 32) & typemax(UInt16)
×
UNCOV
78
    ts_hi = (timestamp >> 48) & 0x0fff
×
79

UNCOV
80
    u |= UInt128(ts_low) << 96
×
UNCOV
81
    u |= UInt128(ts_mid) << 80
×
UNCOV
82
    u |= UInt128(ts_hi) << 64
×
83

UNCOV
84
    UUID(u)
×
85
end
86

87
"""
88
    uuid4([rng::AbstractRNG]) -> UUID
89

90
Generates a version 4 (random or pseudo-random) universally unique identifier (UUID),
91
as specified by RFC 4122.
92

93
The default rng used by `uuid4` is not `Random.default_rng()` and every invocation of `uuid4()` without
94
an argument should be expected to return a unique identifier. Importantly, the outputs of
95
`uuid4` do not repeat even when `Random.seed!(seed)` is called. Currently (as of Julia 1.6),
96
`uuid4` uses `Random.RandomDevice` as the default rng. However, this is an implementation
97
detail that may change in the future.
98

99
!!! compat "Julia 1.6"
100
    The output of `uuid4` does not depend on `Random.default_rng()` as of Julia 1.6.
101

102
# Examples
103
```jldoctest
104
julia> using Random
105

106
julia> rng = Xoshiro(123);
107

108
julia> uuid4(rng)
109
UUID("856e446e-0c6a-472a-9638-f7b8557cd282")
110
```
111
"""
112
function uuid4(rng::AbstractRNG=Random.RandomDevice())
113
    u = rand(rng, UInt128)
86✔
114
    u &= 0xffffffffffff0fff3fffffffffffffff
43✔
115
    u |= 0x00000000000040008000000000000000
43✔
116
    UUID(u)
43✔
117
end
118

119
"""
120
    uuid5(ns::UUID, name::String) -> UUID
121

122
Generates a version 5 (namespace and domain-based) universally unique identifier (UUID),
123
as specified by RFC 4122.
124

125
!!! compat "Julia 1.1"
126
    This function requires at least Julia 1.1.
127

128
# Examples
129
```jldoctest
130
julia> using Random
131

132
julia> rng = Xoshiro(123);
133

134
julia> u4 = uuid4(rng)
135
UUID("856e446e-0c6a-472a-9638-f7b8557cd282")
136

137
julia> u5 = uuid5(u4, "julia")
138
UUID("2df91e3f-da06-5362-a6fe-03772f2e14c9")
139
```
140
"""
UNCOV
141
function uuid5(ns::UUID, name::String)
×
UNCOV
142
    nsbytes = zeros(UInt8, 16)
×
UNCOV
143
    nsv = ns.value
×
UNCOV
144
    for idx in Base.OneTo(16)
×
UNCOV
145
        nsbytes[idx] = nsv >> 120
×
UNCOV
146
        nsv = nsv << 8
×
UNCOV
147
    end
×
UNCOV
148
    hash_result = SHA.sha1(append!(nsbytes, convert(Vector{UInt8}, codeunits(unescape_string(name)))))
×
149
    # set version number to 5
UNCOV
150
    hash_result[7] = (hash_result[7] & 0x0F) | (0x50)
×
UNCOV
151
    hash_result[9] = (hash_result[9] & 0x3F) | (0x80)
×
UNCOV
152
    v = zero(UInt128)
×
153
    #use only the first 16 bytes of the SHA1 hash
UNCOV
154
    for idx in Base.OneTo(16)
×
UNCOV
155
        v = (v << 0x08) | hash_result[idx]
×
UNCOV
156
    end
×
UNCOV
157
    return UUID(v)
×
158
end
159

160
"""
161
    uuid7([rng::AbstractRNG]) -> UUID
162

163
Generates a version 7 (random or pseudo-random) universally unique identifier (UUID),
164
as specified by RFC 9652.
165

166
The default rng used by `uuid7` is not `Random.default_rng()` and every invocation of `uuid7()` without
167
an argument should be expected to return a unique identifier. Importantly, the outputs of
168
`uuid7` do not repeat even when `Random.seed!(seed)` is called. Currently (as of Julia 1.12),
169
`uuid7` uses `Random.RandomDevice` as the default rng. However, this is an implementation
170
detail that may change in the future.
171

172
!!! compat "Julia 1.12"
173
    `uuid7()` is available as of Julia 1.12.
174

175
# Examples
176
```jldoctest; filter = r"[a-z0-9]{8}-([a-z0-9]{4}-){3}[a-z0-9]{12}"
177
julia> using Random
178

179
julia> rng = Xoshiro(123);
180

181
julia> uuid7(rng)
182
UUID("019026ca-e086-772a-9638-f7b8557cd282")
183
```
184
"""
UNCOV
185
function uuid7(rng::AbstractRNG=Random.RandomDevice())
×
UNCOV
186
    bytes = rand(rng, UInt128)
×
187
    # make space for the timestamp
UNCOV
188
    bytes &= 0x0000000000000fff3fffffffffffffff
×
189
    # version & variant
UNCOV
190
    bytes |= 0x00000000000070008000000000000000
×
191

192
    # current time in ms, rounded to an Integer
UNCOV
193
    timestamp = round(UInt128, time() * 1e3)
×
UNCOV
194
    bytes |= timestamp << UInt128(80)
×
195

UNCOV
196
    return UUID(bytes)
×
197
end
198

199
end
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc