Skip to content

Commit 1ebe4a7

Browse files
committed
finalize atomic macro names
1 parent 00e9ec6 commit 1ebe4a7

File tree

4 files changed

+101
-129
lines changed

4 files changed

+101
-129
lines changed

base/exports.jl

+2-3
Original file line numberDiff line numberDiff line change
@@ -1019,9 +1019,8 @@ export
10191019

10201020
@assert,
10211021
@atomic,
1022-
@atomic!,
1023-
@atomic_swap!,
1024-
@atomic_replace!,
1022+
@atomicswap,
1023+
@atomicreplace,
10251024
@__dot__,
10261025
@enum,
10271026
@label,

base/expr.jl

+64-90
Original file line numberDiff line numberDiff line change
@@ -453,43 +453,10 @@ end
453453
454454
Mark `var` or `ex` as being performed atomically, if `ex` is a supported expression.
455455
456-
See [atomics](#man-atomics) in the manual for more details.
457-
458-
```jldoctest
459-
julia> mutable struct Atomic{T}; @atomic x::T; end
460-
461-
julia> a = Atomic(1)
462-
Atomic{Int64}(1)
463-
464-
julia> @atomic a.x # fetch field x of a, with sequential consistency
465-
1
466-
```
467-
"""
468-
macro atomic(ex)
469-
if !isa(ex, Symbol) && !is_expr(ex, :(::))
470-
return make_atomic(QuoteNode(:sequentially_consistent), ex)
471-
end
472-
return esc(Expr(:atomic, ex))
473-
end
474-
macro atomic(order, ex)
475-
order isa QuoteNode || (order = esc(order))
476-
return make_atomic(order, ex)
477-
end
478-
function make_atomic(order, ex)
479-
@nospecialize
480-
if isexpr(ex, :., 2)
481-
l, r = esc(ex.args[1]), esc(ex.args[2])
482-
return :(getproperty($l, $r, $order))
483-
end
484-
error("could not parse @atomic expression $ex")
485-
end
486-
487-
488-
"""
489-
@atomic! a.b.x = new
490-
@atomic! a.b.x += addend
491-
@atomic! :acquire_release a.b.x = new
492-
@atomic! :acquire_release a.b.x += addend
456+
@atomic a.b.x = new
457+
@atomic a.b.x += addend
458+
@atomic :acquire_release a.b.x = new
459+
@atomic :acquire_release a.b.x += addend
493460
494461
Perform the store operation expressed on the right atomically and return the
495462
new value.
@@ -498,18 +465,19 @@ With `=`, this operation translates to a `setproperty!(a.b, :x, new)` call.
498465
With any operator also, this operation translates to a `modifyproperty!(a.b,
499466
:x, +, addend)[2]` call.
500467
501-
@atomic! a.b.x max arg2
502-
@atomic! a.b.x + arg2
503-
@atomic! max(a.b.x, arg2)
504-
@atomic! :acquire_release max(a.b.x, arg2)
505-
@atomic! :acquire_release a.b.x + arg2
506-
@atomic! :acquire_release a.b.x max arg2
468+
@atomic a.b.x max arg2
469+
@atomic a.b.x + arg2
470+
@atomic max(a.b.x, arg2)
471+
@atomic :acquire_release max(a.b.x, arg2)
472+
@atomic :acquire_release a.b.x + arg2
473+
@atomic :acquire_release a.b.x max arg2
507474
508475
Perform the binary operation expressed on the right atomically. Store the
509476
result into the field in the first argument and return the values `(old, new)`.
510477
511478
This operation translates to a `modifyproperty!(a.b, :x, func, arg2)` call.
512479
480+
513481
See [atomics](#man-atomics) in the manual for more details.
514482
515483
```jldoctest
@@ -518,44 +486,53 @@ julia> mutable struct Atomic{T}; @atomic x::T; end
518486
julia> a = Atomic(1)
519487
Atomic{Int64}(1)
520488
521-
julia> @atomic! :sequentially_consistent a.x = 2 # set field x of a, with sequential consistency
489+
julia> @atomic a.x # fetch field x of a, with sequential consistency
490+
1
491+
492+
julia> @atomic :sequentially_consistent a.x = 2 # set field x of a, with sequential consistency
522493
2
523494
524-
julia> @atomic! a.x += 1 # increment field x of a, with sequential consistency
495+
julia> @atomic a.x += 1 # increment field x of a, with sequential consistency
525496
3
526497
527-
julia> @atomic! a.x + 1 # increment field x of a, with sequential consistency
498+
julia> @atomic a.x + 1 # increment field x of a, with sequential consistency
528499
(3, 4)
529500
530501
julia> @atomic a.x # fetch field x of a, with sequential consistency
531502
4
532503
533-
julia> @atomic! max(a.x, 10) # change field x of a to the max value, with sequential consistency
504+
julia> @atomic max(a.x, 10) # change field x of a to the max value, with sequential consistency
534505
(4, 10)
535506
536-
julia> @atomic! a.x max 5 # again change field x of a to the max value, with sequential consistency
507+
julia> @atomic a.x max 5 # again change field x of a to the max value, with sequential consistency
537508
(10, 10)
538509
```
539510
"""
540-
macro atomic!(order, a1, op, a2)
511+
macro atomic(ex)
512+
if !isa(ex, Symbol) && !is_expr(ex, :(::))
513+
return make_atomic(QuoteNode(:sequentially_consistent), ex)
514+
end
515+
return esc(Expr(:atomic, ex))
516+
end
517+
macro atomic(order, ex)
541518
order isa QuoteNode || (order = esc(order))
542-
return make_atomic!(order, a1, op, a2)
519+
return make_atomic(order, ex)
543520
end
544-
macro atomic!(a1, op, a2)
545-
return make_atomic!(QuoteNode(:sequentially_consistent), a1, op, a2)
521+
macro atomic(a1, op, a2)
522+
return make_atomic(QuoteNode(:sequentially_consistent), a1, op, a2)
546523
end
547-
macro atomic!(order, ex)
524+
macro atomic(order, a1, op, a2)
548525
order isa QuoteNode || (order = esc(order))
549-
return make_atomic!(order, ex)
550-
end
551-
macro atomic!(ex)
552-
return make_atomic!(QuoteNode(:sequentially_consistent), ex)
526+
return make_atomic(order, a1, op, a2)
553527
end
554-
function make_atomic!(order, ex)
528+
function make_atomic(order, ex)
555529
@nospecialize
556530
if ex isa Expr
557-
if isexpr(ex, :call, 3)
558-
return make_atomic!(order, ex.args[2], ex.args[1], ex.args[3])
531+
if isexpr(ex, :., 2)
532+
l, r = esc(ex.args[1]), esc(ex.args[2])
533+
return :(getproperty($l, $r, $order))
534+
elseif isexpr(ex, :call, 3)
535+
return make_atomic(order, ex.args[2], ex.args[1], ex.args[3])
559536
elseif ex.head === :(=)
560537
l, r = ex.args[1], ex.args[2]
561538
if is_expr(l, :., 2)
@@ -575,26 +552,23 @@ function make_atomic!(order, ex)
575552
end
576553
end
577554
if @isdefined(op)
578-
l, r = ex.args[1], esc(ex.args[2])
579-
is_expr(l, :.) || error("@atomic modify expression missing field access")
580-
ll, lr, op = esc(l.args[1]), esc(l.args[2]), esc(op)
581-
return :(modifyproperty!($ll, $lr, $op, $r, $order)[2])
555+
return Expr(:ref, make_atomic(order, ex.args[1], op, ex.args[2]), 2)
582556
end
583557
end
584558
end
585-
error("could not parse @atomic! modify expression $ex")
559+
error("could not parse @atomic expression $ex")
586560
end
587-
function make_atomic!(order, a1, op, a2)
561+
function make_atomic(order, a1, op, a2)
588562
@nospecialize
589-
is_expr(a1, :., 2) || error("@atomic! modify expression missing field access")
563+
is_expr(a1, :., 2) || error("@atomic modify expression missing field access")
590564
a1l, a1r, op, a2 = esc(a1.args[1]), esc(a1.args[2]), esc(op), esc(a2)
591565
return :(modifyproperty!($a1l, $a1r, $op, $a2, $order))
592566
end
593567

594568

595569
"""
596-
@atomic_swap! a.b.x new
597-
@atomic_swap! :sequentially_consistent a.b.x new
570+
@atomicswap a.b.x new
571+
@atomicswap :sequentially_consistent a.b.x new
598572
599573
Stores `new` into `a.b.x` and returns the old value of `a.b.x`.
600574
@@ -608,32 +582,32 @@ julia> mutable struct Atomic{T}; @atomic x::T; end
608582
julia> a = Atomic(1)
609583
Atomic{Int64}(1)
610584
611-
julia> @atomic_swap! a.x 2+2 # replace field x of a with 4, with sequential consistency
585+
julia> @atomicswap a.x 2+2 # replace field x of a with 4, with sequential consistency
612586
1
613587
614588
julia> @atomic a.x # fetch field x of a, with sequential consistency
615589
4
616590
```
617591
"""
618-
macro atomic_swap!(order, ex, val)
592+
macro atomicswap(order, ex, val)
619593
order isa QuoteNode || (order = esc(order))
620-
return make_atomic_swap!(order, ex, val)
594+
return make_atomicswap(order, ex, val)
621595
end
622-
macro atomic_swap!(ex, val)
623-
return make_atomic_swap!(QuoteNode(:sequentially_consistent), ex, val)
596+
macro atomicswap(ex, val)
597+
return make_atomicswap(QuoteNode(:sequentially_consistent), ex, val)
624598
end
625-
function make_atomic_swap!(order, ex, val)
599+
function make_atomicswap(order, ex, val)
626600
@nospecialize
627-
is_expr(ex, :., 2) || error("@atomic_swap! expression missing field access")
601+
is_expr(ex, :., 2) || error("@atomicswap expression missing field access")
628602
l, r, val = esc(ex.args[1]), esc(ex.args[2]), esc(val)
629603
return :(swapproperty!($l, $r, $val, $order))
630604
end
631605

632606

633607
"""
634-
@atomic_replace! a.b.x expected => desired
635-
@atomic_replace! :sequentially_consistent a.b.x expected => desired
636-
@atomic_replace! :sequentially_consistent :monotonic a.b.x expected => desired
608+
@atomicreplace a.b.x expected => desired
609+
@atomicreplace :sequentially_consistent a.b.x expected => desired
610+
@atomicreplace :sequentially_consistent :monotonic a.b.x expected => desired
637611
638612
Perform the conditional replacement expressed by the pair atomically, returning
639613
the values `(old, success::Bool)`. Where `success` indicates whether the
@@ -649,39 +623,39 @@ julia> mutable struct Atomic{T}; @atomic x::T; end
649623
julia> a = Atomic(1)
650624
Atomic{Int64}(1)
651625
652-
julia> @atomic_replace! a.x 1 => 2 # replace field x of a with 2 if it was 1, with sequential consistency
626+
julia> @atomicreplace a.x 1 => 2 # replace field x of a with 2 if it was 1, with sequential consistency
653627
(1, true)
654628
655629
julia> @atomic a.x # fetch field x of a, with sequential consistency
656630
2
657631
658-
julia> @atomic_replace! a.x 1 => 2 # replace field x of a with 2 if it was 1, with sequential consistency
632+
julia> @atomicreplace a.x 1 => 2 # replace field x of a with 2 if it was 1, with sequential consistency
659633
(2, false)
660634
661635
julia> xchg = 2 => 0; # replace field x of a with 0 if it was 1, with sequential consistency
662636
663-
julia> @atomic_replace! a.x xchg
637+
julia> @atomicreplace a.x xchg
664638
(2, true)
665639
666640
julia> @atomic a.x # fetch field x of a, with sequential consistency
667641
0
668642
```
669643
"""
670-
macro atomic_replace!(success_order, fail_order, ex, old_new)
644+
macro atomicreplace(success_order, fail_order, ex, old_new)
671645
fail_order isa QuoteNode || (fail_order = esc(fail_order))
672646
success_order isa QuoteNode || (success_order = esc(success_order))
673-
return make_atomic_replace!(success_order, fail_order, ex, old_new)
647+
return make_atomicreplace(success_order, fail_order, ex, old_new)
674648
end
675-
macro atomic_replace!(order, ex, old_new)
649+
macro atomicreplace(order, ex, old_new)
676650
order isa QuoteNode || (order = esc(order))
677-
return make_atomic_replace!(order, order, ex, old_new)
651+
return make_atomicreplace(order, order, ex, old_new)
678652
end
679-
macro atomic_replace!(ex, old_new)
680-
return make_atomic_replace!(QuoteNode(:sequentially_consistent), QuoteNode(:sequentially_consistent), ex, old_new)
653+
macro atomicreplace(ex, old_new)
654+
return make_atomicreplace(QuoteNode(:sequentially_consistent), QuoteNode(:sequentially_consistent), ex, old_new)
681655
end
682-
function make_atomic_replace!(success_order, fail_order, ex, old_new)
656+
function make_atomicreplace(success_order, fail_order, ex, old_new)
683657
@nospecialize
684-
is_expr(ex, :., 2) || error("@atomic_replace! expression missing field access")
658+
is_expr(ex, :., 2) || error("@atomicreplace expression missing field access")
685659
ll, lr = esc(ex.args[1]), esc(ex.args[2])
686660
if is_expr(old_new, :call, 3) && old_new.args[1] === :(=>)
687661
exp, rep = esc(old_new.args[2]), esc(old_new.args[3])

doc/src/base/multi-threading.md

+2-3
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,8 @@ See also [Synchronization](@ref lib-task-sync).
2121

2222
```@docs
2323
Base.@atomic
24-
Base.@atomic!
25-
Base.@atomic_swap!
26-
Base.@atomic_replace!
24+
Base.@atomicswap
25+
Base.@atomicreplace
2726
```
2827

2928
!!! note

test/atomics.jl

+33-33
Original file line numberDiff line numberDiff line change
@@ -286,53 +286,53 @@ test_field_undef(ARefxy{UndefComplex{UndefComplex{Any}}})
286286

287287
@test_throws ErrorException @macroexpand @atomic foo()
288288
@test_throws ErrorException @macroexpand @atomic foo += bar
289-
@test_throws ErrorException @macroexpand @atomic! foo += bar
290-
@test_throws ErrorException @macroexpand @atomic! foo = bar
291-
@test_throws ErrorException @macroexpand @atomic! foo()
292-
@test_throws ErrorException @macroexpand @atomic! foo(bar)
293-
@test_throws ErrorException @macroexpand @atomic! foo(bar, baz)
294-
@test_throws ErrorException @macroexpand @atomic! foo(bar, baz, bax)
295-
@test_throws ErrorException @macroexpand @atomic_replace! foo bar
289+
@test_throws ErrorException @macroexpand @atomic foo += bar
290+
@test_throws ErrorException @macroexpand @atomic foo = bar
291+
@test_throws ErrorException @macroexpand @atomic foo()
292+
@test_throws ErrorException @macroexpand @atomic foo(bar)
293+
@test_throws ErrorException @macroexpand @atomic foo(bar, baz)
294+
@test_throws ErrorException @macroexpand @atomic foo(bar, baz, bax)
295+
@test_throws ErrorException @macroexpand @atomicreplace foo bar
296296

297297
# test macroexpansions
298298
let a = ARefxy(1, -1)
299299
@test 1 === @atomic a.x
300-
@test 2 === @atomic! :sequentially_consistent a.x = 2
301-
@test 3 === @atomic! :monotonic a.x = 3
302-
@test_throws ConcurrencyViolationError @atomic! :not_atomic a.x = 2
300+
@test 2 === @atomic :sequentially_consistent a.x = 2
301+
@test 3 === @atomic :monotonic a.x = 3
302+
@test_throws ConcurrencyViolationError @atomic :not_atomic a.x = 2
303303
@test_throws ConcurrencyViolationError @atomic :not_atomic a.x
304-
@test_throws ConcurrencyViolationError @atomic! :not_atomic a.x += 1
304+
@test_throws ConcurrencyViolationError @atomic :not_atomic a.x += 1
305305

306306
@test 3 === @atomic :monotonic a.x
307-
@test 5 === @atomic! a.x += 2
308-
@test 4 === @atomic! :monotonic a.x -= 1
309-
@test 12 === @atomic! :monotonic a.x *= 3
307+
@test 5 === @atomic a.x += 2
308+
@test 4 === @atomic :monotonic a.x -= 1
309+
@test 12 === @atomic :monotonic a.x *= 3
310310

311311
@test 12 === @atomic a.x
312-
@test (12, 13) === @atomic! a.x + 1
313-
@test (13, 15) === @atomic! :monotonic a.x + 2
314-
@test (15, 19) === @atomic! a.x max 19
315-
@test (19, 20) === @atomic! :monotonic a.x max 20
316-
@test_throws ConcurrencyViolationError @atomic! :not_atomic a.x + 1
317-
@test_throws ConcurrencyViolationError @atomic! :not_atomic a.x max 30
312+
@test (12, 13) === @atomic a.x + 1
313+
@test (13, 15) === @atomic :monotonic a.x + 2
314+
@test (15, 19) === @atomic a.x max 19
315+
@test (19, 20) === @atomic :monotonic a.x max 20
316+
@test_throws ConcurrencyViolationError @atomic :not_atomic a.x + 1
317+
@test_throws ConcurrencyViolationError @atomic :not_atomic a.x max 30
318318

319319
@test 20 === @atomic a.x
320-
@test 20 === @atomic_swap! a.x 1
321-
@test 1 === @atomic_swap! :monotonic a.x 2
322-
@test_throws ConcurrencyViolationError @atomic_swap! :not_atomic a.x 1
320+
@test 20 === @atomicswap a.x 1
321+
@test 1 === @atomicswap :monotonic a.x 2
322+
@test_throws ConcurrencyViolationError @atomicswap :not_atomic a.x 1
323323

324324
@test 2 === @atomic a.x
325-
@test (2, true) === @atomic_replace! a.x 2 => 1
326-
@test (1, false) === @atomic_replace! :monotonic a.x 2 => 1
327-
@test (1, false) === @atomic_replace! :monotonic :monotonic a.x 2 => 1
328-
@test_throws ConcurrencyViolationError @atomic_replace! :not_atomic a.x 1 => 2
329-
@test_throws ConcurrencyViolationError @atomic_replace! :monotonic :acquire a.x 1 => 2
325+
@test (2, true) === @atomicreplace a.x 2 => 1
326+
@test (1, false) === @atomicreplace :monotonic a.x 2 => 1
327+
@test (1, false) === @atomicreplace :monotonic :monotonic a.x 2 => 1
328+
@test_throws ConcurrencyViolationError @atomicreplace :not_atomic a.x 1 => 2
329+
@test_throws ConcurrencyViolationError @atomicreplace :monotonic :acquire a.x 1 => 2
330330

331331
@test 1 === @atomic a.x
332332
xchg = 1 => 2
333-
@test (1, true) === @atomic_replace! a.x xchg
334-
@test (2, false) === @atomic_replace! :monotonic a.x xchg
335-
@test (2, false) === @atomic_replace! :acquire_release :monotonic a.x xchg
336-
@test_throws ConcurrencyViolationError @atomic_replace! :not_atomic a.x xchg
337-
@test_throws ConcurrencyViolationError @atomic_replace! :monotonic :acquire a.x xchg
333+
@test (1, true) === @atomicreplace a.x xchg
334+
@test (2, false) === @atomicreplace :monotonic a.x xchg
335+
@test (2, false) === @atomicreplace :acquire_release :monotonic a.x xchg
336+
@test_throws ConcurrencyViolationError @atomicreplace :not_atomic a.x xchg
337+
@test_throws ConcurrencyViolationError @atomicreplace :monotonic :acquire a.x xchg
338338
end

0 commit comments

Comments
 (0)