home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / adav313.zip / gnat-3_13p-os2-bin-20010916.zip / emx / gnatlib / s-tposen.adb < prev    next >
Text File  |  2000-07-19  |  22KB  |  653 lines

  1. ------------------------------------------------------------------------------
  2. --                                                                          --
  3. --                GNU ADA RUN-TIME LIBRARY (GNARL) COMPONENTS               --
  4. --                                                                          --
  5. --     S Y S T E M . T A S K I N G . P R O T E C T E D _ O B J E C T S .    --
  6. --                          S I N G L E _ E N T R Y                         --
  7. --                                                                          --
  8. --                                  B o d y                                 --
  9. --                                                                          --
  10. --                             $Revision: 1.11 $
  11. --                                                                          --
  12. --             Copyright (C) 1991-1999 Florida State University             --
  13. --                                                                          --
  14. -- GNARL is free software; you can  redistribute it  and/or modify it under --
  15. -- terms of the  GNU General Public License as published  by the Free Soft- --
  16. -- ware  Foundation;  either version 2,  or (at your option) any later ver- --
  17. -- sion. GNARL is distributed in the hope that it will be useful, but WITH- --
  18. -- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
  19. -- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
  20. -- for  more details.  You should have  received  a copy of the GNU General --
  21. -- Public License  distributed with GNARL; see file COPYING.  If not, write --
  22. -- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
  23. -- MA 02111-1307, USA.                                                      --
  24. --                                                                          --
  25. -- As a special exception,  if other files  instantiate  generics from this --
  26. -- unit, or you link  this unit with other files  to produce an executable, --
  27. -- this  unit  does not  by itself cause  the resulting  executable  to  be --
  28. -- covered  by the  GNU  General  Public  License.  This exception does not --
  29. -- however invalidate  any other reasons why  the executable file  might be --
  30. -- covered by the  GNU Public License.                                      --
  31. --                                                                          --
  32. -- GNARL was developed by the GNARL team at Florida State University. It is --
  33. -- now maintained by Ada Core Technologies Inc. in cooperation with Florida --
  34. -- State University (http://www.gnat.com).                                  --
  35. --                                                                          --
  36. ------------------------------------------------------------------------------
  37.  
  38. --  This package provides an optimized version of Protected_Objects.Operations
  39. --  and Protected_Objects.Entries making the following assumptions:
  40. --
  41. --  PO have only one entry
  42. --  There is only one caller at a time (No_Entry_Queue)
  43. --  There is no dynamic priority support (No_Dynamic_Priorities)
  44. --  No Abort Statements
  45. --    (No_Abort_Statements, Max_Asynchronous_Select_Nesting => 0)
  46. --  PO are at library level
  47. --  No Requeue
  48. --  None of the tasks will terminate (no need for finalization)
  49. --
  50. --  This interface is intended to be used in the ravenscar and restricted
  51. --  profiles, the compiler is responsible for ensuring that the conditions
  52. --  mentioned above are respected, except for the No_Entry_Queue restriction
  53. --  that is checked dynamically in this package, since the check cannot be
  54. --  performed at compile time, and is relatively cheap (see PO_Do_Or_Queue,
  55. --  PO_Service_Entry).
  56.  
  57. pragma Polling (Off);
  58. --  Turn off polling, we do not want polling to take place during tasking
  59. --  operations. It can cause  infinite loops and other problems.
  60.  
  61. pragma Suppress (All_Checks);
  62.  
  63. with System.Tasking.Debug;
  64. --  used for Trace
  65.  
  66. with System.Task_Primitives.Operations;
  67. --  used for Self
  68. --           Finalize_Lock
  69. --           Write_Lock
  70. --           Unlock
  71.  
  72. with Ada.Exceptions;
  73. --  used for Exception_Id;
  74.  
  75. with Unchecked_Conversion;
  76.  
  77. package body System.Tasking.Protected_Objects.Single_Entry is
  78.  
  79.    package STPO renames System.Task_Primitives.Operations;
  80.  
  81.    function To_Address is new
  82.      Unchecked_Conversion (Protection_Entry_Access, System.Address);
  83.  
  84.    -----------------------------
  85.    --  Internal declarations  --
  86.    -----------------------------
  87.  
  88.    procedure Send_Program_Error
  89.      (Self_Id    : Task_ID;
  90.       Entry_Call : Entry_Call_Link);
  91.    pragma Inline (Send_Program_Error);
  92.    --  Raise Program_Error in the caller of the specified entry call
  93.  
  94.    --------------------------
  95.    -- Entry Calls Handling --
  96.    --------------------------
  97.  
  98.    procedure Wakeup_Entry_Caller
  99.      (Self_ID    : Task_ID;
  100.       Entry_Call : Entry_Call_Link;
  101.       New_State  : Entry_Call_State);
  102.    pragma Inline (Wakeup_Entry_Caller);
  103.    --  This is called at the end of service of an entry call,
  104.    --  to abort the caller if he is in an abortable part, and
  105.    --  to wake up the caller if he is on Entry_Caller_Sleep.
  106.    --  Call it holding the lock of Entry_Call.Self.
  107.    --
  108.    --  Timed_Call or Simple_Call:
  109.    --    The caller is waiting on Entry_Caller_Sleep, in
  110.    --    Wait_For_Completion, or Wait_For_Completion_With_Timeout.
  111.  
  112.    procedure Wait_For_Completion
  113.      (Self_ID    : Task_ID;
  114.       Entry_Call : Entry_Call_Link);
  115.    pragma Inline (Wait_For_Completion);
  116.    --  This procedure suspends the calling task until the specified entry call
  117.    --  has either been completed or cancelled. On exit, the call will not be
  118.    --  queued. This waits for calls on protected entries.
  119.    --  Call this only when holding Self_ID locked.
  120.  
  121.    procedure Wait_For_Completion_With_Timeout
  122.      (Self_ID     : Task_ID;
  123.       Entry_Call  : Entry_Call_Link;
  124.       Wakeup_Time : Duration;
  125.       Mode        : Delay_Modes);
  126.    --  Same as Wait_For_Completion but it waits for a timeout with the value
  127.    --  specified in Wakeup_Time as well.
  128.    --  Self_ID will be locked by this procedure.
  129.  
  130.    procedure Check_Exception
  131.      (Self_ID : Task_ID;
  132.       Entry_Call : Entry_Call_Link);
  133.    pragma Inline (Check_Exception);
  134.    --  Raise any pending exception from the Entry_Call.
  135.    --  This should be called at the end of every compiler interface procedure
  136.    --  that implements an entry call.
  137.    --  The caller should not be holding any locks, or there will be deadlock.
  138.  
  139.    ------------------------
  140.    -- Send_Program_Error --
  141.    ------------------------
  142.  
  143.    procedure Send_Program_Error
  144.      (Self_Id    : Task_ID;
  145.       Entry_Call : Entry_Call_Link)
  146.    is
  147.       Caller : constant Task_ID := Entry_Call.Self;
  148.    begin
  149.       Entry_Call.Exception_To_Raise := Program_Error'Identity;
  150.       STPO.Write_Lock (Caller);
  151.       Wakeup_Entry_Caller (Self_Id, Entry_Call, Done);
  152.       STPO.Unlock (Caller);
  153.    end Send_Program_Error;
  154.  
  155.    -------------------------
  156.    -- Wakeup_Entry_Caller --
  157.    -------------------------
  158.  
  159.    --  This is called at the end of service of an entry call, to abort the
  160.    --  caller if he is in an abortable part, and to wake up the caller if it
  161.    --  is on Entry_Caller_Sleep. It assumes that the call is already off-queue.
  162.  
  163.    --  (This enforces the rule that a task must be off-queue if its state is
  164.    --  Done or Cancelled.) Call it holding the lock of Entry_Call.Self.
  165.  
  166.    --  Timed_Call or Simple_Call:
  167.    --    The caller is waiting on Entry_Caller_Sleep, in
  168.    --    Wait_For_Completion, or Wait_For_Completion_With_Timeout.
  169.  
  170.    --  Conditional_Call:
  171.    --    The caller might be in Wait_For_Completion,
  172.    --    waiting for a rendezvous (possibly requeued without abort)
  173.    --    to complete.
  174.  
  175.    procedure Wakeup_Entry_Caller
  176.      (Self_ID    : Task_ID;
  177.       Entry_Call : Entry_Call_Link;
  178.       New_State  : Entry_Call_State)
  179.    is
  180.       Caller : constant Task_ID := Entry_Call.Self;
  181.    begin
  182.       pragma Debug (Debug.Trace
  183.         (Self_ID, "Wakeup_Entry_Caller", Caller, 'E'));
  184.       pragma Assert (New_State = Done or else New_State = Cancelled);
  185.  
  186.       pragma Assert
  187.         (Caller.Common.State /= Terminated and then
  188.          Caller.Common.State /= Unactivated);
  189.  
  190.       Entry_Call.State := New_State;
  191.  
  192.       STPO.Wakeup (Caller, Entry_Caller_Sleep);
  193.    end Wakeup_Entry_Caller;
  194.  
  195.    -------------------------
  196.    -- Wait_For_Completion --
  197.    -------------------------
  198.  
  199.    --  Call this only when holding Self_ID locked
  200.  
  201.    procedure Wait_For_Completion
  202.      (Self_ID    : Task_ID;
  203.       Entry_Call : Entry_Call_Link) is
  204.    begin
  205.       pragma Assert (Self_ID = Entry_Call.Self);
  206.       Self_ID.Common.State := Entry_Caller_Sleep;
  207.  
  208.       STPO.Sleep (Self_ID, Entry_Caller_Sleep);
  209.  
  210.       Self_ID.Common.State := Runnable;
  211.    end Wait_For_Completion;
  212.  
  213.    --------------------------------------
  214.    -- Wait_For_Completion_With_Timeout --
  215.    --------------------------------------
  216.  
  217.    --  This routine will lock Self_ID.
  218.  
  219.    --  This procedure waits for the entry call to
  220.    --  be served, with a timeout.  It tries to cancel the
  221.    --  call if the timeout expires before the call is served.
  222.  
  223.    --  If we wake up from the timed sleep operation here,
  224.    --  it may be for the following possible reasons:
  225.  
  226.    --  1) The entry call is done being served.
  227.    --  2) The timeout has expired (Timedout = True)
  228.  
  229.    --  Once the timeout has expired we may need to continue to wait if
  230.    --  the call is already being serviced. In that case, we want to go
  231.    --  back to sleep, but without any timeout. The variable Timedout is
  232.    --  used to control this. If the Timedout flag is set, we do not need
  233.    --  to Sleep with a timeout. We just sleep until we get a wakeup for
  234.    --  some status change.
  235.  
  236.    procedure Wait_For_Completion_With_Timeout
  237.      (Self_ID     : Task_ID;
  238.       Entry_Call  : Entry_Call_Link;
  239.       Wakeup_Time : Duration;
  240.       Mode        : Delay_Modes)
  241.    is
  242.       Timedout : Boolean;
  243.       Yielded  : Boolean;
  244.  
  245.       use type Ada.Exceptions.Exception_Id;
  246.  
  247.    begin
  248.       STPO.Write_Lock (Self_ID);
  249.  
  250.       pragma Assert (Entry_Call.Self = Self_ID);
  251.       pragma Assert (Entry_Call.Mode = Timed_Call);
  252.       Self_ID.Common.State := Entry_Caller_Sleep;
  253.  
  254.       STPO.Timed_Sleep
  255.         (Self_ID, Wakeup_Time, Mode, Entry_Caller_Sleep, Timedout, Yielded);
  256.  
  257.       if Timedout then
  258.          Entry_Call.State := Cancelled;
  259.       else
  260.          Entry_Call.State := Done;
  261.       end if;
  262.  
  263.       Self_ID.Common.State := Runnable;
  264.       STPO.Unlock (Self_ID);
  265.    end Wait_For_Completion_With_Timeout;
  266.  
  267.    ---------------------
  268.    -- Check_Exception --
  269.    ---------------------
  270.  
  271.    --  Raise any pending exception from the Entry_Call.
  272.  
  273.    --  This should be called at the end of every compiler interface
  274.    --  procedure that implements an entry call.
  275.  
  276.    --  In principle, the caller should not be abort-deferred (unless
  277.    --  the application program violates the Ada language rules by doing
  278.    --  entry calls from within protected operations -- an erroneous practice
  279.    --  apparently followed with success by some adventurous GNAT users).
  280.    --  Absolutely, the caller should not be holding any locks, or there
  281.    --  will be deadlock.
  282.  
  283.    procedure Check_Exception
  284.      (Self_ID    : Task_ID;
  285.       Entry_Call : Entry_Call_Link)
  286.    is
  287.       use type Ada.Exceptions.Exception_Id;
  288.  
  289.       procedure Internal_Raise (X : Ada.Exceptions.Exception_Id);
  290.       pragma Import (C, Internal_Raise, "__gnat_raise_with_msg");
  291.  
  292.       E : constant Ada.Exceptions.Exception_Id :=
  293.         Entry_Call.Exception_To_Raise;
  294.  
  295.    begin
  296.       if E /= Ada.Exceptions.Null_Id then
  297.          Internal_Raise (E);
  298.       end if;
  299.    end Check_Exception;
  300.  
  301.    -------------------------
  302.    --  Restricted GNARLI  --
  303.    -------------------------
  304.  
  305.    ---------------------------------
  306.    -- Initialize_Protection_Entry --
  307.    ---------------------------------
  308.  
  309.    procedure Initialize_Protection_Entry
  310.      (Object            : Protection_Entry_Access;
  311.       Ceiling_Priority  : Integer;
  312.       Compiler_Info     : System.Address;
  313.       Entry_Body        : Entry_Body_Access)
  314.    is
  315.       Init_Priority  : Integer := Ceiling_Priority;
  316.    begin
  317.       if Init_Priority = Unspecified_Priority then
  318.          Init_Priority := System.Priority'Last;
  319.       end if;
  320.  
  321.       STPO.Initialize_Lock (Init_Priority, Object.L'Access);
  322.       Object.Ceiling := System.Any_Priority (Init_Priority);
  323.       Object.Compiler_Info := Compiler_Info;
  324.       Object.Call_In_Progress := null;
  325.       Object.Entry_Body := Entry_Body;
  326.       Object.Entry_Queue := null;
  327.    end Initialize_Protection_Entry;
  328.  
  329.    ----------------
  330.    -- Lock_Entry --
  331.    ----------------
  332.  
  333.    --  Compiler interface only.
  334.    --  Do not call this procedure from within the run-time system.
  335.  
  336.    procedure Lock_Entry (Object : Protection_Entry_Access) is
  337.       Ceiling_Violation : Boolean;
  338.    begin
  339.       STPO.Write_Lock (Object.L'Access, Ceiling_Violation);
  340.  
  341.       if Ceiling_Violation then
  342.          raise Program_Error;
  343.       end if;
  344.    end Lock_Entry;
  345.  
  346.    --------------------------
  347.    -- Lock_Read_Only_Entry --
  348.    --------------------------
  349.  
  350.    --  Compiler interface only.
  351.    --  Do not call this procedure from within the runtime system.
  352.  
  353.    procedure Lock_Read_Only_Entry
  354.      (Object : Protection_Entry_Access)
  355.    is
  356.       Ceiling_Violation : Boolean;
  357.    begin
  358.       STPO.Read_Lock (Object.L'Access, Ceiling_Violation);
  359.  
  360.       if Ceiling_Violation then
  361.          raise Program_Error;
  362.       end if;
  363.    end Lock_Read_Only_Entry;
  364.  
  365.    ------------------
  366.    -- Unlock_Entry --
  367.    ------------------
  368.  
  369.    procedure Unlock_Entry (Object : Protection_Entry_Access) is
  370.    begin
  371.       STPO.Unlock (Object.L'Access);
  372.    end Unlock_Entry;
  373.  
  374.    --------------------
  375.    -- PO_Do_Or_Queue --
  376.    --------------------
  377.  
  378.    procedure PO_Do_Or_Queue
  379.      (Self_Id    : Task_ID;
  380.       Object     : Protection_Entry_Access;
  381.       Entry_Call : Entry_Call_Link);
  382.  
  383.    procedure PO_Service_Entry
  384.      (Self_Id : Task_ID;
  385.       Object  : Protection_Entry_Access);
  386.  
  387.    procedure PO_Do_Or_Queue
  388.      (Self_Id    : Task_ID;
  389.       Object     : Protection_Entry_Access;
  390.       Entry_Call : Entry_Call_Link)
  391.    is
  392.       Barrier_Value     : Boolean;
  393.    begin
  394.       --  When the Action procedure for an entry body returns, it must be
  395.       --  completed (having called [Exceptional_]Complete_Entry_Body).
  396.  
  397.       Barrier_Value := Object.Entry_Body.Barrier (Object.Compiler_Info, 1);
  398.  
  399.       if Barrier_Value then
  400.          if Object.Call_In_Progress /= null then
  401.             --  This violates the No_Entry_Queue restriction, send
  402.             --  Program_Error to the caller.
  403.  
  404.             Send_Program_Error (Self_Id, Entry_Call);
  405.             return;
  406.          end if;
  407.  
  408.          Object.Call_In_Progress := Entry_Call;
  409.  
  410.          pragma Debug
  411.           (Debug.Trace (Self_Id, "PODOQ: start entry body", 'P'));
  412.          Object.Entry_Body.Action
  413.            (Object.Compiler_Info, Entry_Call.Uninterpreted_Data, 1);
  414.  
  415.          Object.Call_In_Progress := null;
  416.          Wakeup_Entry_Caller (Self_Id, Entry_Call, Done);
  417.  
  418.       elsif Entry_Call.Mode /= Conditional_Call then
  419.          Object.Entry_Queue := Entry_Call;
  420.       else
  421.          --  Conditional_Call
  422.  
  423.          STPO.Write_Lock (Entry_Call.Self);
  424.          Wakeup_Entry_Caller (Self_Id, Entry_Call, Cancelled);
  425.          STPO.Unlock (Entry_Call.Self);
  426.       end if;
  427.  
  428.    exception
  429.       when others =>
  430.          Send_Program_Error (Self_Id, Entry_Call);
  431.          return;
  432.    end PO_Do_Or_Queue;
  433.  
  434.    -------------------
  435.    -- Service_Entry --
  436.    -------------------
  437.  
  438.    procedure Service_Entry (Object : Protection_Entry_Access) is
  439.    begin
  440.       PO_Service_Entry (STPO.Self, Object);
  441.    end Service_Entry;
  442.  
  443.    ----------------------
  444.    -- PO_Service_Entry --
  445.    ----------------------
  446.  
  447.    procedure PO_Service_Entry
  448.      (Self_Id : Task_ID;
  449.       Object  : Protection_Entry_Access)
  450.    is
  451.       Entry_Call : Entry_Call_Link;
  452.       Caller     : Task_ID;
  453.       Barrier_Value     : Boolean;
  454.  
  455.    begin
  456.       Entry_Call := Object.Entry_Queue;
  457.  
  458.       if Entry_Call /= null then
  459.          Barrier_Value :=
  460.            Object.Entry_Body.Barrier (Object.Compiler_Info, 1);
  461.  
  462.          if Barrier_Value then
  463.             if Object.Call_In_Progress /= null then
  464.                --  This violates the No_Entry_Queue restriction, send
  465.                --  Program_Error to the caller.
  466.  
  467.                Send_Program_Error (Self_Id, Entry_Call);
  468.                return;
  469.             end if;
  470.  
  471.             Object.Call_In_Progress := Entry_Call;
  472.  
  473.             pragma Debug
  474.              (Debug.Trace (Self_Id, "POSE: start entry body", 'P'));
  475.             Object.Entry_Body.Action
  476.               (Object.Compiler_Info, Entry_Call.Uninterpreted_Data, 1);
  477.  
  478.             Object.Call_In_Progress := null;
  479.             Caller := Entry_Call.Self;
  480.             STPO.Write_Lock (Caller);
  481.             Wakeup_Entry_Caller (Self_Id, Entry_Call, Done);
  482.             STPO.Unlock (Caller);
  483.          end if;
  484.       end if;
  485.  
  486.       exception
  487.          when others =>
  488.             Send_Program_Error (Self_Id, Entry_Call);
  489.             return;
  490.    end PO_Service_Entry;
  491.  
  492.    ---------------------------------
  493.    -- Protected_Single_Entry_Call --
  494.    ---------------------------------
  495.  
  496.    procedure Protected_Single_Entry_Call
  497.      (Object              : Protection_Entry_Access;
  498.       Uninterpreted_Data  : System.Address;
  499.       Mode                : Call_Modes)
  500.    is
  501.       Self_Id             : constant Task_ID := STPO.Self;
  502.       Entry_Call          : Entry_Call_Record renames Self_Id.Entry_Calls (1);
  503.       Ceiling_Violation   : Boolean;
  504.  
  505.    begin
  506.       pragma Debug
  507.         (Debug.Trace (Self_Id, "Protected_Entry_Call", 'P'));
  508.  
  509.       STPO.Write_Lock (Object.L'Access, Ceiling_Violation);
  510.  
  511.       if Ceiling_Violation then
  512.          raise Program_Error;
  513.       end if;
  514.  
  515.       Entry_Call.Mode := Mode;
  516.       Entry_Call.State := Now_Abortable;
  517.       Entry_Call.Prio := STPO.Get_Priority (Self_Id);
  518.       Entry_Call.Uninterpreted_Data := Uninterpreted_Data;
  519.       Entry_Call.Called_PO := To_Address (Object);
  520.       Entry_Call.Exception_To_Raise := Ada.Exceptions.Null_Id;
  521.  
  522.       PO_Do_Or_Queue (Self_Id, Object, Entry_Call'Access);
  523.       Unlock_Entry (Object);
  524.  
  525.       --  The call is either `Done' or not. It cannot be cancelled since there
  526.       --  is no ATC construct.
  527.  
  528.       pragma Assert (Entry_Call.State /= Cancelled);
  529.  
  530.       if Entry_Call.State = Done then
  531.          Check_Exception (Self_Id, Entry_Call'Access);
  532.          return;
  533.       end if;
  534.  
  535.       STPO.Write_Lock (Self_Id);
  536.       Wait_For_Completion (Self_Id, Entry_Call'Access);
  537.       STPO.Unlock (Self_Id);
  538.       Check_Exception (Self_Id, Entry_Call'Access);
  539.    end Protected_Single_Entry_Call;
  540.  
  541.    ---------------------------------------
  542.    -- Timed_Protected_Single_Entry_Call --
  543.    ---------------------------------------
  544.  
  545.    --  Compiler interface only.  Do not call from within the RTS.
  546.  
  547.    procedure Timed_Protected_Single_Entry_Call
  548.      (Object                : Protection_Entry_Access;
  549.       Uninterpreted_Data    : System.Address;
  550.       Timeout               : Duration;
  551.       Mode                  : Delay_Modes;
  552.       Entry_Call_Successful : out Boolean)
  553.    is
  554.       Self_Id           : constant Task_ID  := STPO.Self;
  555.       Entry_Call        : Entry_Call_Record renames Self_Id.Entry_Calls (1);
  556.       Ceiling_Violation : Boolean;
  557.  
  558.    begin
  559.       STPO.Write_Lock (Object.L'Access, Ceiling_Violation);
  560.  
  561.       if Ceiling_Violation then
  562.          raise Program_Error;
  563.       end if;
  564.  
  565.       Entry_Call.Mode := Timed_Call;
  566.       Entry_Call.State := Now_Abortable;
  567.       Entry_Call.Prio := STPO.Get_Priority (Self_Id);
  568.       Entry_Call.Uninterpreted_Data := Uninterpreted_Data;
  569.       Entry_Call.Called_PO := To_Address (Object);
  570.       Entry_Call.Exception_To_Raise := Ada.Exceptions.Null_Id;
  571.  
  572.       PO_Do_Or_Queue (Self_Id, Object, Entry_Call'Access);
  573.       Unlock_Entry (Object);
  574.  
  575.       --  Try to avoid waiting for completed calls.
  576.       --  The call is either `Done' or not. It cannot be cancelled since there
  577.       --  is no ATC construct and the timed wait has not started yet.
  578.  
  579.       pragma Assert (Entry_Call.State /= Cancelled);
  580.  
  581.       if Entry_Call.State = Done then
  582.          Check_Exception (Self_Id, Entry_Call'Access);
  583.          Entry_Call_Successful := True;
  584.          return;
  585.       end if;
  586.  
  587.       Wait_For_Completion_With_Timeout
  588.         (Self_Id, Entry_Call'Access, Timeout, Mode);
  589.  
  590.       pragma Assert (Entry_Call.State >= Done);
  591.  
  592.       Check_Exception (Self_Id, Entry_Call'Access);
  593.       Entry_Call_Successful := Entry_Call.State = Done;
  594.    end Timed_Protected_Single_Entry_Call;
  595.  
  596.    --------------------------------
  597.    -- Complete_Single_Entry_Body --
  598.    --------------------------------
  599.  
  600.    procedure Complete_Single_Entry_Body
  601.      (Object : Protection_Entry_Access) is
  602.    begin
  603.       --  Nothing needs to be done since
  604.       --  Object.Call_In_Progress.Exception_To_Raise has already been set to
  605.       --  Null_Id
  606.  
  607.       null;
  608.    end Complete_Single_Entry_Body;
  609.  
  610.    --------------------------------------------
  611.    -- Exceptional_Complete_Single_Entry_Body --
  612.    --------------------------------------------
  613.  
  614.    procedure Exceptional_Complete_Single_Entry_Body
  615.      (Object : Protection_Entry_Access;
  616.       Ex     : Ada.Exceptions.Exception_Id) is
  617.    begin
  618.       pragma Debug
  619.        (Debug.Trace (STPO.Self, "Exceptional_Complete_Entry_Body", 'P'));
  620.  
  621.       Object.Call_In_Progress.Exception_To_Raise := Ex;
  622.    end Exceptional_Complete_Single_Entry_Body;
  623.  
  624.    ----------------------------
  625.    -- Protected_Single_Count --
  626.    ----------------------------
  627.  
  628.    function Protected_Count_Entry (Object : Protection_Entry)
  629.      return Natural is
  630.    begin
  631.       if Object.Call_In_Progress /= null then
  632.          return 1;
  633.       else
  634.          return 0;
  635.       end if;
  636.    end Protected_Count_Entry;
  637.  
  638.    -----------------------------------
  639.    -- Protected_Single_Entry_Caller --
  640.    -----------------------------------
  641.  
  642.    function Protected_Single_Entry_Caller (Object : Protection_Entry)
  643.      return Task_ID is
  644.    begin
  645.       return Object.Call_In_Progress.Self;
  646.    end Protected_Single_Entry_Caller;
  647.  
  648. end System.Tasking.Protected_Objects.Single_Entry;
  649.  
  650.  
  651.  
  652.  
  653.