File : s-shamem.ads


------------------------------------------------------------------------------
--                                                                          --
--                         GNAT COMPILER COMPONENTS                         --
--                                                                          --
--                 S Y S T E M . S H A R E D _ M E M O R Y                  --
--                                                                          --
--                                 S p e c                                  --
--                                                                          --
--                            $Revision: 1.2 $                              --
--                                                                          --
--            Copyright (C) 1998, Free Software Foundation, Inc.            --
--                                                                          --
-- GNAT is free software;  you can  redistribute it  and/or modify it under --
-- terms of the  GNU General Public License as published  by the Free Soft- --
-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
-- OUT 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  distributed with GNAT;  see file COPYING.  If not, write --
-- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
-- MA 02111-1307, USA.                                                      --
--                                                                          --
-- As a special exception,  if other files  instantiate  generics from this --
-- unit, or you link  this unit with other files  to produce an executable, --
-- this  unit  does not  by itself cause  the resulting  executable  to  be --
-- covered  by the  GNU  General  Public  License.  This exception does not --
-- however invalidate  any other reasons why  the executable file  might be --
-- covered by the  GNU Public License.                                      --
--                                                                          --
-- GNAT was originally developed  by the GNAT team at  New York University. --
-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
--                                                                          --
------------------------------------------------------------------------------

--  This package manages the shared/persistant memory required for full
--  implementation of variables in Shared_Passive packages, more precisely
--  variables whose enclosing dynamic scope is a shared passive package.

--  -------------------------
--  -- Shared Memory Model --
--  -------------------------

--  The basic model used is that each partition that references the
--  Shared_Passive package has a local copy of the package data that is
--  initialized in accordance with the declarations of the package in
--  the normal manner. The routines in System.Shared_Memory are then
--  used to ensure that the values in these separate copies are properly
--  synchronized with the state of the overall system.

--  This synchronization is ensured by maintaining a set of files in a
--  designated directory. The directory is designated by setting the
--  environment variable SHARED_MEMORY_DIRECTORY. This variable must be
--  set for all partitions. If the environment variable is not defined,
--  then the current directory is used.

--  There is one file for each variable. The name is the fully qualified
--  name of the variable with all letters forced to lower case. For example,
--  the variable Key_Name in the Shared_Passive package Shared_Data results
--  in the file name shared_data.key_name.

--  If the file does not exist, it indicates that no partition has assigned
--  a new value, so that the initial value is the correct one. This is the
--  critical component of the model. It means that there is no system-wide
--  synchronization required for initializing the package, since the shared
--  memory files need not (and do not) reflect the initial state. There is
--  therefore no issue of synchronizing initialization and read/write accress.

--  If the file does exist, it is a Stream_IO file that contains the most
--  recently assigned value of the variable, as written by the use of the
--  typ'Write stream attribute.

--  -----------------------
--  -- Read/Write Access --
--  -----------------------

--  The approach is as follows:

--    For each shared variable, var, an access routine varR is created whose
--    body has the following form (this example is for Pkg.Var):

--      procedure varR is
--         S : Ada.Streams.Stream_IO.Stream_Access;
--      begin
--         S := Shared_Mem_RFile ("pkg.var");
--         if S /= null then
--            typ'Read (S);
--         end if;
--      end varR;

--    The routine Shared_Mem_RFile in package System.Shared_Memory either
--    returns null if the file does not exist, or otherwise a Stream_Access
--    value that references the corresponding shared memory file, positioned
--    at start of the file, ready to read the current value.

--    Each reference to the shared variable, var, is preceded by a call to
--    the corresponding varR procedure, which either leaves the initial value
--    unchanged if the file does not exist, or reads the current value from
--    the shared memory file.

--    In addition, for each shared variable, var, an assignment routine
--    is created whose body has the following form (again for Pgg.Var)

--      procedure VarA is
--      begin
--         typ'Write (Shared_Mem_WFile ("pkg.var"), var);
--      end VarA;

--    The routine Shared_Mem_WFile is package System.Shared_Memory returns
--    a Stream_Access value that references the corresponding shared memory
--    file, positioned at the start, ready to write the new value.

--    Each assignment to the shared variable, var, is followed by a call
--    to the corresponding varA procedure, which writes the new value to
--    the shared memory file.

--  Note that there is no synchronization for these file read and write
--  operations, since it is assumed that a correctly operating programs
--  will provide appropriate synchronization. In particular, variables
--  can be protected using protected types with no entries.

--  Note: a special circuit allows the use of stream attributes Read and
--  Write for limited types (using the corresponding attribute for the
--  full type), but there are limitations on the data that can be placed
--  in shared passive partitions. See sem_smem.ads/adb for details.

--  ----------------------------------------------------------------
--  -- Handling of Protected Objects in Shared Passive Partitions --
--  ----------------------------------------------------------------

--  During the execution of a protected subprogram call, access is locked
--  out using a global locking mechanism, as provided by the GNAT.Lock_Files
--  capability. This package contains the lock and unlock calls, and the
--  expander generates a call to the lock routine before the protected call
--  and a call to the unlock routine after the protected call.

--  Within the code of the protected subprogram, the access to the protected
--  object itself uses the local copy, without any special synchronization.
--  Since global access is locked out, no other task or partition can attempt
--  to read or write this data as long as the lock is held.

--  The data in the local copy does however need synchronizing with the
--  global values in the shared memory file. This is achieved as follows:

--    The protected object generates a read and assignment routine as
--    described for other shared passive variables. The code for the
--    'Read and 'Write attributes (not normally allowed, but allowed
--    in this special case) simply reads or writes the values of the
--    components in the protected record.

--    The lock call is followed by a call to the shared read routine to
--    synchronize the local copy to contain the proper global value.

--    The unlock call in the procedure case only is preceded by a call
--    to the shared assign routine to synchronize the global shared
--    memory files with the (possibly modified) local copy.

--  These calls to the read and assign routines, as well as the lock
--  and unlock routines, are inserted by the expander (see exp_smem.adb).

with Ada.Streams.Stream_IO;

package System.Shared_Memory is

   package SIO renames Ada.Streams.Stream_IO;

   function Shared_Mem_RFile (Fname : String) return SIO.Stream_Access;
   --  As described above, this routine returns null if the corresponding
   --  shared memory file does not exist, and otherwise, if the file does
   --  exist, a Stream_Access value that references the shared memory file,
   --  positioned to the start, ready to read the current value.

   function Shared_Mem_WFile (Fname : String) return SIO.Stream_Access;
   --  As described above, this routine returns a Stream_Access value that
   --  references the shared memory file, positioned to the start, ready to
   --  write the new value. The file is created by this call if it does not
   --  already exist.

   procedure Shared_Mem_Lock;
   --  This procedure claims the global shared memory lock. It is used for
   --  protected types in shared passive packages. A call to this locking
   --  routine is generated as the first operation in the code for the body
   --  of a protected subprogram, and it busy waits if the lock is busy.

   procedure Shared_Mem_Unlock;
   --  This procedure releases the lock obtaind by a prior call to the
   --  Shared_Mem_Lock procedure, and is to be generated as the last
   --  operation in the body of a protected subprogram.

end System.Shared_Memory;