polyorb_hi-unprotected_queue.ads 12.9 KB
Newer Older
1 2 3 4 5 6 7 8
------------------------------------------------------------------------------
--                                                                          --
--                          PolyORB HI COMPONENTS                           --
--                                                                          --
--         P O L Y O R B _ H I . U N P R O T E C T E D _ Q U E U E          --
--                                                                          --
--                                 S p e c                                  --
--                                                                          --
9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
--                   Copyright (C) 2014-2015 ESA & ISAE.                    --
--                                                                          --
-- PolyORB-HI is free software; you can redistribute it and/or modify under --
-- terms of the  GNU General Public License as published  by the Free Soft- --
-- ware  Foundation;  either version 3,  or (at your option) any later ver- --
-- sion. PolyORB-HI is distributed in the hope that it will be useful, but  --
-- WITHOUT ANY WARRANTY; without even the implied warranty of               --
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.                     --
--                                                                          --
-- As a special exception under Section 7 of GPL version 3, you are granted --
-- additional permissions described in the GCC Runtime Library Exception,   --
-- version 3.1, as published by the Free Software Foundation.               --
--                                                                          --
-- You should have received a copy of the GNU General Public License and    --
-- a copy of the GCC Runtime Library Exception along with this program;     --
-- see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see    --
-- <http://www.gnu.org/licenses/>.                                          --
26 27 28 29 30 31 32 33
--                                                                          --
--              PolyORB-HI/Ada is maintained by the TASTE project           --
--                      (taste-users@lists.tuxfamily.org)                   --
--                                                                          --
------------------------------------------------------------------------------

with Ada.Unchecked_Conversion;
With Ada.Real_Time;
34
With System;
35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293

with PolyORB_HI_Generated.Deployment;

with PolyORB_HI.Port_Kinds;
with PolyORB_HI.Streams;

generic

   type Port_Type is (<>);
   --  This should be an enumeration type that represent the port list
   --  of a given thread.

   type Integer_Array is array (Port_Type) of Integer;
   --  An array type to specify the port FIFO sizes and urgencies.

   type Port_Kind_Array is array (Port_Type) of Port_Kinds.Port_Kind;
   --  An array type to specify the kind of each port.

   type Port_Image_Array is array (Port_Type) of
    PolyORB_HI_Generated.Deployment.Port_Sized_String;
   --  An array type to specify the image of each port.

   type Overflow_Protocol_Array is array (Port_Type) of
     Port_Kinds.Overflow_Handling_Protocol;
   --  An array to specify the overflow_handling_protocol of each port

   type Thread_Interface_Type (Port : Port_Type) is private;
   --  This is a discriminated record type that represents a thread
   --  port. The discriminant of this type must have a default value
   --  so that the type size can be computed at compile time.

   Current_Entity : in PolyORB_HI_Generated.Deployment.Entity_Type;
   --  Indicate the thread for which this package has been
   --  instantiated.

   Thread_Port_Kinds : in Port_Kind_Array;
   --  For each port, a value indicates the kind and the orientation
   --  of the port.

   Has_Event_Ports : in Boolean;
   --  True if Thread_Port_Kinds contains Event or Event Data ports

   Thread_Port_Images : in Port_Image_Array;
   --  For each port, a string indicates the image of the port.

   Thread_Fifo_Sizes : in Integer_Array;
   --  This array gives for each port the FIFO size (depending on the
   --  port nature or on an AADL property associated to the port. FIFO
   --  size for IN DATA ports is either 1 (immediate connection) or 2
   --  (delayed connection). In this case (data ports), the value must
   --  not be interpreted as a FIFO size but rather a way to support
   --  delayed connections. By convention, FIFO size for all OUT ports
   --  must be set to -1 by the code generator.

   Thread_Fifo_Offsets : in Integer_Array;
   --  This array holds an incremental value of the queue size for
   --  each IN [event] [data] port. For each IN [event] [data] port, the
   --  corresponding offset value is 1 + the sum of all queue sized of
   --  the ports declared before it. For other port kinds, the value
   --  must be 0. We give this array as a generic formal instead of
   --  computing it in this package to guarantee an O(1) access time
   --  for queue elements.

   Thread_Overflow_Protocols : in Overflow_Protocol_array;
   --  This array gives for each port the Overflow_Handling_Protocol
   --  depending on the AADL property associated to the port.

   Urgencies : in Integer_Array;
   --  This array gives for each port the Urgency depending on the
   --  AADL property associated to the port.

   Global_Data_Queue_Size : in Integer;
   --  The sum of all IN [event] [data] port queue sizes. Giving this
   --  value as a generic formal in spite of the possibility of
   --  deducing it from Thread_Fifo_Sizes is done to guarantee static
   --  allocation of the global message queue of the thread.

package PolyORB_HI.Unprotected_Queue is

   use Ada.Real_Time;
   use PolyORB_HI_Generated.Deployment;
   use PolyORB_HI.Streams;

   --  The types and the routines below give a flexible way to handle
   --  Thread_Interface_Type variables and to store them in arrays.

   type Port_Stream is
     new PolyORB_HI.Streams.Stream_Element_Array
     (1 .. Thread_Interface_Type'Size / 8);

   type Port_Stream_Entry is record
      From    : Entity_Type;
      Payload : Port_Stream;
   end record;
   --  A couple of a message and its sender

   N_Ports : constant Integer :=
     Port_Type'Pos (Port_Type'Last) - Port_Type'Pos (Port_Type'First) + 1;
   --  Number of ports in the thread

   function Interface_To_Stream is
      new Ada.Unchecked_Conversion (Thread_Interface_Type, Port_Stream);
   function Stream_To_Interface is
      new Ada.Unchecked_Conversion (Port_Stream, Thread_Interface_Type);

   function CE return String;
   pragma Inline (CE);
   --  Shortcut to Entity_Image (Current_Entity)

   type Port_Stream_Array is array (Port_Type) of Port_Stream_Entry;

   subtype Big_Port_Index_Type is Integer range 0 .. Global_Data_Queue_Size;

   Default_Index_Value : constant Big_Port_Index_Type
     := (if Global_Data_Queue_Size > 0 then 1 else 0);

   type Big_Port_Stream_Array is
     array (Big_Port_Index_Type) of Port_Stream_Entry;
   type Big_Port_Type_Array is array (Big_Port_Index_Type) of Port_Type;
   --  FIXME: We begin by 0 although the 0 position is unused. We do
   --  this to avoid compile time warning. After this package is
   --  deeply tested, begin by 1 and disable Index_Check and
   --  Range_Check for the Big_Port_Stream_Array type.

   type Port_Index_Array is array (Port_Type) of Big_Port_Index_Type;
   --  An array type to specify the port FIFO sizes and urgencies.

   procedure H_Increment_First (F : in out Big_Port_Index_Type);
   procedure H_Increment_Last  (L : in out Big_Port_Index_Type);
   pragma Inline (H_Increment_First);
   pragma Inline (H_Increment_Last);
   --  Cyclic incrementation and decrementation of F or L within the
   --  1..Global_Data_Queue_Size range.

   type Boolean_Array is array (Port_Type) of Boolean;
   type Time_Array is array (Port_Type) of Time;

   procedure Read_Event
     (P : out Port_Type;
      Valid : out Boolean;
      Not_Empty : Boolean);
   --  Same as 'Wait_Event' but without blocking. Valid is set to
   --  False if there is nothing to receive.

   procedure Dequeue
     (T : Port_Type; P : out Port_Stream_Entry; Not_Empty : out Boolean);
   --  Dequeue a value from the partial FIFO of port T. If there is
   --  no enqueued value, return the latest dequeued value.

   function Read_In (T : Port_Type) return Port_Stream_Entry;
   --  Read the oldest queued value on the partial FIFO of IN port
   --  T without dequeuing it. If there is no queued value, return
   --  the latest dequeued value.

   function Read_Out (T : Port_Type) return Port_Stream_Entry;
   --  Return the value put for OUT port T.

   function Is_Invalid (T : Port_Type) return Boolean;
   --  Return True if no Put_Value has been called for this port
   --  since the last Set_Invalid call.

   procedure Set_Invalid (T : Port_Type);
   --  Set the value stored for OUT port T as invalid to impede its
   --  future sending without calling Put_Value. This procedure is
   --  generally called just after Read_Out. However we cannot
   --  combine them in one routine because we need Read_Out to be a
   --  function and functions cannot modify protected object
   --  states.

   procedure Store_In
     (P : Port_Stream_Entry; T : Time; Not_Empty : out Boolean);
   --  Stores a new incoming message in its corresponding
   --  position. If this is an event [data] incoming message, then
   --  stores it in the queue, updates its most recent value and
   --  unblock the barrier. Otherwise, it only overrides the most
   --  recent value. T is the time stamp associated to the port
   --  P. In case of data ports with delayed connections, it
   --  indicates the instant from which the data of P becomes
   --  deliverable.

   procedure Store_Out (P : Port_Stream_Entry; T : Time);
   --  Store a value of an OUT port to be sent at the next call to
   --  Send_Output and mark the value as valid.

   function Count (T : Port_Type) return Integer;
   --  Return the number of pending messages on IN port T.

   function Get_Time_Stamp (P : Port_Type) return Time;
   --  Return the time stamp associated to port T

   --  The following are accessors to some internal data of the event queue

   function Get_Most_Recent_Value (P : Port_Type) return Port_Stream_Entry;
   procedure Set_Most_Recent_Value
     (P : Port_Type;
      S : Port_Stream_Entry;
      T : Time);
   --  The protected object contains also an array to store the
   --  values of received IN DATA ports as well as the most recent
   --  value of IN EVENT DATA. For OUT port, the value is the
   --  message to be send when Send_Output is called. In case of an
   --  event data port, we do not use the 2 elements of the array
   --  to store most recent values because there is no delayed
   --  connections for event data ports.

private
   Global_Data_Queue : Big_Port_Stream_Array;
   --  The structure of the buffer is as follows:

   --  ----------------------------------------------------------------
   --  |   Q1   |     Q2      |       Q3        |  ... |      Qn      |
   --  ----------------------------------------------------------------
   --  O1       O2            O3                O4 ... On

   --  'On' is the offset associated to IN [event] [data] port n,
   --  given from the generic formal, Thread_FIFO_Offsets. This
   --  guarantees an O(1) access and storage time of a given
   --  element in the global queue. Intrinsically, the global table
   --  is a concatenation of circular arrays each one corresponding
   --  to a port queue.

   Firsts : Port_Index_Array := (Port_Type'Range => Default_Index_Value);
   Lasts  : Port_Index_Array := (Port_Type'Range => 0);
   --  Used for IN [event] [data] ports to navigate in the global
   --  queue. For IN DATA ports, in case of immediate connection
   --  only the 'Lasts' value is relevant and it is 0 or 1, in case
   --  of a delayed connection both values are relevant.

   Empties : Boolean_Array := (Port_Type'Range => True);
   --  Indicates whether each port-FIFO is empty or not

   Global_Data_History : Big_Port_Type_Array;
   GH_First            : Big_Port_Index_Type := Default_Index_Value;
   GH_Last             : Big_Port_Index_Type := 0;
   --  This contains, in an increasing chronological order the IN
   --  EVENT ports that have a pending event. Example (P_1, P_3,
   --  P_1, P_2, P_3) means that the oldest pending message is
   --  received on P_1 then on P_3, then on P_1 again and so on...

   --  FIXME: Add N_Ports to the array size to handle the case the
   --  thread has an IN event [data] port with a FIFO size equal to
   --  zero which is not supported yet.

   Most_Recent_Values : Port_Stream_Array;
   Time_Stamps        : Time_Array;

   Initialized : Boolean_Array := (Port_Type'Range => False);
   --  To indicate whether the port ever received a data (or an
   --  event).

   Value_Put : Boolean_Array := (Port_Type'Range => False);
   --  To indicate whether the OUT port values have been set in
   --  order to be sent.

   N_Empties : Integer := N_Ports;
   --  Number of empty partial queues. At the beginning, all the
   --  queues are empty.

end PolyORB_HI.Unprotected_Queue;