@@ -525,14 +525,10 @@ end
525525 @atomic! :acquire_release a.b.x + new()
526526 @atomic! :acquire_release a.b.x max new()
527527
528- @atomic! a.b.x = new()
529- @atomic! :acquire_release a.b.x = new()
528+ Perform the binary operation expressed on the right atomically. Store the
529+ result into the field in the first argument and return the values `(old, new)`.
530530
531- Perform the operation expressed on the right atomically, for the supported
532- expressions shown, returning the values `(old, new)`.
533-
534- The first set of operations translates to a `modifyproperty!` call.
535- The second set of operations translates to a `swapproperty!` call.
531+ This operation translates to a `modifyproperty!(a.b, :x, func, arg2)` call.
536532
537533See [atomics](#man-atomics) in the manual for more details.
538534
@@ -542,17 +538,14 @@ julia> mutable struct Atomic{T}; @atomic x::T; end
542538julia> a = Atomic(1)
543539Atomic{Int64}(1)
544540
545- julia> @atomic! :sequentially_consistent a.x = 2 # swap field x of a, with sequential consistency
541+ julia> @atomic! a.x + 1 # increment field x of a, with sequential consistency
546542(1, 2)
547543
548544julia> @atomic a.x # fetch field x of a, with sequential consistency
5495452
550546
551- julia> @atomic! a.x + 1 # increment field x of a, with sequential consistency
552- (2, 3)
553-
554547julia> @atomic! max(a.x, 10) # change field x of a to the max value, with sequential consistency
555- (3 , 10)
548+ (2 , 10)
556549
557550julia> @atomic! a.x max 5 # again change field x of a to the max value, with sequential consistency
558551(10, 10)
@@ -574,27 +567,55 @@ macro atomic!(ex)
574567end
575568function make_atomic! (order, ex)
576569 @nospecialize
577- if ex isa Expr
578- if ex. head === :call
579- length (ex. args) == 3 || error (" @atomic modify expression has the wrong number of function arguments" )
580- return make_atomic! (order, ex. args[2 ], ex. args[1 ], ex. args[3 ])
581- elseif ex. head === :(= )
582- l, r = ex. args[1 ], ex. args[2 ]
583- is_expr (l, :., 2 ) || error (" @atomic swap expression missing field access" )
584- ll, lr = esc (l. args[1 ]), esc (l. args[2 ])
585- val = esc (r)
586- return :(local val = $ val; (swapproperty! ($ ll, $ lr, val, $ order), val))
587- end
588- end
589- error (" could not parse @atomic expression $ex " )
570+ isexpr (ex, :call , 3 ) || error (" could not parse @atomic! modify expression $ex " )
571+ return make_atomic! (order, ex. args[2 ], ex. args[1 ], ex. args[3 ])
590572end
591573function make_atomic! (order, a1, op, a2)
592574 @nospecialize
593- is_expr (a1, :., 2 ) || error (" @atomic modify expression missing field access" )
575+ is_expr (a1, :., 2 ) || error (" @atomic! modify expression missing field access" )
594576 a1l, a1r, op, a2 = esc (a1. args[1 ]), esc (a1. args[2 ]), esc (op), esc (a2)
595577 return :(modifyproperty! ($ a1l, $ a1r, $ op, $ a2, $ order))
596578end
597579
580+
581+ """
582+ @atomic_swap! a.b.x new
583+ @atomic_swap! :sequentially_consistent a.b.x new
584+
585+ Stores `new` into `a.b.x` and returns the old value of `a.b.x`.
586+
587+ This operation translates to a `swapproperty!(a.b, :x, new)` call.
588+
589+ See [atomics](#man-atomics) in the manual for more details.
590+
591+ ```jldoctest
592+ julia> mutable struct Atomic{T}; @atomic x::T; end
593+
594+ julia> a = Atomic(1)
595+ Atomic{Int64}(1)
596+
597+ julia> @atomic_swap! a.x 2+2 # replace field x of a with 4, with sequential consistency
598+ 1
599+
600+ julia> @atomic a.x # fetch field x of a, with sequential consistency
601+ 4
602+ ```
603+ """
604+ macro atomic_swap! (order, ex, val)
605+ order isa QuoteNode || (order = esc (order))
606+ return make_atomic_swap! (order, ex, val)
607+ end
608+ macro atomic_swap! (ex, val)
609+ return make_atomic_swap! (QuoteNode (:sequentially_consistent ), ex, val)
610+ end
611+ function make_atomic_swap! (order, ex, val)
612+ @nospecialize
613+ is_expr (ex, :., 2 ) || error (" @atomic_swap! expression missing field access" )
614+ l, r, val = esc (ex. args[1 ]), esc (ex. args[2 ]), esc (val)
615+ return :(swapproperty! ($ l, $ r, $ val, $ order))
616+ end
617+
618+
598619"""
599620 @atomic_replace! a.b.x expected => desired
600621 @atomic_replace! :sequentially_consistent a.b.x expected => desired
@@ -646,7 +667,7 @@ macro atomic_replace!(ex, old_new)
646667end
647668function make_atomic_replace! (success_order, fail_order, ex, old_new)
648669 @nospecialize
649- is_expr (ex, :., 2 ) || error (" @atomic replace expression missing field access" )
670+ is_expr (ex, :., 2 ) || error (" @atomic_replace! expression missing field access" )
650671 ll, lr = esc (ex. args[1 ]), esc (ex. args[2 ])
651672 if is_expr (old_new, :call , 3 ) && old_new. args[1 ] === :(=> )
652673 exp, rep = esc (old_new. args[2 ]), esc (old_new. args[3 ])
0 commit comments