concur/atomic.fz
# This file is part of the Fuzion language implementation.
#
# The Fuzion language implementation is free software: you can redistribute it
# and/or modify it under the terms of the GNU General Public License as published
# by the Free Software Foundation, version 3 of the License.
#
# The Fuzion language implementation is distributed in the hope that it will be
# useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
# License for more details.
#
# You should have received a copy of the GNU General Public License along with The
# Fuzion language implementation. If not, see <https://www.gnu.org/licenses/>.
# -----------------------------------------------------------------------
#
# Tokiwa Software GmbH, Germany
#
# Source code of Fuzion standard library feature concur.atomic
#
# Author: Fridtjof Siebert (siebert@tokiwa.software)
#
# -----------------------------------------------------------------------
# atomic -- low-level atomic values
#
# Atomic values can be used for communication between threads in a safe
# way.
#
public atomic (
T type,
v T
)
is
# Does the current system permit racy accesses to the value of type T
# stored in this atomic?
#
# This is typically true for ref values and for small primitive types
# such as `i32`, `f64`, etc. while this is typically not the case for
# more complex types such as `point(x,y i64)`.
#
public racy_accesses_supported bool => intrinsic_constructor
# read the value stored in this atomic and do not care about synchronization.
#
# In case of concurrent write operations, the result that is read may be
# outdated. In the presence of concurrent writes and no synchronization,
# out-of-thin-air values are possible (see https://dl.acm.org/doi/10.1145/3276506).
#
# In general, this is useful only for debugging or monitoring purposes where
# occasionally wrong random results are acceptable.
#
public racy_read ! racy_access
pre
racy_accesses_supported
=>
racy_access_env.replace
v
# write a value in this atomic and do not care about synchronization.
#
# Note that in conjunction with `racy_read`, this might create arbitrary
# out-of-thin-air values.
#
public racy_write(new_value T) ! racy_access
pre
racy_accesses_supported
=>
racy_access_env.replace
set v := new_value
# read this value in a way that is atomic with respect to write operations
# performed by concurrent threads
#
public read T ! atomic_access =>
atomic_access_env.replace
read0
# write this value in a way that is atomic with respect to read and write
# operations performed by concurrent threads
#
public write(new_value T) unit ! atomic_access =>
atomic_access_env.replace
write0 new_value
# Perform a bit-wise comparison of the value contained in this atomic and
# `expected`. In case both values are equal, replace this value with `new_value`.
#
# returns the old value, independent of whether the old value is bit-wise
# equal to `expected` or not.
#
public compare_and_swap(expected, new_value T) T ! atomic_access =>
atomic_access_env.replace
compare_and_swap0 expected new_value
# Perform a bit-wise comparison of the value contained in this atomic and
# `expected`. In case both values are equal, replace this value with `new_value`.
#
# returns true, if successful
#
public compare_and_set(expected, new_value T) bool ! atomic_access =>
atomic_access_env.replace
compare_and_set0 expected new_value
# intrinsic to read this value in a way that is atomic with respect to write
# operations performed by concurrent threads
#
read0 T => intrinsic
# intrinsic to write this value in a way that is atomic with respect to read
# and write operations performed by concurrent threads
#
write0(new_value T) unit => intrinsic
# intrinsic to perform a bit-wise comparison of the value contained in this atomic
# and `expected`. In case both values are equal, replace this value with `new_value`.
#
# returns the old value, independent of whether the old value is bit-wise
# equal to `expected` or not.
#
compare_and_swap0(expected, new_value T) T => intrinsic
# intrinsic to perform a bit-wise comparison of the value contained in this atomic
# and `expected`. In case both values are equal, replace this value with `new_value`.
#
# returns true, if successful
#
compare_and_set0(expected, new_value T) bool => intrinsic_constructor
last changed: 2024-03-07