concurrent interface Bounded_Buffer <Element_Type is Assignable<>; Index_Type is Integer<>> is function Create_Buffer( Max_In_Buffer : Index_Type {Max_In_Buffer > 0}) -> Result : Bounded_Buffer; // Create buffer of given capacity procedure Put(Buffer : queued Bounded_Buffer; Element : Element_Type); // Add element to bounded buffer; // remain queued until there is room // in the buffer. function Get(Buffer : queued Bounded_Buffer) -> Element_Type; // Retrieve next element from bounded buffer; // remain queued until there is an element. end interface Bounded_Buffer;To wait on a Get from two different buffers, you could do this using the select statement in ParaSail:
select var X := Get(Buf1) => ... // use X received from Buf1 || var X := Get(Buf2) => ... // use X received from Buf2 end select;A select statement attempts to perform each of the queued operations concurrently. The first one to become dequeued causes the others to be canceled, and then proceeds to completion.
Time delays are also represented as queued operations on a concurrent object (a clock or a timer):
concurrent interface Clock<Time_Type is Assignable<>> is function Create_Clock(...) -> Clock; function Now(C : locked Clock) -> Time_Type; procedure Delay_Until (C : queued Clock; Wakeup : Time_Type); end interface Clock;Presumably a call of Delay_Until(C, Wakeup_Time) will queue the caller until Now >= Wakeup_Time. A possible implementation of the Delay_Until procedure could use that as its dequeue condition:
concurrent class Clock<Time_Type is Assignable<>> is var Current_Time : Time_Type; ... exports ... function Now(C : locked Clock) -> Time_Type is return Current_Time; end Now; procedure Delay_Until (C : queued Clock; Wakeup : Time_Type) queued until Current_Time >= Wakeup is return; // nothing more to do end Delay_Until; ... end class Clock;We can effectively put a time bound on a select statement by adding an alternative that is a call on an operation like Delay_Until:
select var X := Get(Buf1) => ... || var X := Get(Buf2) => ... || Delay_Until(Next_Time) => ... end select;
The "select" construct does not seem fundamental, as it can effectively be accomplished using a block with multiple threads, where each thread exits with an indication of which call finished first. That indication can then be used to determine what to do next. In general, the "exit ... with" seems adequately flexible to make the special-purpose "select" unnecessary.
ReplyDeleteBottom line: we don't mention the "select" construct in the current ParaSail reference manual (available at https://groups.google.com/forum/#!forum/parasail-programming-language).
The "select" construct has been completely removed from ParaSail, as of 11/2012. Use the "exit ... with" (or "return") construct instead. Both exit and return now support exiting from parallel contexts, automatically terminating the non-exiting/non-returning threads as appropriate (but first waiting for locked operations to complete).
Delete