123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960(**************************************************************************)(* *)(* OCaml *)(* *)(* Gabriel Scherer, projet Partout, INRIA Paris-Saclay *)(* *)(* Copyright 2020 Institut National de Recherche en Informatique et *)(* en Automatique. *)(* *)(* All rights reserved. This file is distributed under the terms of *)(* the GNU Lesser General Public License version 2.1, with the *)(* special exception on linking described in the file LICENSE. *)(* *)(**************************************************************************)(* CamlinternalAtomic is a dependency of Stdlib, so it is compiled with
-nopervasives. *)external(==):'a->'a->bool="%eq"external(+):int->int->int="%addint"externalignore:'a->unit="%ignore"(* We are not reusing ('a ref) directly to make it easier to reason
about atomicity if we wish to: even in a sequential implementation,
signals and other asynchronous callbacks might break atomicity. *)type'at={mutablev:'a}letmakev={v}letgetr=r.vletsetrv=r.v<-v(* The following functions are set to never be inlined: Flambda is
allowed to move surrounding code inside the critical section,
including allocations. *)let[@inlinenever]exchangerv=(* BEGIN ATOMIC *)letcur=r.vinr.v<-v;(* END ATOMIC *)curlet[@inlinenever]compare_and_setrseenv=(* BEGIN ATOMIC *)letcur=r.vinifcur==seenthen(r.v<-v;(* END ATOMIC *)true)elsefalselet[@inlinenever]fetch_and_addrn=(* BEGIN ATOMIC *)letcur=r.vinr.v<-(cur+n);(* END ATOMIC *)curletincrr=ignore(fetch_and_addr1)letdecrr=ignore(fetch_and_addr(-1))