===================================================================
@@ -273,7 +273,8 @@ package body GNAT.Sockets is
function Is_Open (S : Selector_Type) return Boolean;
-- Return True for an "open" Selector_Type object, i.e. one for which
- -- Create_Selector has been called and Close_Selector has not been called.
+ -- Create_Selector has been called and Close_Selector has not been called,
+ -- or the null selector.
---------
-- "+" --
@@ -294,6 +295,10 @@ package body GNAT.Sockets is
begin
if not Is_Open (Selector) then
raise Program_Error with "closed selector";
+
+ elsif Selector.Is_Null then
+ raise Program_Error with "null selector";
+
end if;
-- Send one byte to unblock select system call
@@ -491,7 +496,7 @@ package body GNAT.Sockets is
is
Res : C.int;
Last : C.int;
- RSig : constant Socket_Type := Selector.R_Sig_Socket;
+ RSig : Socket_Type := No_Socket;
TVal : aliased Timeval;
TPtr : Timeval_Access;
@@ -511,9 +516,12 @@ package body GNAT.Sockets is
TPtr := TVal'Unchecked_Access;
end if;
- -- Add read signalling socket
+ -- Add read signalling socket, if present
- Set (R_Socket_Set, RSig);
+ if not Selector.Is_Null then
+ RSig := Selector.R_Sig_Socket;
+ Set (R_Socket_Set, RSig);
+ end if;
Last := C.int'Max (C.int'Max (C.int (R_Socket_Set.Last),
C.int (W_Socket_Set.Last)),
@@ -540,7 +548,7 @@ package body GNAT.Sockets is
-- If Select was resumed because of read signalling socket, read this
-- data and remove socket from set.
- if Is_Set (R_Socket_Set, RSig) then
+ if RSig /= No_Socket and then Is_Set (R_Socket_Set, RSig) then
Clear (R_Socket_Set, RSig);
Res := Signalling_Fds.Read (C.int (RSig));
@@ -585,10 +593,9 @@ package body GNAT.Sockets is
procedure Close_Selector (Selector : in out Selector_Type) is
begin
- if not Is_Open (Selector) then
-
- -- Selector already in closed state: nothing to do
+ -- Nothing to do if selector already in closed state
+ if Selector.Is_Null or else not Is_Open (Selector) then
return;
end if;
@@ -1425,14 +1432,19 @@ package body GNAT.Sockets is
function Is_Open (S : Selector_Type) return Boolean is
begin
- -- Either both controlling socket descriptors are valid (case of an
- -- open selector) or neither (case of a closed selector).
+ if S.Is_Null then
+ return True;
+
+ else
+ -- Either both controlling socket descriptors are valid (case of an
+ -- open selector) or neither (case of a closed selector).
- pragma Assert ((S.R_Sig_Socket /= No_Socket)
- =
- (S.W_Sig_Socket /= No_Socket));
+ pragma Assert ((S.R_Sig_Socket /= No_Socket)
+ =
+ (S.W_Sig_Socket /= No_Socket));
- return S.R_Sig_Socket /= No_Socket;
+ return S.R_Sig_Socket /= No_Socket;
+ end if;
end Is_Open;
------------
===================================================================
@@ -422,6 +422,11 @@ package GNAT.Sockets is
type Selector_Access is access all Selector_Type;
-- Selector objects are used to wait for i/o events to occur on sockets
+ Null_Selector : constant Selector_Type;
+ -- The Null_Selector can be used in place of a normal selector without
+ -- having to call Create_Selector if the use of Abort_Selector is not
+ -- required.
+
-- Timeval_Duration is a subtype of Standard.Duration because the full
-- range of Standard.Duration cannot be represented in the equivalent C
-- structure. Moreover, negative values are not allowed to avoid system
@@ -1067,7 +1072,7 @@ package GNAT.Sockets is
-- the situation where a change to the monitored sockets set must be made.
procedure Create_Selector (Selector : out Selector_Type);
- -- Create a new selector
+ -- Initialize (open) a new selector
procedure Close_Selector (Selector : in out Selector_Type);
-- Close Selector and all internal descriptors associated; deallocate any
@@ -1110,7 +1115,8 @@ package GNAT.Sockets is
-- different objects.
procedure Abort_Selector (Selector : Selector_Type);
- -- Send an abort signal to the selector
+ -- Send an abort signal to the selector. The Selector may not be the
+ -- Null_Selector.
type Fd_Set is private;
-- ??? This type must not be used directly, it needs to be visible because
@@ -1126,14 +1132,28 @@ private
type Socket_Type is new Integer;
No_Socket : constant Socket_Type := -1;
- type Selector_Type is limited record
- R_Sig_Socket : Socket_Type := No_Socket;
- W_Sig_Socket : Socket_Type := No_Socket;
- -- Signalling sockets used to abort a select operation
+ -- A selector is either a null selector, which is always "open" and can
+ -- never be aborted, or a regular selector, which is created "closed",
+ -- becomes "open" when Create_Selector is called, and "closed" again when
+ -- Close_Selector is called.
+
+ type Selector_Type (Is_Null : Boolean := False) is limited record
+ case Is_Null is
+ when True =>
+ null;
+
+ when False =>
+ R_Sig_Socket : Socket_Type := No_Socket;
+ W_Sig_Socket : Socket_Type := No_Socket;
+ -- Signalling sockets used to abort a select operation
+
+ end case;
end record;
pragma Volatile (Selector_Type);
+ Null_Selector : constant Selector_Type := (Is_Null => True);
+
type Fd_Set is
new System.Storage_Elements.Storage_Array (1 .. SOSC.SIZEOF_fd_set);
for Fd_Set'Alignment use Interfaces.C.long'Alignment;