blob: 71ce1bbff9c90e55631821c3e5ea0120fe92b34b [file] [log] [blame]
-- --
-- --
-- G N A T . S O C K E T S . P O L L --
-- --
-- S p e c --
-- --
-- Copyright (C) 2020-2021, AdaCore --
-- --
-- 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 3, 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 --
-- --
-- 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 --
-- <>. --
-- --
-- GNAT was originally developed by the GNAT team at New York University. --
-- Extensive contributions were provided by Ada Core Technologies Inc. --
-- --
-- This package provides an interface to wait for one of a set of sockets to
-- become ready to perform I/O.
with System.OS_Constants;
package GNAT.Sockets.Poll is
type Event_Type is (Input, Output, Error, Hang_Up, Invalid_Request);
-- I/O events we can expect on socket.
-- Input - socket ready to read;
-- Output - socket available for write;
-- Error - socket is in error state;
-- Hang_Up - peer closed;
-- Invalid_Request - invalid socket;
type Event_Set is array (Event_Type) of Boolean;
-- The type to get results on events waiting
subtype Wait_Event_Type is Event_Type range Input .. Output;
type Wait_Event_Set is array (Wait_Event_Type) of Boolean;
-- The type to set events to wait. Note that Error event would be waited
-- anyway.
-- Predefined set of events --
Input_Event : constant Wait_Event_Set;
-- Wait for input availability only
Output_Event : constant Wait_Event_Set;
-- Wait for output availability only
Both_Events : constant Wait_Event_Set;
-- Wait for Input and Output availability
Error_Event : constant Wait_Event_Set;
-- Wait only for error state on socket
type Set (Size : Positive) is private;
-- Set of sockets with I/O event set to wait on
function Create (Size : Positive) return Set;
-- Create empty socket set with defined size
function To_Set
(Socket : Socket_Type;
Events : Wait_Event_Set;
Size : Positive := 1) return Set;
-- Create socket set and put the Socket there at the first place.
-- Events parameter is defining what state of the socket we are going to
-- wait.
procedure Append
(Self : in out Set;
Socket : Socket_Type;
Events : Wait_Event_Set);
-- Add Socket and its I/O waiting state at the end of Self
procedure Insert
(Self : in out Set;
Socket : Socket_Type;
Events : Wait_Event_Set;
Index : Positive;
Keep_Order : Boolean := False);
-- Insert Socket and its I/O waiting state at the Index position.
-- If Keep_Order is True then all next elements moved to the next index up.
-- Otherwise the old element from Index moved to the end of the Self set.
procedure Remove
(Self : in out Set; Index : Positive; Keep_Order : Boolean := False);
-- Remove socket from Index. If Keep_Order is True then move all next
-- elements after removed one to previous index. If Keep_Order is False
-- then move the last element on place of the removed one.
procedure Set_Event
(Self : in out Set;
Index : Positive;
Event : Wait_Event_Type;
Value : Boolean);
-- Set I/O waiting event to Value for the socket at Index position
procedure Set_Events
(Self : in out Set;
Index : Positive;
Events : Wait_Event_Set);
-- Set I/O waiting events for the socket at Index position
function Get_Events
(Self : Set; Index : Positive) return Wait_Event_Set;
-- Get I/O waiting events for the socket at Index position
function Length (Self : Set) return Natural;
-- Get the number of sockets currently in the Self set
function Full (Self : Set) return Boolean;
-- Return True if there is no more space in the Self set for new sockets
procedure Wait (Self : in out Set; Timeout : Duration; Count : out Natural);
-- Wait no longer than Timeout on the socket set for the I/O events.
-- Count output parameter is the number of elements in the Self set are
-- detected for I/O events. Zero Count mean timeout on wait.
-- The iteration over activated elements in set could be done with routine
-- Next. The kind of I/O events on element could be cheched with State or
-- Status routines.
procedure Next (Self : Set; Index : in out Natural);
-- Iterate over set looking for the next index with active I/O event state.
-- Put 0 initially into Index. Each iteration increments Index and then
-- checks for state. End of iterations can be detected by 0 in the Index.
procedure Copy (Source : Set; Target : out Set);
-- Copy sockets and its I/O waiting events from Source set into Target
function Resize (Self : Set; Size : Positive) return Set;
-- Returns the copy of Source with modified Size
function Growth (Self : Set) return Set;
-- Returns the copy of Source with increased Size
function Socket (Self : Set; Index : Positive) return Socket_Type;
-- Returns the Socket from Index position
function Status (Self : Set; Index : Positive) return Event_Set;
-- Returns I/O events detected in previous Wait call at Index position
procedure State
(Self : Set;
Index : Positive;
Socket : out Socket_Type;
Status : out Event_Set);
-- Returns Socket and its I/O events detected in previous Wait call at
-- Index position.
function C_Status
(Self : Set; Index : Positive) return Interfaces.C.unsigned;
-- Return word with I/O events detected flags in previous Wait call at
-- Index position. Possible flags are defined in System.OS_Constants names
-- starting with POLL prefix.
Input_Event : constant Wait_Event_Set := (Input => True, Output => False);
Output_Event : constant Wait_Event_Set := (Input => False, Output => True);
Both_Events : constant Wait_Event_Set := (others => True);
Error_Event : constant Wait_Event_Set := (others => False);
package SOC renames System.OS_Constants;
type nfds_t is mod 2 ** SOC.SIZEOF_nfds_t;
for nfds_t'Size use SOC.SIZEOF_nfds_t;
FD_Type_Bound : constant := 2 ** (SOC.SIZEOF_fd_type - 1);
type FD_Type is range -FD_Type_Bound .. FD_Type_Bound - 1;
for FD_Type'Size use SOC.SIZEOF_fd_type;
type Events_Type is mod 2 ** SOC.SIZEOF_pollfd_events;
for Events_Type'Size use SOC.SIZEOF_pollfd_events;
type Pollfd is record
Socket : FD_Type;
Events : Events_Type := 0;
REvents : Events_Type := 0;
end record with Convention => C;
type Poll_Set is array (Positive range <>) of Pollfd with Convention => C;
type Set (Size : Positive) is record
Length : Natural := 0;
Max_FD : FD_Type := 0;
Max_OK : Boolean;
-- Is the Max_FD actual. It can became inactual after remove socket with
-- Max_FD from set and became actual again after add socket with FD more
-- than Max_FD.
Fds : Poll_Set (1 .. Size);
end record;
function Length (Self : Set) return Natural
is (Self.Length);
function Full (Self : Set) return Boolean
is (Self.Size = Self.Length);
end GNAT.Sockets.Poll;