definition module StdReceiver

//	********************************************************************************
//	Clean Standard Object I/O library.
//	
//	StdReceiver specifies all receiver operations.
//	********************************************************************************

import	StdReceiverDef, StdMaybe
from	iostate	import :: PSt, :: IOSt
from	id		import class ==, :: R2Id, :: RId


//	Open uni- and bi-directional receivers:

class Receivers rdef where
	openReceiver   :: .ls !*(rdef .ls (PSt .l)) !(PSt .l) -> (!ErrorReport,!PSt .l)
	getReceiverType::      *(rdef .ls .pst)               -> ReceiverType
/*	openReceiver
		opens the given receiver if no receiver currently exists with the given 
		R(2)Id. The R(2)Id has to be used to send messages to this receiver. 
	getReceiverType
		returns the type of the receiver (see also getReceivers).
*/

instance Receivers (Receiver  msg)
instance Receivers (Receiver2 msg resp)


closeReceiver			:: !Id !(IOSt .l) -> IOSt .l
/*	closeReceiver closes the indicated uni- or bi-directional receiver.
	Invalid Ids have no effect.
*/

getReceivers			:: !(IOSt .l) -> (![(Id,ReceiverType)], !IOSt .l)
/*	getReceivers returns the Ids and ReceiverTypes of all currently open uni- or 
	bi-directional receivers of this interactive process.
*/

enableReceivers			:: ![Id] !(IOSt .l) ->                      IOSt .l
disableReceivers		:: ![Id] !(IOSt .l) ->                      IOSt .l
getReceiverSelectState	:: ! Id	 !(IOSt .l) -> (!Maybe SelectState,!IOSt .l)
/*	(en/dis)ableReceivers
		(en/dis)able the indicated uni- or bi-directional receivers. 
		Note that this implies that in case of synchronous message passing messages 
		can fail (see the comments of syncSend and syncSend2 below). Invalid Ids 
		have no effect. 
	getReceiverSelectState
		yields the current SelectState of the indicated receiver. In case the 
		receiver does not exist, Nothing is returned.
*/

//	Inter-process communication:

//	Message passing status report:
::	SendReport
	=	SendOk
	|	SendUnknownReceiver
	|	SendUnableReceiver
	|	SendDeadlock
	|	OtherSendReport !String

instance ==       SendReport
instance toString SendReport

asyncSend :: !(RId msg) msg !(PSt .l) -> (!SendReport, !PSt .l)
/*	asyncSend posts a message to the receiver indicated by the argument RId. In case
	the indicated receiver belongs to this process, the message is simply buffered. 
	asyncSend is asynchronous: the message will at some point be received by the 
	indicated receiver. 
	The SendReport can be one of the following alternatives:
	-	SendOk:	No exceptional situation has occurred. The message has been sent. 
				Note that even though the message has been sent, it cannot be 
				guaranteed that the message will actually be handled by the 
				indicated receiver because it might become closed, forever disabled,
				or flooded with synchronous messages.
	-	SendUnknownReceiver:
				The indicated receiver does not exist. 
	-	SendUnableReceiver:
				Does not occur: the message is always buffered, regardless whether 
				the indicated receiver is Able or Unable. Note that in case the 
				receiver never becomes Able, the message will not be handled.
	-	SendDeadlock:
				Does not occur.
*/

syncSend :: !(RId msg) msg !(PSt .l) -> (!SendReport, !PSt .l)
/*	syncSend posts a message to the receiver indicated by the argument RId. In case 
	the indicated receiver belongs to the current process, the corresponding 
	ReceiverFunction is applied directly to the message argument and current process
	state. 
	syncSend is synchronous: this interactive process blocks evaluation until the 
	indicated receiver has received the message. 
	The SendReport can be one of the following alternatives:
	-	SendOk:	No exceptional situation has occurred. The message has been sent and
				handled by the indicated receiver. 
	-	SendUnknownReceiver:
				The indicated receiver does not exist. 
	-	SendUnableReceiver:
				The receiver exists, but its ReceiverSelectState is Unable. 
				Message passing is halted. The message is not sent. 
	-	SendDeadlock:
				The receiver is involved in a synchronous, cyclic communication 
				with the current process. Blocking the current process would result 
				in a deadlock situation. Message passing is halted to circumvent the
				deadlock. The message is not sent.
*/

syncSend2 :: !(R2Id msg resp) msg  !(PSt .l)
	-> (!(!SendReport,!Maybe resp), !PSt .l)
/*	syncSend2 posts a message to the receiver indicated by the argument R2Id. In 
	case the indicated receiver belongs to the current process, the corresponding 
	Receiver2Function is applied directly to the message argument and current 
	process state. 
	syncSend2 is synchronous: this interactive process blocks until the indicated 
	receiver has received the message. 
	The SendReport can be one of the following alternatives:
	-	SendOk:	No exceptional situation has occurred. The message has been sent and
				handled by the indicated receiver. The response of the receiver is 
				returned as well as (Just response).
	-	SendUnknownReceiver:
				The indicated receiver does not exist. 
	-	SendUnableReceiver:
				The receiver exists, but its ReceiverSelect is Unable. 
				Message passing is halted. The message is not sent. 
	-	SendDeadlock:
				The receiver is involved in a synchronous, cyclic communication 
				with the current process. Blocking the current process would result 
				in a deadlock situation. Message passing is halted to circumvent the
				deadlock. The message is not sent.
	In all other cases than SendOk, the optional response is Nothing.
*/
