--------------------------------
-- Ivan Levashew aka OCTAGRAM --
--         Barnaul, 2009-2010 --
--------------------------------

-- Turbo_Private.Generic_Atomic_64, x86 version

-- TODO: nothing has been done           
-- TODO: read the instruction reference  
-- TODO:  cmpxchg8b description          

generic
   type Type_64 is private;
package Turbo_Private.Generic_Atomic_64 is
   pragma Preelaborate;

   type Atomic_Type_64 is limited record
      Item : aliased Type_64;
      pragma Volatile (Item);
   end record;

   for Atomic_Type_64'Size use 64;
   for Atomic_Type_64'Alignment use 8;

   function Get (Source : in Atomic_Type_64)
      return Type_64;
   function Get (Source : not null access Atomic_Type_64)
      return Type_64;
   pragma Inline (Get);

   function Lazy_Get (Source : in Atomic_Type_64)
      return Type_64;
   function Lazy_Get (Source : not null access Atomic_Type_64)
      return Type_64;
   pragma Inline (Lazy_Get);

   function "+" (Source : in Atomic_Type_64)
      return Type_64 renames Lazy_Get;
   function "+" (Source : not null access Atomic_Type_64)
      return Type_64 renames Lazy_Get;

   procedure Set (Target : not null access Atomic_Type_64;
      Item : Type_64);
   procedure Set (Target : in out Atomic_Type_64;
      Item : Type_64);
   pragma Inline (Set);

   procedure Lazy_Set (Target : not null access Atomic_Type_64;
      Item : Type_64);
   procedure Lazy_Set (Target : in out Atomic_Type_64;
      Item : Type_64);
   pragma Inline (Lazy_Set);

   function Create (Item : Type_64) return Atomic_Type_64;
   pragma Inline (Create);

   function "+" (Item : Type_64) return Atomic_Type_64
      renames Create;
   pragma Inline ("+");

   function Lazy_Create (Item : Type_64) return Atomic_Type_64;
   pragma Inline (Lazy_Create);

   function Swap (Target : not null access Atomic_Type_64;
      Item : Type_64) return Type_64;
   pragma Inline (Swap);
   
   function Compare_Swap (Target : not null access Atomic_Type_64;
      Comparand, New_Item : Type_64) return Boolean;
   function Compare_Swap (Target : not null access Atomic_Type_64;
      Comparand, New_Item : Type_64) return Type_64;
   function Compare_Swap (Target : not null access Atomic_Type_64;
      Comparand, New_Item : Type_64; Fetched : not null access Type_64)
      return Boolean;

   function Compare_Swap (Target : not null access Type_64;
      Comparand, New_Item : Type_64) return Type_64; -- internal
   pragma Inline (Compare_Swap);

end Turbo_Private.Generic_Atomic_64;
