# Does \`@atomic\` syntax support non-primitive-type fields in a \`mutable struct\`?

**URL:** <https://discourse.julialang.org/t/does-atomic-syntax-support-non-primitive-type-fields-in-a-mutable-struct/116703>\
**Category:** General Usage\
**Tags:** multithreading, atomic\
**Created:** [July 6, 2024, 6:45pm UTC](https://discourse.julialang.org/t/does-atomic-syntax-support-non-primitive-type-fields-in-a-mutable-struct/116703 "2024-07-06T18:45:53Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![frankwswang](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/frankwswang/32/18561_2.png) [@frankwswang](https://discourse.julialang.org/u/frankwswang)\
**Post date:** [July 6, 2024, 6:45pm UTC](https://discourse.julialang.org/t/does-atomic-syntax-support-non-primitive-type-fields-in-a-mutable-struct/116703/1 "2024-07-06T18:45:53Z")

</div>

I was reading the documentation on [per-field atomics](https://docs.julialang.org/en/v1/manual/multi-threading/#man-atomics), and it seems that `@atomic` can be put in front of any type of field (unlike [`Base.Threads.Atomic`](https://docs.julialang.org/en/v1/base/multi-threading/#Base.Threads.Atomic)) as long as the `struct` is mutable. I also tested it with the following code which ran just fine:

```julia
julia> mutable struct TT{T}
           @atomic a::T
       end

julia> t1 = TT(fill(1))
TT{Array{Int64, 0}}(fill(1))

julia> @atomic t1.a = fill(2)
0-dimensional Array{Int64, 0}:
2

```

Does this mean that `@atomic` recursively applies the atomic version of `setproperty!` to the fields of a composite-type field object? Or does it fall back to thread-unsafe version when the field is not of a primitive type?

Thanks!

---

<div class="post-metadata">

**Author:** ![vchuravy](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/vchuravy/32/8_2.png) [@vchuravy](https://discourse.julialang.org/u/vchuravy)\
**Post date:** [July 6, 2024, 7:05pm UTC](https://discourse.julialang.org/t/does-atomic-syntax-support-non-primitive-type-fields-in-a-mutable-struct/116703/2 "2024-07-06T19:05:53Z")

</div>

> Does this mean that @atomic recursively applies the atomic version of setproperty! to the fields of a composite-type field object?

Not quite there is nothing recursive about the use of `@atomic` here.  
`t1.a` contains a reference to an array. `t1.a = b` replaces that reference with another one. Only the update of the reference needs to be atomic.

Now if you have:

```julia
t1 = TT((1,2))

@atomic t1.a = (2, 1)

```

Tuples are stored inline

```julia
julia> sizeof(TT((1,2)))
32

```

and so the question is. How does Julia make sure that this  
is done atomically?

```julia
julia> f(t1, b) = @atomic t1.a = b 
f (generic function with 1 method)

julia> @code_llvm f(TT((1,2)), (2, 3))
; Function Signature: f(Main.TT{Tuple{Int64, Int64}}, Tuple{Int64, Int64})
; @ REPL[4]:1 within `f`
define void @julia_f_1185(ptr noalias nocapture noundef nonnull sret([2 x i64]) align 8 dereferenceable(16) %sret_return, ptr noundef nonnull align 8 dereferenceable(32) %"t1::TT", ptr nocapture noundef nonnull readonly align 8 dereferenceable(16) %"b::Tuple") #0 {
top:
; ┌ @ Base.jl:75 within `setproperty!`
   %.a_ptr = getelementptr inbounds i8, ptr %"t1::TT", i64 16
   call void @jl_lock_value(ptr nonnull %"t1::TT")
   call void @llvm.memcpy.p0.p0.i64(ptr noundef nonnull align 8 dereferenceable(16) %.a_ptr, ptr noundef nonnull align 8 dereferenceable(16) %"b::Tuple", i64 16, i1 false)
   call void @jl_unlock_value(ptr nonnull %"t1::TT")
   call void @llvm.memcpy.p0.p0.i64(ptr noundef nonnull align 8 dereferenceable(16) %sret_return, ptr noundef nonnull align 8 dereferenceable(16) %"b::Tuple", i64 16, i1 false)
   ret void
; └
}

```

So if we can’t use an atomic instruction, because your CPU may not support the use of them, Julia falls back to using locks transparently.

---

<div class="post-metadata">

**Author:** ![frankwswang](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/frankwswang/32/18561_2.png) [@frankwswang](https://discourse.julialang.org/u/frankwswang)\
**Post date:** [July 6, 2024, 7:30pm UTC](https://discourse.julialang.org/t/does-atomic-syntax-support-non-primitive-type-fields-in-a-mutable-struct/116703/3 "2024-07-06T19:30:30Z")

</div>

Cool! Thanks for the explanation!

So I can safely assume that whatever field is annotated by `@atomic` should be thread-safe (regardless the underlying implementation is an optimized atomic operation or a basic lock mechanism), as long as the evaluation of the mutation expression also annotated by `@atomic` does not prompt an error, right?
