blob: f884e76935b095ccdfe7eaab554fc6721cb67bad [file] [log] [blame]
------------------------------------------------------------------------------
-- --
-- GNAT COMPILER COMPONENTS --
-- --
-- S Y S T E M . S H A R E D _ S T O R A G E --
-- --
-- S p e c --
-- --
-- $Revision: 1.1 $ --
-- --
-- Copyright (C) 1998-2001 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/persistent storage required for
-- full implementation of variables in Shared_Passive packages, more
-- precisely variables whose enclosing dynamic scope is a shared
-- passive package. This implementation is specific to GNAT and GLADE
-- provides a more general implementation not dedicated to file
-- storage.
-- --------------------------
-- -- Shared Storage 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_Storage are
-- then used to ensure that the values in these separate copies are
-- properly synchronized with the state of the overall system.
-- In the GNAT implementation, 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 storage for each variable. The name is the fully
-- qualified name of the variable with all letters forced to lower
-- case. For example, the variable Var in the shared passive package
-- Pkg results in the storage name pkg.var.
-- If the storage 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 storages need not (and do not)
-- reflect the initial state. There is therefore no issue of
-- synchronizing initialization and read/write access.
-- -----------------------
-- -- 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_Var_ROpen ("pkg.var");
-- if S /= null then
-- typ'Read (S);
-- Shared_Var_Close (S);
-- end if;
-- end varR;
-- The routine Shared_Var_ROpen in package System.Shared_Storage
-- either returns null if the storage does not exist, or otherwise a
-- Stream_Access value that references the corresponding shared
-- storage, 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 storage does not exist, or reads
-- the current value from the shared storage.
-- In addition, for each shared variable, var, an assignment routine
-- is created whose body has the following form (again for Pkg.Var)
-- procedure VarA is
-- S : Ada.Streams.Stream_IO.Stream_Access;
-- begin
-- S := Shared_Var_WOpen ("pkg.var");
-- typ'Write (S, var);
-- Shared_Var_Close (S);
-- end VarA;
-- The routine Shared_Var_WOpen in package System.Shared_Storage
-- returns a Stream_Access value that references the corresponding
-- shared storage, 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 storage.
-- Note that there is no general synchronization for these storage
-- 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.
-- The routine Shared_Var_Close is called to indicate the end of a
-- read/write operations. This can be useful even in the context of
-- the GNAT implementation. For instance, when a read operation and a
-- write operation occur at the same time on the same partition, as
-- the same stream is used simultaneously, both operations can
-- terminate abruptly by raising exception Mode_Error because the
-- stream has been opened in read mode and then in write mode and at
-- least used by the read opartion. To avoid this unexpected
-- behaviour, we introduce a synchronization at the partition level.
-- 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 --
-- ----------------------------------------------------------------
-- In the context of GNAT, during the execution of a protected
-- subprogram call, access is locked out using a locking mechanism
-- per protected object, as provided by the GNAT.Lock_Files
-- capability in the specific case of GNAT. 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 storage. 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
-- storages 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_Storage is
package SIO renames Ada.Streams.Stream_IO;
function Shared_Var_ROpen (Var : String) return SIO.Stream_Access;
-- As described above, this routine returns null if the
-- corresponding shared storage does not exist, and otherwise, if
-- the storage does exist, a Stream_Access value that references
-- the shared storage, ready to read the current value.
function Shared_Var_WOpen (Var : String) return SIO.Stream_Access;
-- As described above, this routine returns a Stream_Access value
-- that references the shared storage, ready to write the new
-- value. The storage is created by this call if it does not
-- already exist.
procedure Shared_Var_Close (Var : in SIO.Stream_Access);
-- This routine signals the end of a read/assign operation. It can
-- be useful to embrace a read/write operation between a call to
-- open and a call to close which protect the whole operation.
-- Otherwise, two simultaneous operations can result in the
-- raising of exception Data_Error by setting the access mode of
-- the variable in an incorrect mode.
procedure Shared_Var_Lock (Var : String);
-- This procedure claims the shared storage 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_Var_Unlock (Var : String);
-- This procedure releases the shared storage 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_Storage;