26
26
UInt8, UInt16, UInt32, UInt64, UInt128)
27
27
end
28
28
const floattypes = (Float16, Float32, Float64)
29
- # TODO : Support Bool, Ptr
30
- const atomictypes = (inttypes... , floattypes... )
29
+ const arithmetictypes = (inttypes... , floattypes... )
30
+ # TODO : Support Ptr
31
+ const atomictypes = (arithmetictypes... , Bool)
31
32
const IntTypes = Union{inttypes... }
32
33
const FloatTypes = Union{floattypes... }
34
+ const ArithmeticTypes = Union{arithmetictypes... }
33
35
const AtomicTypes = Union{atomictypes... }
34
36
35
37
"""
@@ -39,8 +41,8 @@ Holds a reference to an object of type `T`, ensuring that it is only
39
41
accessed atomically, i.e. in a thread-safe manner.
40
42
41
43
Only certain "simple" types can be used atomically, namely the
42
- primitive integer and float-point types. These are `Int8`...`Int128 `,
43
- `UInt8`...`UInt128`, and `Float16`...`Float64`.
44
+ primitive boolean, integer, and float-point types. These are `Bool `,
45
+ `Int8`...`Int128`, ` UInt8`...`UInt128`, and `Float16`...`Float64`.
44
46
45
47
New atomic objects can be created from a non-atomic values; if none is
46
48
specified, the atomic object is initialized with zero.
@@ -130,11 +132,12 @@ julia> x[]
130
132
function atomic_xchg! end
131
133
132
134
"""
133
- Threads.atomic_add!(x::Atomic{T}, val::T) where T
135
+ Threads.atomic_add!(x::Atomic{T}, val::T) where T <: ArithmeticTypes
134
136
135
137
Atomically add `val` to `x`
136
138
137
- Performs `x[] += val` atomically. Returns the **old** value.
139
+ Performs `x[] += val` atomically. Returns the **old** value. Not defined for
140
+ `Atomic{Bool}`.
138
141
139
142
For further details, see LLVM's `atomicrmw add` instruction.
140
143
@@ -153,11 +156,12 @@ julia> x[]
153
156
function atomic_add! end
154
157
155
158
"""
156
- Threads.atomic_sub!(x::Atomic{T}, val::T) where T
159
+ Threads.atomic_sub!(x::Atomic{T}, val::T) where T <: ArithmeticTypes
157
160
158
161
Atomically subtract `val` from `x`
159
162
160
- Performs `x[] -= val` atomically. Returns the **old** value.
163
+ Performs `x[] -= val` atomically. Returns the **old** value. Not defined for
164
+ `Atomic{Bool}`.
161
165
162
166
For further details, see LLVM's `atomicrmw sub` instruction.
163
167
@@ -317,7 +321,7 @@ unsafe_convert(::Type{Ptr{T}}, x::Atomic{T}) where {T} = convert(Ptr{T}, pointer
317
321
setindex! (x:: Atomic{T} , v) where {T} = setindex! (x, convert (T, v))
318
322
319
323
const llvmtypes = IdDict {Any,String} (
320
- Bool => " i1 " ,
324
+ Bool => " i8 " , # julia represents bools with 8-bits for now. # TODO : is this okay?
321
325
Int8 => " i8" , UInt8 => " i8" ,
322
326
Int16 => " i16" , UInt16 => " i16" ,
323
327
Int32 => " i32" , UInt32 => " i32" ,
@@ -380,13 +384,15 @@ for typ in atomictypes
380
384
unsafe_convert (Ptr{$ typ}, x), cmp, new)
381
385
end
382
386
383
- for rmwop in [:xchg , :add , :sub , :and , :nand , :or , :xor , :max , :min ]
387
+ arithmetic_ops = [:add , :sub ]
388
+ for rmwop in [arithmetic_ops... , :xchg , :and , :nand , :or , :xor , :max , :min ]
384
389
rmw = string (rmwop)
385
390
fn = Symbol (" atomic_" , rmw, " !" )
386
391
if (rmw == " max" || rmw == " min" ) && typ <: Unsigned
387
392
# LLVM distinguishes signedness in the operation, not the integer type.
388
393
rmw = " u" * rmw
389
394
end
395
+ if rmwop in arithmetic_ops && ! (typ <: ArithmeticTypes ) continue end
390
396
if typ <: Integer
391
397
@eval $ fn (x:: Atomic{$typ} , v:: $typ ) =
392
398
llvmcall ($ """
0 commit comments