Fuzion Logo
fuzion-lang.dev — The Fuzion Language Portal
JavaScript seems to be disabled. Functionality is limited.

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