package body Readers_Writers is

    task body Control is
        Read_Count : Natural := 0;
    begin
        loop
            select
                -- remove the first reader or writer from the queue
                accept Start (Mode : Service) do
                    if Mode = Read then
                        Read_Count := Read_Count + 1;
                    else
                        -- when writer, wait for readers which have already
                        -- started to finish before allowing the writer to
                        -- perform the update
                        while Read_Count > 0 loop
                            -- when a write is pending, readers stop here
                            accept Stop;

                            Read_Count := Read_Count - 1;
                        end loop;
                    end if;
                end Start;

                if Read_Count = 0 then
                    -- when writer, wait for writer to stop before allowing
                    -- other readers or writers to start
                    accept Stop;
                end if;
            or
                -- when no write is pending, readers stop here
                accept Stop;

                Read_Count := Read_Count - 1;
            or
                -- quit when everyone agrees to do so
                terminate;
            end select;
        end loop;
    end Control;

end Readers_Writers;



-- This package allows any number of concurrent programs to read and/or
-- indivisibly write a particular (possibly composite) variable object
-- without interference and in FIFO order.  Similar packages can be
-- constructed to perform partial reads and writes of composite objects.
-- If service cannot be started before the appropriate time limit expires,
-- the exception Timed_Out will be raised.  (By default, service must be
-- started within Duration'Last (24+) hours.  Setting the time limits to
-- 0.0 will require immediate service.)
--