CVS difference for ai12s/ai12-0234-1.txt

Differences between 1.10 and version 1.11
Log of other versions for file ai12s/ai12-0234-1.txt

--- ai12s/ai12-0234-1.txt	2019/03/06 03:20:41	1.10
+++ ai12s/ai12-0234-1.txt	2019/03/08 02:27:46	1.11
@@ -1,4 +1,4 @@
-!standard A.19(0)                                      18-06-06  AI12-0234-1/03
+!standard A.19(0)                                      19-03-07  AI12-0234-1/04
 !class Amendment 17-06-09
 !status work item 17-06-09
 !status received 17-05-19
@@ -16,37 +16,44 @@
 detriment to performance, and reduce opportunities for parallelism.
 
 Lock-free data structures guarantee system-wide progress, while wait-free
-data structures, in addition to being lock-free, also guarantee per-thread progresss.
+data structures, in addition to being lock-free, also guarantee per-thread
+progress.
 
 Lock-free data structures can also be used to improve performance by increasing
-the amount of time spent executing in parallel since access to the data structure
-does not need to be serialised.
+the amount of time spent executing in parallel since access to the data
+structure does not need to be serialised.
 
-If one wanted to construct such a structure in Ada, one might use Atomic objects.
-But Ada does not provide any compare-and-swap operation (or other read-write locked
-operations, like atomic increment). The RM has Implementation Advice that package
-Machine_Code include such operations - C.1(11-12), but that is the absolute
-opposite of a portable operation. One could write such a library in another
-language such as C and call that library from Ada, but then that involves at
-least one subprogram call in addition to a single instruction insertion,
-which is significantly higher overhead than what might be desired, and having
-to rely on the existence of other languages for a given target is also undesirable
-and less portable. Should Ada provide some simple primitives
-that can be mapped to hardware instructions that allow such updates to perform
-as expected? -- Yes
+If one wanted to construct such a structure in Ada, one might use Atomic
+objects. But Ada does not provide any compare-and-swap operation (or other
+read-write locked operations, like atomic increment). The RM has Implementation
+Advice that package Machine_Code include such operations - C.1(11-12), but that
+is the absolute opposite of a portable operation. One could write such a library
+in another language such as C and call that library from Ada, but then that
+involves at least one subprogram call in addition to a single instruction
+insertion, which is significantly higher overhead than what might be desired,
+and having to rely on the existence of other languages for a given target is
+also undesirable and less portable.
+
+Compare-and-swap in particular is likely one of the most important
+capabilities needed for atomic operations. This is because
+compare-and-swap instructions can be used as a building block
+to create all the other atomic operations one might want to use.
+Ada should provide a way to more portably insert
+Compare-And-Swap instructions into an application.
 
 !proposal
 
-The solution is to provide a set of standard library calls that map to commonly
-available atomic hardware instructions such as compare and swap,
-test and set, and atomic increment. These subprograms are to be intrinsic calls,
-and the generic libraries will assert an error if a particular target platform
-does not support such atomic operations.
+The solution is to provide a standard library call that maps to commonly
+available atomic hardware instructions that perform compare and swap
+operations. This subprogram is to be an intrinsic call. If the target
+architecture does not support compare-and-swap instructions, then
+the subprogram is implemented to produce the same result using
+proper synchronization for concurrent access.
 
-The libraries are generic libraries in order to support operations on discrete
+The library is a generic function in order to support operations on
 types of different sizes, and we require that the actual types for the generics
 be  atomic types, so that Ada's semantics of atomic types can be associated
-with these primitive operations.
+with this primitive operation.
 
 This proposal depends on the ability to specify the Atomic aspect for a generic
 formal type (AI12-0282-1). This is needed to ensure that the actual types used
@@ -57,353 +64,131 @@
 A.19 Atomic Operations
 
 This clause presents the specifications of the package Atomic_Operations and
-several child packages, which provide facilities for atomically manipulating discrete
-types, and for creating lock-free data types.
+its child packages, which provide facilities for manipulating
+object of atomic types and for creating lock-free data types.
+The subprograms of these packages are Intrinsic subprograms (see 6.3.1)
+in order to provide convenient access to machine operations that can
+provide these capabilities if they are available in the target environment.
 
 A.19.1  The Package Atomic_Operations
 
-The package Atomic_Operations is the root of the atomic operations subsystem.
+The library package Ada.Atomic_Operations is the parent of a set of child units
+that provide facilities for manipulating objects of atomic types.
 
 Static Semantics
 
-The library package Atomic_Operations has the following declaration:
+The following language-defined library package exists:
 
-with System.Storage_Elements;
-
-package Ada.Atomic_Operations is
-
-   pragma Pure;
-
-   type Test_And_Set_Type is mod System.Storage_Elements.Storage_Element'Modulus
-      with Atomic, Size => System.Storage_Elements.Storage_Element'Size;
-
-   --  Or alternatively we could go with
-   --
-   --  type Test_And_Set_Type is new System.Storage_Elements.Storage_Element
-   --    with Atomic, Size => System.Storage_Elements.Storage_Element'Size;
-
-   Atomic_Support_Error : exception;
-
-   function Atomic_Test_And_Set (Item : aliased in out Test_And_Set_Type) return Boolean
-     with Convention => Intrinsic
-     with Post => Item /= 0;
-
-   procedure Atomic_Clear (Item : aliased in out Test_And_Set_Type)
-     with Convention => Intrinsic
-     with Post => Item = 0;
-
-   procedure Atomic_Thread_Fence
-     with Convention => Intrinsic;
-
-   procedure Atomic_Signal_Fence
-     with Convention => Intrinsic;
-
+package Ada.Atomic_Operations
+   with Pure, Nonblocking is
 end Ada.Atomic_Operations;
-
-
-Test_And_Set_Type represents the resulting state of a call to Atomic_Test_And_Set.
-
-Atomic_Support_Error is raised during elaboration of a child package of
-Ada.Atomic_Operations if the implementation cannot map the instantiation to
-atomic operations of the target system.
-
-function Atomic_Test_And_Set (Item : aliased in out Test_And_Set_Type) return Boolean
-  with Convention => Intrinsic;
 
-Performs an atomic test-and-set operation on Item. Item is set to some
-implementation defined "set" value and the return value is True
-if and only if the previous contents were "set".
+Ada.Atomic_Operations serves as the parent of other language-defined library
+units that manipulate atomic objects; its declaration is empty.
 
-procedure Atomic_Clear (Item : aliased in out Test_And_Set_Type)
-  with Convention => Intrinsic;
+A.19.2  The Generic Function Atomic_Operations.Atomic_Compare_And_Exchange
 
-Performs an atomic clear operation on Item. After the operation, Item
-contains 0. This call should be used in conjunction with Atomic_Test_And_Set.
+The language-defined generic function
+Atomic_Operations.Atomic_Compare_And_Exchange provides an operation to
+atomically compare the value of two atomic objects, and update the first atomic
+object with a desired value if both objects were found to be equal, or otherwise
+update the second object with the value of the first object.
 
-procedure Atomic_Thread_Fence
-   with Convention => Intrinsic;
-
-This procedure acts as a synchronization fence between threads.
-
-procedure Atomic_Signal_Fence
-   with Convention => Intrinsic;
-
-This procedure acts as a synchronization fence between a thread and
-signal handlers in the same thead.
-
-A.19.2  The Generic Package Atomic_Operations.Storage
-
-The language-defined generic package Atomic_Operations.Storage provides a set of
-operations for atomically loading, storing, and comparing storage associated with
-discrete types.
-
-generic
-   type Atomic_Type is (<>) with Atomic;
-package Ada.Atomic_Operations.Storage is
-
-   pragma Pure;
-
-   function Atomic_Load (From : aliased Atomic_Type) return Atomic_Type
-    with Convention => Intrinsic;
-
-   procedure Atomic_Store (Into  : aliased in out Atomic_Type;
-                           Value : Atomic_Type)
-    with Convention => Intrinsic;
-
-   function Atomic_Exchange (Item  : aliased in out Atomic_Type;
-                             Value : Atomic_Type) return Atomic_Type
-    with Convention => Intrinsic;
-
-   function Atomic_Compare_And_Exchange (Item     : aliased in out Atomic_Type;
-                                         Expected : aliased in out Atomic_Type;
-                                         Desired  : Atomic_Type;
-                                         Weak     : Boolean) return Boolean
-    with Convention => Intrinsic;
-
-   function Atomic_Always_Lock_Free return Boolean
-   with Convention => Intrinsic;
-
-   function Atomic_Always_Lock_Free (Item : aliased Atomic_Type) return Boolean
-     with Convention => Intrinsic;
-
-   function Atomic_Is_Lock_Free (Item : aliased Atomic_Type) return Boolean;
-
-end Ada.Atomic_Operations.Storage;
-
-function Atomic_Load (From : aliased Atomic_Type) return Atomic_Type
-with Convention => Intrinsic;
-
-Returns the value of From.
-
-procedure Atomic_Store (Into  : aliased in out Atomic_Type;
-                        Value : Atomic_Type)
-with Convention => Intrinsic;
-
-Writes Value into Into.
-
-function Atomic_Exchange (Item  : aliased in out Atomic_Type;
-                          Value : Atomic_Type) return Atomic_Type
-with Convention => Intrinsic;
-
-Writes Value into Item, and returns the previous value of Item.
-
-function Atomic_Compare_And_Exchange (Item     : aliased in out Atomic_Type;
-                                      Expected : aliased in out Atomic_Type;
-                                      Desired  : Atomic_Type;
-                                      Weak     : Boolean) return Boolean
-with Convention => Intrinsic;
-
-Compares the value of Item with the value of Expected. If equal, the
-operation is a read-modify-write operation that writes Desired into
-Item. If they are not equal, the operation is a read and the current
-contents of Item are written into Expected.
-Weak is True for weak compare_and_exchange, which may fail spuriously,
-and false for the strong variation, which never fails spuriously. Many
-targets only offer the strong variation and ignore the parameter.
-When in doubt, use the strong variation.
-If Desired is written into Item then True is returned. Otherwise, False is returned.
-
-Returns True if objects always generate lock-free atomic instructions for the
-target architecture.
-
-function Atomic_Always_Lock_Free (Item : aliased Atomic_Type) return Boolean
-with Convention => Intrinsic;
+Static Semantics
 
-Returns True if objects always generate lock-free atomic instructions for the
-target architecture. Item may be used ot determine alignment. The compiler may
-also ignore this parameter.
-
-function Atomic_Is_Lock_Free (Item : aliased Atomic_Type) return Boolean;
-Returns True if objects always generate lock-free atomic instructions
-for the target architecture. Item may be used ot determine alignment.
-The compiler may also ignore this parameter.
-
-A.19.3  The Generic Package Atomic_Operations.Signed_Arithmetic
-
-The language-defined generic package Atomic_Operations.Signed_Arithmetic
-provides a set of operations for adding and subtracting values atomically to
-signed integer types.
+The library function Ada.Atomic_Operations.Atomic_Compare_And_Exchange has the
+following declaration:
 
 generic
-   type Atomic_Type is range <> with Atomic;
-package Ada.Atomic_Operations.Signed_Arithmetic is
-
-   pragma Pure;
-
-   function Atomic_Add_And_Fetch (Item  : aliased in out Atomic_Type;
-                                  Value : Atomic_Type) return Atomic_Type
-    with Convention => Intrinsic;
+   type Atomic_Type is private with Atomic;
+function Ada.Atomic_Operations.Atomic_Compare_And_Exchange
+     (Item     : aliased in out Atomic_Type;
+      Expected : aliased in out Atomic_Type;
+      Desired  :                Atomic_Type) return Boolean
+   with Nonblocking, Global => null, Convention => Intrinsic;
+
+Compares the value denoted by Item with the value denoted by Expected.
+If equal, the operation is a read-modify-write operation that writes
+the value denoted by Desired into Item. If they are not equal, the operation
+is a read and the value denoted by Item is written into Expected.
+If Desired is written into Item then True is returned. Otherwise, False is
+returned.
+
+A.19.3  The Generic Function Atomic_Operations.Is_Lock_Free
+
+A call to a subprogram is said to be *lock-free* if the subprogram
+is guaranteed to return from the call while keeping the processor of
+logical thread of control busy for the duration of the call.
+
+The language-defined generic function Ada.Atomic_Operations.Is_Lock_Free
+provides an operation to test whether the operations of the other child units
+of Atomic_Operations are lock-free operations when applied to a specific
+object of an atomic type.
 
-   function Atomic_Subtract_And_Fetch (Item  : aliased in out Atomic_Type;
-                                       Value : Atomic_Type) return Atomic_Type
-    with Convention => Intrinsic;
-
-   function Atomic_Fetch_And_Add (Item  : aliased in out Atomic_Type;
-                                  Value : Atomic_Type) return Atomic_Type
-    with Convention => Intrinsic;
-
-   function Atomic_Fetch_And_Subtract (Item  : not null access Atomic_Type;
-                                       Value : Atomic_Type) return Atomic_Type
-    with Convention => Intrinsic;
-
-end Ada.Atomic_Operations.Signed_Arithmetic;
-
-The following functions perform the operation suggested by the name,
-and return the result of the operation.
-
-i.e. Item := Item op Value; return Item;
-
-
-function Atomic_Add_And_Fetch (Item  : aliased in out Atomic_Type;
-                               Value : Atomic_Type) return Atomic_Type
-with Intrinsic;
-
-function Atomic_Subtract_And_Fetch (Item  : aliased in out Atomic_Type;
-                                    Value : Atomic_Type) return Atomic_Type
-with Intrinsic;
-
-The following functions perform the operation suggested by the name,
-and return the value that had previously been in Item.
-
-i.e.  Tmp := Item; Item := Item op Value; return Tmp;
-
-function Atomic_Fetch_And_Add (Item  : aliased in out Atomic_Type;
-                               Value : Atomic_Type) return Atomic_Type;
-
-function Atomic_Fetch_And_Subtract (Item  : aliased in out Atomic_Type;
-                                    Value : Atomic_Type) return Atomic_Type;
-
-A.19.4  The Generic Package Atomic_Operations.Modular_Arithmetic
+Static Semantics
 
-The language-defined generic package Atomic_Operations.Modular_Arithmetic
-provides a set of operations for atomically adding, subtracting, and
-bitwise manipulation, for modular integer types.
+The library function Ada.Atomic_Operations.Is_Lock_Free has the
+following declaration:
 
 generic
-   type Atomic_Type is mod <> with Atomic;
-package Ada.Atomic_Operations.Modular_Arithmetic is
-
-   pragma Pure;
-
-   function Atomic_Add_And_Fetch (Item  : aliased in out Atomic_Type;
-                                  Value : Atomic_Type) return Atomic_Type
-    with Convention => Intrinsic;
-
-   function Atomic_Subtract_And_Fetch (Item  : aliased in out Atomic_Type;
-                                       Value : Atomic_Type) return Atomic_Type
-    with Convention => Intrinsic;
-
-   function Atomic_Bitwise_And_And_Fetch (Item  : aliased in out Atomic_Type;
-                                          Value : Atomic_Type) return Atomic_Type
-    with Convention => Intrinsic;
+   type Atomic_Type is private; -- with Atomic;
+function Ada.Atomic_Operations.Is_Lock_Free
+  (Item : aliased Atomic_Type) return Boolean
+  with Nonblocking, Global => null, Convention => Intrinsic
 
-   function Atomic_Bitwise_Or_And_Fetch (Item  : aliased in out Atomic_Type;
-                                         Value : Atomic_Type) return Atomic_Type
-    with Intrinsic;
-
-   function Atomic_Xor_And_Fetch (Item  : aliased in out Atomic_Type;
-                                  Value : Atomic_Type) return Atomic_Type
-    with Intrinsic;
-
-   function Atomic_Nand_And_Fetch (Item  : aliased in out Atomic_Type;
-                                   Value : Atomic_Type) return Atomic_Type
-    with Intrinsic;
-
-   function Atomic_Fetch_And_Add (Item  : aliased in out Atomic_Type;
-                                  Value : Atomic_Type) return Atomic_Type
-    with Intrinsic;
-
-   function Atomic_Fetch_And_Subtract (Item  : aliased in out Atomic_Type;
-                                       Value : Atomic_Type) return Atomic_Type
-    with Intrinsic;
-
-   function Atomic_Fetch_And_Bitwise_And (Item  : aliased in out Atomic_Type;
-                                          Value : Atomic_Type) return Atomic_Type
-    with Intrinsic;
-
-   function Atomic_Fetch_And_Bitwise_Or (Item  : aliased in out Atomic_Type;
-                                         Value : Atomic_Type) return Atomic_Type
-    with Intrinsic;
-
-   function Atomic_Fetch_And_Xor (Item  : aliased in out Atomic_Type;
-                                  Value : Atomic_Type) return Atomic_Type
-    with Intrinsic;
-
-   function Atomic_Fetch_And_Nand (Item  : aliased in out Atomic_Type;
-                                   Value : Atomic_Type) return Atomic_Type
-    with Intrinsic;
-
-end Ada.Atomic_Operations.Modular_Arithmetic;
-
-The following functions perform the operation suggested by the name,
-and return the result of the operation.
-  i.e. Item := Item op Value; return Item;
-
-   function Atomic_Add_And_Fetch (Item  : aliased in out Atomic_Type;
-                                  Value : Atomic_Type) return Atomic_Type
-    with Convention => Intrinsic;
-
-   function Atomic_Subtract_And_Fetch (Item  : aliased in out Atomic_Type;
-                                       Value : Atomic_Type) return Atomic_Type
-    with Convention => Intrinsic;
-
-   function Atomic_Bitwise_And_And_Fetch (Item  : aliased in out Atomic_Type;
-                                          Value : Atomic_Type) return Atomic_Type
-    with Convention => Intrinsic;
-
-   function Atomic_Bitwise_Or_And_Fetch (Item  : aliased in out Atomic_Type;
-                                         Value : Atomic_Type) return Atomic_Type
-    with Intrinsic;
-
-   function Atomic_Xor_And_Fetch (Item  : aliased in out Atomic_Type;
-                                  Value : Atomic_Type) return Atomic_Type
-    with Intrinsic;
-
-   function Atomic_Nand_And_Fetch (Item  : aliased in out Atomic_Type;
-                                   Value : Atomic_Type) return Atomic_Type
-    with Intrinsic;
-
-The following functions perform the operation suggested by the name,
-and return the value that had previously been in Item.
-  i.e.  Tmp := Item; Item := Item op Value; return Tmp;
-
-   function Atomic_Fetch_And_Add (Item  : aliased in out Atomic_Type;
-                                  Value : Atomic_Type) return Atomic_Type
-    with Intrinsic;
-
-   function Atomic_Fetch_And_Subtract (Item  : aliased in out Atomic_Type;
-                                       Value : Atomic_Type) return Atomic_Type
-    with Intrinsic;
-
-   function Atomic_Fetch_And_Bitwise_And (Item  : aliased in out Atomic_Type;
-                                          Value : Atomic_Type) return Atomic_Type
-    with Intrinsic;
+function Is_Lock_Free (Item : aliased Atomic_Type) return Boolean
+with Convention => Intrinsic;
 
-   function Atomic_Fetch_And_Bitwise_Or (Item  : aliased in out Atomic_Type;
-                                         Value : Atomic_Type) return Atomic_Type
-    with Intrinsic;
+Returns true if operations defined in other child units of Atomic_Operations
+are lock-free when applied to the object denoted by Item.
 
-   function Atomic_Fetch_And_Xor (Item  : aliased in out Atomic_Type;
-                                  Value : Atomic_Type) return Atomic_Type
-    with Intrinsic;
+NOTES
+Some target environments do not always support lock-free machine operations
+for objects of a certain size.
+For example, a 64 bit target environment might support atomic lock-free
+operations on objects that are 64 bits in size, but when executed on a
+32 bit target environment, such machine operations may not be available,
+and the calls to Atomic_Compare_And_Exchange would need to switch over
+to a locking implementation.
 
-   function Atomic_Fetch_And_Nand (Item  : aliased in out Atomic_Type;
-                                   Value : Atomic_Type) return Atomic_Type
-    with Intrinsic;
+Similarly, the alignment of an object may determine whether lock free
+operations may be applied.
 
 !discussion
 
-It seems that the solution will need to be generic, in order to work with different
+The solution needs to be generic, in order to work with different
 atomic types. For that to make sense, it is necessary to allow aspect Atomic
-to be given on a formal type, in order to require any actual type is indeed
+to be given on the formal type, in order to require any actual type is indeed
 atomic. The alternative of just saying that if the type is not atomic, then the
 operation isn't either, seems error-prone.
 
 Many lock free algorithms involve atomic primitives such as compare and swap
 instructions or load and store instuctions. Most target platforms provide some
-form of instruction of these category. A limitation of these instructions is
-that they typically can only be applied to a single elementary integer type of
-1, 2, 4, or 8 bytes in size.
+form of machine instructions in this category.
+
+However, most target architectures have limits on the size of objects that
+can be mapped to hardware machine instructions. Furthermore, some target
+architectures have sub-architectures that do not always provide such
+machine instructions. For example, an executable compiled for one target
+might support 64 bit atomic instructions, but only 32 bit atomic
+instructions on older versions of the same target family.  It is
+desirable that such machine instructions be used when they are available,
+but that the software should still work and provide the same results when
+executing on another target that does not provide such instructions.
+
+Similarly, the alignment of the object can sometimes determine whether
+lock-free instructions may be used on some architectures.
+
+To allow the programmer to query the implementation to determine if
+the operations declared in child units of Ada.Atomic_Operations can be
+executed as lock-free calls, a generic function is provided: Is_Lock_Free.
+
+The gcc intrinsic libraries also provide a call to determine if the
+target environment always provides lock-free versions of the calls, for
+a given size, and alignment. We considered whether we should similarly
+define a call Alway_Lock_Free, with similar semantics, but decided that
+there would not be enough need to provide such a call. We could add
+such a call later, if the need arises.
 
 The approach taken to improving support for lock free data structures is to
 provide a set of libraries of low level atomic primitives similar to the library
@@ -415,11 +200,15 @@
 and the order seen by all threads is the same. Due to the higher level of
 synchronisation, this is also the most inefficient memory order, but it is the
 default memory order because it is the safest, and produces the least number
-of surprising results. Moving towards lower level of synchronisation,there are
-are memory orders called Acquire and Release, where essentially the synchronisation
+of surprising results.
+
+Moving towards lower level of synchronisation, there are memory orders called
+Acquire and Release, where essentially the synchronisation
 is limited to the threads involved in the atomic operations for a particular
-shared variable.  Relaxing the synchronisation even further is a memory order
-called Relaxed, where this synchronisation is not present. There are guarantees
+shared variable.
+
+Relaxing the synchronisation even further is a memory order called Relaxed,
+where this synchronisation is not present. There are guarantees
 that a given thread will not see older values of variables once it has seen an
 update to a variable, but that is about the limit of the guarantees, other than
 that updates are seen in some sort of time bounded manner. Programmers using this
@@ -438,8 +227,8 @@
 which is both safer to use, and easier to understand.
 
 The library of intrinsic primitives might be of interest to those wishing to
-implement specific lock free algoriths, particularly if porting those applications
-from other languages.
+implement specific lock free algorithms, particularly if porting those
+applications from other languages.
 
 We considered whether these libraries should be "future proofed" by providing
 an extra parameter for the memory model. The type of that parameter could be
@@ -448,9 +237,33 @@
 there is not likely to be backwards compatibility issues since these are
 intrinsic suprograms. For example, they cannot be passed as actual subprograms
 to generic libraries. Also, if needed, in the future we could add overloaded
-calls to these libraries that accept a memory order parameter, without introducing
-backward compatibility issues.
+calls to these libraries that accept a memory order parameter, without
+introducing backward compatibility issues.
 
+The gcc version of the Atomic_Compare_And_Exchange call has an extra
+boolean parameter, named "Weak". According to the documentation, Weak is
+true for weak compare_and_exchange, which may fail spuriously,
+and false for the strong variation, which never fails spuriously. Many
+targets only offer the strong variation and ignore the parameter.
+The benefit for having the "Weak" version is that it can provide additional
+performance benefits, if the programmer knows how to use it properly.
+For Ada, we thought it was probably not a good idea to provide a parameter
+that can cause "spurious failures", so for now we eliminated that parameter,
+and expect Weak to be passed as False, if needed by the implementation.
+We could add a separate call in the future that exposes the Weak parameter,
+if there is enough need for such a capability.
+
+It was considered whether Atomic_Compare_And_Exchange should be a function
+in a generic package, along with potentially an Atomic_Exchange function.
+
+There are the only two functions that likely could be grouped together
+in the same package. It seemed better to not group these together,
+as they are typically used for different purposes. There also is a third
+function in this category, Test_And_Set, but that would need to be a separate
+child package because it does not need to be generic. It seems like a
+better design to have these as 3 capabilities as separate child units
+for these reasons.
+
 !ASIS
 
 No ASIS effect.
@@ -3372,6 +3185,116 @@
 
 The ptr parameter is expected to be the address of a byte of storage, as only
 the one byte pointed to by that address is modified by the call.
+
+****************************************************************
+
+From: Brad Moore
+Sent: Thursday, March 7, 0219  5:33 PM
+
+Here is an update to AI12-0234-1, Compare-and-swap for atomic objects
+
+This represents a significant change over the last version.
+
+This version only attempts to provide a Compare-And-Swap capability.
+
+The other atomic functions will be split off into another AI.
+
+Compare-and-swap is defined as an intrinsic generic function.
+
+Previously it was a generic package, but the only other function that could
+possibly be grouped into such a package is Atomic_Exchange, because it is the
+only other atomic function defined by gcc that can operate on any atomic types.
+
+Most of the other ones are arithmetic functions, more suitable for a
+generic-formal modular type.
+
+The only other similar function is Test_And_Set, which should not be a generic
+package, as the type it operates on is defined in the package.
+
+So, it seemed to make sense to keep the three capabilities,
+Atomic_Compare_And_Swap, Atomic_Exchange, and Atomic_Test_And_Set in separate
+child units.
+
+For all atomic functions, gcc provides a method to determine if the call is lock
+free or not. That call needs a pointer to the object to be operated on, as well
+as the size of the object.
+
+It seems important to provide the user with the ability to check the
+lock-free-ness of the call, so I provided another generic child function,
+Is_Lock_Free, that can be applied to any atomic type to determine if a specific
+object of that type can be used with all of the operations declared in the child
+units of Atomic_Operations, in a lock-free manner.
+
+This required me defining what lock-free means.
+
+****************************************************************
+
+From: Brad Moore
+Sent: Thursday, March 7, 0219  5:33 PM
+
+Oops, forgot to include the actual AI text.....
+
+Here it is....
+
+[This is version /04 of the AI - Editor.]
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Thursday, March 7, 0219  7:29 PM
+
+...
+> A.19 Atomic Operations
+
+I haven't mentioned this before, but A.19 is Ada.Locales in Ada 2012. It's not a
+very good choice for the number of a new clause. :-)
+
+More seriously...
+
+> The library package Ada.Atomic_Operations is the parent of a set of
+> child units that provide facilities for manipulating objects of atomic
+> types.
+
+Shouldn't this package be a child of System? And in Annex C (since that's where
+Atomic is defined, after all).
+
+So I'd suggest defining this in C.6.1 and later subclauses (since it's related
+to atomic), and have it be a child of System (it's only useful for rather
+low-level programming).
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Thursday, March 7, 0219  8:08 PM
+
+An editorial fix:
+
+> Static Semantics
+>
+> The library function
+> Ada.Atomic_Operations.Atomic_Compare_And_Exchange has the following
+> declaration:
+>
+> generic
+>    type Atomic_Type is private with Atomic; function
+> Ada.Atomic_Operations.Atomic_Compare_And_Exchange
+>      (Item     : aliased in out Atomic_Type;
+>       Expected : aliased in out Atomic_Type;
+>       Desired  :                Atomic_Type) return Boolean
+>    with Nonblocking, Global => null, Convention => Intrinsic;
+>
+> function Atomic_Compare_And_Exchange (Item     : aliased in
+> out Atomic_Type;
+>                                       Expected : aliased in out
+> Atomic_Type;
+>                                       Desired  : Atomic_Type) return
+> Boolean with Nonblocking, Global => null, Convention => Intrinsic;
+
+
+The function specification is given twice here. I deleted the second copy.
+
+There also were a bunch of missing spaces, lines too long, and the like, which I
+fixed and will never speak of again. :-)
 
 ****************************************************************
 

Questions? Ask the ACAA Technical Agent