|
|
DataMuseum.dkPresents historical artifacts from the history of: Rational R1000/400 Tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about Rational R1000/400 Tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T V
Length: 31792 (0x7c30)
Types: TextFile
Names: »V«
└─⟦d10a02448⟧ Bits:30000409 8mm tape, Rational 1000, ENVIRONMENT, D_12_7_3
└─⟦fc9b38f02⟧ »DATA«
└─⟦9b46a407a⟧
└─⟦12c68c704⟧
└─⟦this⟧
└─⟦5f3412b64⟧ Bits:30000745 8mm tape, Rational 1000, ENVIRONMENT 12_6_5 TOOLS
└─⟦91c658230⟧ »DATA«
└─⟦458657fb6⟧
└─⟦220843204⟧
└─⟦this⟧
with Action;
with Directory;
with Io_Exceptions;
with System;
package Pipe is
subtype Action_Id is Action.Id;
Null_Action_Id : constant Action_Id := Action.Null_Id;
subtype Byte is System.Byte;
subtype Byte_String is System.Byte_String;
subtype Object_Id is Directory.Version;
subtype Operate_Status is Integer;
Status_Error : exception renames Io_Exceptions.Status_Error;
Mode_Error : exception renames Io_Exceptions.Mode_Error;
Name_Error : exception renames Io_Exceptions.Name_Error;
Use_Error : exception renames Io_Exceptions.Use_Error;
Device_Error : exception renames Io_Exceptions.Device_Error;
End_Error : exception renames Io_Exceptions.End_Error;
Data_Error : exception renames Io_Exceptions.Data_Error;
Layout_Error : exception renames Io_Exceptions.Layout_Error;
-- Exceptions are raised iff the the comments following the operation
-- indicate that the exception is possible. All other exception
-- propagation is considered a bug in the underlying implementation.
-- A pipe is an object which contains a queue of messages, possibly empty.
-- By opening the object for write, one can do "Write" operations which
-- append messages to the end of the queue. By opening the object for
-- read, one can do "Read" operations which consume messages from the
-- beginning of the queue. Each message is read by exactly one Read
-- operation; thus, in the face of concurrent Reads, each client may see
-- just a subset of the messages that were written to the pipe.
-- It is ok to make concurrent calls to this package. BUT, this does NOT
-- include calls which supply the same Handle; this is considered
-- erroneous. The implementation does not prevent such erroneous behavior;
-- this behavior might cause your Handle to be left inconsistent, but the
-- internal representation of the pipe itself is protected and will remain
-- consistent; thus, other Handle's (including those in other jobs) should
-- still work properly.
function Pipe_Class return Directory.Class;
type Handle is private;
Null_Handle : constant Handle;
-- Contains control information which is pertinent to a particular "open"
-- of a particular pipe. Other control information (about pipes) is kept
-- internally. Logically, a Handle is limited private. Use of multiple
-- copies is considered erroneous. The implementation does not prevent
-- such erroneous behavior. At worst, an erroneous program will be able
-- to Read/Write a pipe which is still open elsewhere, even though other
-- copies of the Handle have been closed; the internal representation of
-- the pipe itself is protected from such erroneous behavior and will
-- remain consistent.
function Max_Buffer_Size return Positive;
-- Measured in bytes. Currently about half the maximum size of a heap.
function Default_Buffer_Size return Positive;
-- Measured in bytes. Currently about 20K bytes.
function Message_Overhead return Natural;
-- Measured in bytes. Currently about 8 bytes. Clients can compute the
-- value of B = n * (c + M), where "c" is the result of this function, "M"
-- is the fixed size of messages supplied to the Write operation, "n" is
-- the desired capacity of the buffer (in messages), and "B" is the
-- resulting requirement for buffer size, in bytes. This function may
-- change between releases of the system.
type Pipe_Open_Mode is (Exclusive_Read, Shared_Read,
Exclusive_Write, Shared_Write, Exclusive);
-- The read modes allow one to use Read operations to consume messages from
-- the beginning of the queue. The write modes allow one to use Write
-- operations to append messages to the end of the queue. The same client
-- can use both Read and Write by opening the pipe multiple times. The
-- compatibility matrix is as follows:
-- Other action compatibility matrix:
-- Current Mode
-- (other actions)
-- ER SR EW SW E
-- ---------------------
-- ER | X X
-- |
-- SR | X X X
-- |
-- Desired EW | X X
-- Mode |
-- SW | X X X
-- |
-- E |
-- ---------------------
-- Absence of an "X" indicates that the desired access will not be granted
-- if any OTHER action (not including requesting action) has the indicated
-- current access. Via Max_Wait, queueing is available when access is
-- denied for this reason.
-- Assuming access is not denied by the above rules, the following matrix
-- indicates the upgrade compatibility rules:
-- Upgrade matrix:
-- Current Access
-- (by same action)
-- ER SR EW SW E
-- ---------------------
-- ER | ER ER E
-- |
-- SR | ER SR E
-- Desired |
-- Access EW | EW EW E
-- |
-- SW | EW SW E
-- |
-- E | E E E E E
-- ---------------------
-- Absence of a mode indicates that the desired access will not be granted
-- if the requesting action already has the indicated current access.
-- Queueing is not available in this case. Presence of a mode indicates
-- that the access will be granted, and indicates the new lock mode in
-- which the action holds object.
-- Note that the upgrade rules imply that a single action cannot be used to
-- both read and write the same pipe. Of course, a single task can read
-- and write the same pipe by using 2 actions.
-- RESTRICTION: In Delta, the Create operation only supports Exclusive,
-- and the Open operation only supports Shared_Read, Shared_Write, and
-- Exclusive.
procedure Create (Pipe : in out Handle;
Mode : Pipe_Open_Mode;
Name : String;
Action : Action_Id := Null_Action_Id;
Max_Wait : Duration := Directory.Default_Wait;
Permanent_Contents : Boolean := False;
Buffer_Size : Positive := Default_Buffer_Size;
Reader_Buffer_Size : Natural := 0);
-- Since it's an object, a pipe lives in the directory system, as specified
-- by the Name parameter. Naming of pipes is the same as for vanilla
-- files. Multiple versions of a pipe are allowed.
-- With respect to disk space, the system reserves the right to allocate
-- disk space for the entire buffer, at any time, including the first
-- open. Thus, one should not use excessively large buffer sizes. With
-- respect to working set, under certain circumstances the buffer is used
-- in a cylic fashion. Thus, a large buffer size may cause a large
-- working set. All in all, its a good idea to use reasonable buffer
-- sizes. One rule of thumb is to use a buffer of size 2 * N * E, where
-- "N" is the number of servers (readers), and "E" is the expected message
-- size; this tends to leave just enough room for writers to be "double
-- bufferred". (Of course, the buffer must be large enough to hold the
-- biggest message.)
-- Given variable length messages, it is not possible for clients to
-- accurately predict the number of messages that can be stored by a buffer
-- of a particular size.
-- A pipe is made empty when it is last closed, or first opened if the
-- system crashes while the pipe is open. The only difference from the
-- user's point of view is disk space consumption.
-- The create operation leaves the pipe "open" in the specified mode.
-- Rules for Action are the same as for Open.
-- Abandoning the action may cause the object to dissappear from the
-- directory system.
-- Abandoning/Committing the action causes all open handles (using the
-- action) to become closed.
-- If Null_Action_Id is supplied, a new action is created. If the Create
-- is successful, the new id is stored in the Handle, and committed when
-- the Handle is closed. If the Create fails, the new action is
-- abandoned.
-- Reader_Buffer_Size controls the operation of the Read function. If 0,
-- then it defaults to the result of calling Max_Buffer_Size.
-- KNOWN BUGS IN DELTA: (1) Abandoning the action which created the pipe
-- does NOT cause all open handles to become closed immediately. (2) The
-- implementation has a window in which concurrent opens may acquire the
-- object; this will cause the Create to return any of the exceptions that
-- can be returned by Open.
-- EXCEPTIONS:
-- Status_Error: The given Handle is already open
-- Mode_Error: Mode must be Exclusive
-- Name_Error: Directory wont create the object
-- Use_Error: Illegal buffer size, or lock error, or
-- access control violation
-- Device_Error: Obj Mgr can't set/get the buffer size;
-- and other internal errors
procedure Open (Pipe : in out Handle;
Mode : Pipe_Open_Mode;
Name : String;
Reader_Buffer_Size : Natural := 0;
Action : Action_Id := Null_Action_Id;
Max_Wait : Duration := Directory.Default_Wait);
-- Open an already existing pipe.
-- If the action is abandoned, the Handle may become implicitly closed.
-- Committing the action has no effect on the state of the pipe buffer.
-- If Null_Action_Id is supplied, a new action is created, its id stored
-- in the Handle, and the action is committed when the Handle is closed.
-- Reader_Buffer_Size controls the operation of the Read function. If 0,
-- then it defaults to the result of calling Max_Buffer_Size.
-- KNOWN BUG IN DELTA: Exclusive access shows up in the action_manager's
-- lock information as "Update"; all other access modes show up as "Read".
-- EXCEPTIONS:
-- Status_error : The given Handle is already open.
-- Mode_Error: Mode must be Shared_Read, Shared_Write, or Exclusive
-- Name_Error: Directory can't find the object
-- Use_Error: Lock error, or access control violation
-- Device_Error: Obj mgr can't get the buffer size;
-- and other internal errors
procedure Open (Pipe : in out Handle;
Mode : Pipe_Open_Mode;
Object : Object_Id;
Reader_Buffer_Size : Natural := 0;
Action : Action_Id := Null_Action_Id;
Max_Wait : Duration := Directory.Default_Wait);
-- Same as above, but assumes that the caller has already resolved the
-- string name into an object id.
procedure Close (Pipe : in out Handle;
Max_Wait : Duration := Directory.Default_Wait);
-- If the pipe is open for writing, causes an implicit call to
-- Write_End_Of_File (throwing away a Use_Error caused by Max_Wait
-- induced timeout);
-- If the corresponding Create/Open supplied Null_Action_Id, then the
-- implicit action is either committed (when the Close is successful) or
-- abandoned (when the Close is unsuccessful).
-- The handle becomes closed.
-- EXCEPTIONS:
-- Status_error: The given Handle is not open.
-- Device_Error: internal errors
procedure Delete (Pipe : in out Handle;
Max_Wait : Duration := Directory.Default_Wait);
-- Like all objects, causes it to be deleted. Must have the object open
-- for Exclusive access. Assuming a reasonable value for retention count,
-- the object can be "undeleted" using other environment operations.
-- If the corresponding Create/Open supplied Null_Action_Id, then the
-- implicit action is either committed (when the Delete is successful) or
-- abandoned (when the Delete is unsuccessful).
-- The handle becomes closed.
-- EXCEPTIONS:
-- Status_Error: The given Handle is not open
-- Name_Error: Directory returned an error other than Lock_Error or
-- access control error
-- Use_Error: Directory returned Lock_Error, which probably means
-- that Handle was not open for Exclusive access;
-- or could be an access control violation
-- Device_Error: internal errors
Dont_Wait : constant Duration := 0.0;
Forever : constant Duration := Duration'Last;
procedure Write (Pipe : in out Handle;
Message : Byte_String;
Max_Wait : Duration := Forever);
procedure Read (Pipe : in out Handle;
Message : out Byte_String;
Length : out Integer;
Max_Wait : Duration := Forever);
function Read (Pipe : Handle; Max_Wait : Duration := Forever)
return Byte_String;
-- These operations are "record (message) oriented". That is, the write
-- operation puts one record into the pipe which remembers the record and
-- its length. When successful, the read operation reads exactly one
-- record (when unsuccessful, it reads 0 records), the Length out parameter
-- indicates the actual length of the record (as given by the corresponding
-- Write operation).
-- This is in contrast with the Device_Independent_Io (Dio) Byte_String
-- operations which are "stream oriented". That is, the read operation
-- returns exactly the number of bytes that are requested, unless
-- end-of-file is reached, in which case fewer bytes are returned, as
-- indicated by the Length out parameter.
-- Given that pipes are record oriented, it is possible to write a program
-- which reads messages from a pipe, and copies them or sends them
-- somewhere else, without regard for the actual type of the data, and
-- preserving message boundaries.
-- The Read function is the same as the Read procedure except that it
-- internally allocates a Byte_String (of the length specified by the
-- Reader_Buffer_Size parameter of Create/Open) in which to read the
-- message, and then returns the first Length bytes. For variable length
-- messages, this frees the client (of this package) from needing to know
-- the maximum message size. In the current implementation, this
-- convenience is not free: the function makes an additional copy of the
-- message (as compared to the procedure), and it allocates
-- Reader_Buffer_Size - Length extra bytes in its stack frame. Of course,
-- if the function call site simply assigns the result into some variable,
-- there is an additional copy (as compared to the procedure).
-- Read and Write operations are atomic with respect to each other. BUT,
-- This DOES NOT include multiple tasks reading/writing with the same
-- Handle.
-- Messages are passed by value. That is, once Write completes, the entire
-- message is stored within the pipe. Termination of the client (which
-- performed the Write) does not effect the state of the pipe.
-- Recall that a pipe has finite internal buffer capability. A Write
-- operation which would exceed the maximum buffer size (defined at pipe
-- creation time) always raises Use_Error (and extended status
-- Item_Too_Big). A Write operation which would exceed the remaining
-- buffer capacity is handled as follows: If Max_Wait time expires before
-- sufficient room becomes available in the buffer (this is immediately
-- true if Max_Wait = Dont_Wait), then raises Use_Error (and extended
-- status No_Room_In_Buffer). When Use_Error is raised, the pipe is left
-- unmodified (except for overrun notification, as discussed below). The
-- client can distinguish between these flavors of Use_Error via the
-- Get_Extended_Status operation, below.
-- In the event that there are multiple clients waiting to do Write, they
-- are typically serviced FIFO in order to avoid starvation.
-- Similarly, a Read operation specifies the maximum amount of time to
-- wait for the buffer to become non-empty. A time of 0 indicates that the
-- client does not want to wait at all. If the wait time expires before a
-- message is received by the client, then the client gets Use_Error, and
-- the pipe is left unchanged.
-- The Read operation returns a single message. The Length parameter
-- indicates the actual number of bytes written into the Message parameter.
-- In the event that the actual message (supplied by the corresponding
-- Write operation) was longer than the Message parameter supplied to Read,
-- the client will receive Data_Error (and extended status of
-- Item_Too_Big), and the contents of the pipe are left unchanged. In
-- future implementations, negative values of Length may be defined.
-- Recall that each message is read by exactly one Read operation; thus, in
-- the face of concurrent Reads, each client may see just a subset of the
-- messages that were written to the pipe.
-- In the event that there are multiple clients waiting to do Read, they
-- are typically serviced LIFO. We assume that the application considers
-- all readers to be equivalent. In this context, LIFO is better than FIFO
-- because it minimizes the working set of the readers. (LIFO causes the
-- reader which most recently finished working to be the next to receive a
-- message). This simplifies applications which need to choose the number
-- of readers; they can simply pick the maximum number of readers which can
-- operate in parallel.
-- The implementation of Read and Write waiting can handle aborts of
-- clients.
-- Specifying infinite wait times allows one to use the finite buffer
-- capacity as a flow control mechanism.
-- "end of file" (eof) messages are written into a pipe via the
-- Write_End_Of_File operation, and implicitly via Close (which itself may
-- be implicit via action abandon, which itself may be implicit ...). When
-- a Read operation encounters an eof message, it is consumed, and
-- End_Error is raised. Unlike other sequential media, one can read an
-- eof only once.
-- "Overrun" refers to a situation in which the writer does not wait
-- forever for buffer space to become available and drops the unsent
-- messages on the floor. Pipes include the following mechanism for
-- detecting overrun:
-- In addition to messages of type data and eof, there are messages of type
-- overrun. A Write operation which raises Use_Error (because there is
-- insufficient room in the buffer) appends a message of type overrun.
-- Adjacent overrun messages are coalesced into a single overrun message.
-- The Read operation consumes the overrun message (when encountered) and
-- raises Use_Error. Like eof, an overrun message can only be read once.
-- Death of a client that has the pipe open for update may sometimes cause
-- an overrun to be placed in the pipe.
-- Observations: (1) The writer should probably not "poll" the pipe by
-- using a short Max_Wait, since each unsuccessful attempt will append an
-- overrun message, causing the reader to get a Use_Error. (2) The reader
-- can distinguish between timeout and overrun (both raise Use_Error) by
-- using the Extended_Status function, below.
-- EXCEPTIONS:
-- Status_Error : The given Handle is not open
-- Mode_Error : Write: Handle was Open'd for Exclusive_Read
-- or Shared_Read
-- Read: Handle was Open'd for Exclusive_Write
-- or Shared_Write
-- Use_Error : Write: Max_Wait expired,
-- or Message'length is larger than buffer size;
-- Read: Max_Wait expired,
-- or just consumed an overrun message
-- Data_Error : Read: Message'length is shorter than next message
-- : Read/Write: touching Message caused
-- Nonexistant_Page_Error
-- : Read: storing into Message caused
-- Write_To_Read_Only_Page
-- End_Error : Read: just consumed an end-of-file message
-- Device_Error : internal errors
pragma Consume_Offset (4);
generic
type Element_Type is private;
package Type_Specific_Operations is
procedure Write (Pipe : in out Handle;
Message : Element_Type;
Max_Wait : Duration := Forever);
procedure Read (Pipe : in out Handle;
Message : out Element_Type;
Max_Wait : Duration := Forever);
function Read (Pipe : Handle; Max_Wait : Duration := Forever)
return Element_Type;
pragma Consume_Offset;
end Type_Specific_Operations;
-- The usual "legal type for IO" rules apply to Element_Type. In
-- particular, Element_Type cannot be (or contain) pointers or tasks.
-- Both ends of the pipe should instantiate this package with the same
-- type, else one will get implicit unchecked conversions, and might
-- get Data_Error.
-- The generic Write operation first normalizes the Message, converts the
-- bits (of the Message) into a Byte_String (adding up to 7 bits of
-- padding, as necessary), and then calls the non-generic Write.
-- By normalize, we mean the following. For record types, if the object is
-- not constrained, allocate a constained instance of the object and copy
-- the Message into the constrained copy. Note that this is expensive,
-- since it involves declaring collections and doing copies. For array
-- types, if the "bounds with object"ness of the Message is not the same as
-- that of the Element_Type (argument to the generic), then a copy is made
-- to convert the Message to the same boundedness as the Element_Type.
-- The generic Read procedure calls the non-generic Read procedure to fetch
-- the padded Byte_String, does an implicit unchecked conversion to
-- Element_Type, and assigns it to the out parameter.
-- The conversion may cause Data_Error to be raised when Element_Type is
-- not "compatable" with the actual bits in the message; this might happen
-- if the Write generic was instantiated with a different type than the
-- Read generic, for example. Some conditions that may cause
-- incompatibility: The 'size of the result of the unchecked conversion
-- (rounded to a byte) is not the same as the actual byte length of the
-- received message. The Element_Type is unconstrained and the message is
-- garbage (when interpreted according to Element_Type).
-- The assignment follows Ada semantics, and may therefore fail for a
-- variety of reasons, causing Data_Error. Some conditions that may cause
-- the assignment to fail: Element_Type is an unconstrained array type
-- (such as String), and the 'length of the string value in the buffer is
-- not the same as the 'length of the Message out parameter. The
-- Element_Type is unconstrained and the message is garbage (when
-- interpreted according to Element_Type).
-- The generic Read function calls the non-generic Read function, does an
-- implicit unchecked conversion to Element_Type, and returns the result.
-- Data_Error may be raised when Element_Type is not "compatible" with the
-- actual bits in the message, as for the Read procedure.
-- EXCEPTIONS (in addition to those raised by the non-generic forms):
-- Data_Error : Read: bits in the actual message are not
-- "compatible" with Element_Type, or := failed.
-- Pkg instantiation: raised when Element_Type has
-- task or access/heap_access components.
function End_Of_File (Pipe : Handle) return Boolean;
-- Returns true iff a read operation would have caused End_Error to be
-- raised.
-- EXCEPTIONS:
-- Status_Error : The given Handle is not open
-- Device_Error : internal errors
procedure Write_End_Of_File (Pipe : in out Handle;
Max_Wait : Duration := Forever);
-- Puts an end-of-file message into the pipe. Note that Close (of a pipe
-- open for writing) may implicitly call this procedure. Abandoning
-- an action (of a writer) may implicitly call this procedure. With
-- respect to overruns, this call follows rules given for Write.
-- EXCEPTIONS:
-- Status_Error : The given Handle is not open
-- Use_Error : Max_Wait expired,
-- or Message'length is larger than buffer size;
-- Device_Error : internal errors
function Current_Message_Count (Pipe : Handle) return Natural;
-- Can be used to "poll" a pipe to see how many messages are queued up,
-- waiting to be read.
-- EXCEPTIONS:
-- Status_Error : The given Handle is not open
function Max_Buffer_Size (Pipe : Handle) return Positive;
-- Return the buffer size of an open pipe.
-- EXCEPTIONS:
-- Status_Error : The given Handle is not open
function Open_Action (Pipe : Handle) return Action_Id;
-- Returns the action by which the Handle has the pipe open.
-- EXCEPTIONS:
-- Status_Error : The given Handle is not open
pragma Consume_Offset (3);
type Full_Status_Kinds is
(Pipe_Status, Directory_Error_Status,
Directory_Name_Status, Manager_Status, U4, U5, U6, U7);
function Get_Full_Status_Kind (Pipe : Handle) return Full_Status_Kinds;
-- Defined iff the Handle is currently open and the last PROCEDURE call on
-- the Handle raised an exception and the following table indicates that
-- additional status is available.
-- Status_Error no additional status
-- Mode_Error no additional status
-- Name_Error more status available
-- Use_Error more status available
-- Device_Error more status available
-- End_Error more status available
-- Data_Error more status available
-- Layout_Error no additional status In this case, indicates which
-- kind of additional status information is available about the exception.
type Extended_Status is (Internal_Pipe_Error, Item_Too_Big,
No_Room_In_Buffer, Buffer_Is_Empty,
Behind_Other_Readers, Read_An_Eof, Read_An_Overrun,
Missing_Page, Read_Only_Page, U09,
U10, U11, U12, U13, U14, U15, U16);
function Get_Extended_Status (Pipe : Handle) return Extended_Status;
function Get_Directory_Error_Status (Pipe : Handle) return Integer;
function Get_Directory_Name_Status (Pipe : Handle) return Integer;
function Get_Manager_Status (Pipe : Handle) return Operate_Status;
-- The above are defined iff Get_Full_Status_Kind is defined and returns
-- the corresponding value of Full_Status_Kinds. Rational reserves the
-- right to add additional Extended_Status values. Otherwise, it's ok
-- to program against Extended_Status values. The integer values returned
-- by the last 3 functions are for debugging only, and may change between
-- between releases of this software.
function Status_Explanation (Pipe : Handle) return String;
-- Returns, in string form, the best explanation of the status that is
-- currently available. This explanation may include additional internal
-- state information. The returned string may differ between releases of
-- this software.
generic
with procedure Put_Line (S : String);
procedure Put_Pipe_Internal_State (Pipe : Handle;
Depth : Natural := 25;
Get_Locks : Boolean := False);
generic
with procedure Put_Line (S : String);
procedure Put_Internal_State (Depth : Natural := 25;
Get_Locks : Boolean := False);
-- These operations are primarily intended for use as debugging
-- aids by Rational personnel. However, it is also possible for customers
-- to use this information to debug their applications. The format of the
-- of the information fed through Put_Line may change in future releases.
-- The first operation gives you more information if the Handle is for an
-- open pipe! Depth is used to keep various algorithms from going into an
-- infinite loop when the internal data structures for the pipe are
-- inconsistent. Get_Locks indicates whether or not the internal data
-- structures should be viewed from within the appropriate critical
-- regions; in the current implementation, only the default is supported.
-- These operations are primarily intended for use as debugging
-- aids by Rational personnel. However, it is also possible for customers
-- to use this information to debug their applications. The format of the
-- of the information fed through Put_Line may change in future releases.
-- The first operation gives you more information if the Handle is for an
-- open pipe! Depth is used to keep various algorithms from going into an
-- infinite loop when the internal data structures for the pipe are
-- inconsistent. Get_Locks indicates whether or not the internal data
-- structures should be viewed from within the appropriate critical
-- regions; in the current implementation, only the default is supported.
function Debug_Image (Pipe : Handle;
Level : Natural;
Prefix : String;
Expand_Pointers : Boolean) return String;
--
-- Daemon control. The interval specifies how often the pipe daemon
-- runs. It defaults to every 30 seconds at low CPU priority.
--
-- Run_Daemon will cause the daemon to run at the priority of the
-- calling task. Note that this might actually cause the daemon
-- to run twice if it is currently scheduled and blocked, since it
-- has to finish (at the low priority) before this call can run it.
function Get_Daemon_Interval return Duration;
procedure Set_Daemon_Interval (Interval : Duration);
procedure Run_Daemon;
pragma Subsystem (Input_Output, Private_Part => Closed);
pragma Module_Name (4, 3223);
end Pipe;