@@ -461,14 +461,8 @@ julia> mutable struct Atomic{T}; @atomic x::T; end
461
461
julia> a = Atomic(1)
462
462
Atomic{Int64}(1)
463
463
464
- julia> @atomic :sequentially_consistent a.x = 2 # set field x of a, with sequential consistency
465
- 2
466
-
467
464
julia> @atomic a.x # fetch field x of a, with sequential consistency
468
- 2
469
-
470
- julia> @atomic a.x += 1 # increment field x of a, with sequential consistency
471
- 3
465
+ 1
472
466
```
473
467
"""
474
468
macro atomic (ex)
@@ -483,47 +477,33 @@ macro atomic(order, ex)
483
477
end
484
478
function make_atomic (order, ex)
485
479
@nospecialize
486
- if ex isa Expr
487
- if ex. head === :.
488
- l, r = esc (ex. args[1 ]), esc (ex. args[2 ])
489
- return :(getproperty ($ l, $ r, $ order))
490
- elseif ex. head === :(= )
491
- l, r = ex. args[1 ], ex. args[2 ]
492
- if is_expr (l, :., 2 )
493
- ll, lr = esc (l. args[1 ]), esc (l. args[2 ])
494
- return :(setproperty! ($ ll, $ lr, $ r, $ order))
495
- end
496
- end
497
- if length (ex. args) == 2
498
- if ex. head === :(+= )
499
- op = :+
500
- elseif ex. head === :(-= )
501
- op = :-
502
- elseif @isdefined string
503
- shead = string (ex. head)
504
- if endswith (shead, ' =' )
505
- op = Symbol (shead[1 : prevind (shead, end )])
506
- end
507
- end
508
- if @isdefined (op)
509
- l, r = ex. args[1 ], esc (ex. args[2 ])
510
- is_expr (l, :.) || error (" @atomic modify expression missing field access" )
511
- ll, lr, op = esc (l. args[1 ]), esc (l. args[2 ]), esc (op)
512
- return :(modifyproperty! ($ ll, $ lr, $ op, $ r, $ order)[2 ])
513
- end
514
- end
480
+ if isexpr (ex, :., 2 )
481
+ l, r = esc (ex. args[1 ]), esc (ex. args[2 ])
482
+ return :(getproperty ($ l, $ r, $ order))
515
483
end
516
484
error (" could not parse @atomic expression $ex " )
517
485
end
518
486
519
487
520
488
"""
521
- @atomic! a.b.x max new()
522
- @atomic! a.b.x + new()
523
- @atomic! max(a.b.x, new())
524
- @atomic! :acquire_release max(a.b.x, new())
525
- @atomic! :acquire_release a.b.x + new()
526
- @atomic! :acquire_release a.b.x max new()
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
493
+
494
+ Perform the store operation expressed on the right atomically and return the
495
+ new value.
496
+
497
+ With `=`, this operation translates to a `setproperty!(a.b, :x, new)` call.
498
+ With any operator also, this operation translates to a `modifyproperty!(a.b,
499
+ :x, +, addend)[2]` call.
500
+
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
527
507
528
508
Perform the binary operation expressed on the right atomically. Store the
529
509
result into the field in the first argument and return the values `(old, new)`.
@@ -538,14 +518,20 @@ julia> mutable struct Atomic{T}; @atomic x::T; end
538
518
julia> a = Atomic(1)
539
519
Atomic{Int64}(1)
540
520
521
+ julia> @atomic! :sequentially_consistent a.x = 2 # set field x of a, with sequential consistency
522
+ 2
523
+
524
+ julia> @atomic! a.x += 1 # increment field x of a, with sequential consistency
525
+ 3
526
+
541
527
julia> @atomic! a.x + 1 # increment field x of a, with sequential consistency
542
- (1, 2 )
528
+ (3, 4 )
543
529
544
530
julia> @atomic a.x # fetch field x of a, with sequential consistency
545
- 2
531
+ 4
546
532
547
533
julia> @atomic! max(a.x, 10) # change field x of a to the max value, with sequential consistency
548
- (2 , 10)
534
+ (4 , 10)
549
535
550
536
julia> @atomic! a.x max 5 # again change field x of a to the max value, with sequential consistency
551
537
(10, 10)
@@ -567,8 +553,36 @@ macro atomic!(ex)
567
553
end
568
554
function make_atomic! (order, ex)
569
555
@nospecialize
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 ])
556
+ if ex isa Expr
557
+ if isexpr (ex, :call , 3 )
558
+ return make_atomic! (order, ex. args[2 ], ex. args[1 ], ex. args[3 ])
559
+ elseif ex. head === :(= )
560
+ l, r = ex. args[1 ], ex. args[2 ]
561
+ if is_expr (l, :., 2 )
562
+ ll, lr = esc (l. args[1 ]), esc (l. args[2 ])
563
+ return :(setproperty! ($ ll, $ lr, $ r, $ order))
564
+ end
565
+ end
566
+ if length (ex. args) == 2
567
+ if ex. head === :(+= )
568
+ op = :+
569
+ elseif ex. head === :(-= )
570
+ op = :-
571
+ elseif @isdefined string
572
+ shead = string (ex. head)
573
+ if endswith (shead, ' =' )
574
+ op = Symbol (shead[1 : prevind (shead, end )])
575
+ end
576
+ end
577
+ 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 ])
582
+ end
583
+ end
584
+ end
585
+ error (" could not parse @atomic! modify expression $ex " )
572
586
end
573
587
function make_atomic! (order, a1, op, a2)
574
588
@nospecialize
@@ -674,6 +688,6 @@ function make_atomic_replace!(success_order, fail_order, ex, old_new)
674
688
return :(replaceproperty! ($ ll, $ lr, $ exp, $ rep, $ success_order, $ fail_order))
675
689
else
676
690
old_new = esc (old_new)
677
- return :(local old_new = $ old_new :: Pair ; replaceproperty! ($ ll, $ lr, old_new[ 1 ], old_new[ 2 ] , $ success_order, $ fail_order))
691
+ return :(replaceproperty! ($ ll, $ lr, $ old_new:: Pair... , $ success_order, $ fail_order))
678
692
end
679
693
end
0 commit comments