-- ConnectorImpl.mesa
-- last edited  23-Nov-81 16:51:43 

DIRECTORY
	Connector,
	Scheduler,
	Process;

ConnectorImpl: MONITOR
	IMPORTS Scheduler, Process
	EXPORTS Connector = {

Node: PUBLIC TYPE = RECORD [
  value: REF ANY,
  cond: CONDITION,
  max: CARDINAL ← 0,
  body: SEQUENCE size: [0..LAST[INTEGER]] OF RECORD [
        choice: PrivateChoice,
	ret: CARDINAL,
	direction: {Up, Down, Change}]
  ];
PrivateHandle: TYPE = REF Node;
  
ChoiceNode: PUBLIC TYPE = RECORD [
  response: CARDINAL,
  cond: CONDITION];
PrivateChoice: TYPE = REF ChoiceNode;

CreateChoice: PUBLIC PROC RETURNS [PrivateChoice] = {
	choice: PrivateChoice ← NEW[ChoiceNode];
	Process.DisableTimeout[@choice.cond];
	RETURN[choice]};

RegisterUp: PUBLIC PROC [choice: PrivateChoice, retValue: CARDINAL, port: PrivateHandle] = {
	index: CARDINAL ← port.max ← port.max+1;
	port.body[index] ← [choice, retValue, Up]};

GetChoice: PUBLIC ENTRY PROC [choice: PrivateChoice] RETURNS [CARDINAL] = {
	Scheduler.NotifyQueue[];
	WAIT choice.cond;
	RETURN[choice.response]};

Create: PUBLIC PROC [size: CARDINAL] RETURNS [PrivateHandle] = {
	RETURN[NEW[Node[size]]]};

Put: PUBLIC PROC [n: PrivateHandle, v: REF ANY] = {
--	WF.WF1["Put S:%u ", v];
	StuffIt[n, v];
	WakeUp[n];
--	Scheduler.StandardDelay[];
	Process.Yield[];
--	WF.WF0["Put F "]
	};

Stuff: PUBLIC PROC [n: PrivateHandle, v: REF ANY] = {
--	WF.WF1["  Stuff S:%b ", v];
	StuffIt[n, v];
	WakeUp[n];
	Process.Yield[];
--	WF.WF0["  Stuff F "]
	};

StuffIt: ENTRY PROC [n: PrivateHandle, v: REF ANY] = {
	n.value ← v};

Place: PUBLIC PROC [n: PrivateHandle, v: REF ANY] = {
	StuffIt[n, v];
	};

Get: PUBLIC PROC [n: PrivateHandle] RETURNS [ret: REF ANY] = {
--	WF.WF0["    Get S "];
	ret ← GrabIt[n];
	IF ret=NIL THEN ERROR;
	Process.Yield[]
--	Scheduler.StandardDelay[];
--	WF.WF0["    Get F "]
	};

Grab: PUBLIC ENTRY PROC [n: PrivateHandle] RETURNS [ret: REF ANY] = {
--	WF.WF0["      Grab S"];
	ret ← n.value;
--	WF.WF0["      Grab F "]
	};

GrabIt: ENTRY PROC [n: PrivateHandle] RETURNS[REF ANY] = {
	RETURN[n.value]};

GetNew: PUBLIC PROC [n: PrivateHandle, v: BOOLEAN] = {
--	WF.WF1["        GetNew S:%b ", v];
	Scheduler.StandardDelay[];
	GetNewBody[n, v];
--	WF.WF0["        GetNew F"]
	};

GetNewBody: ENTRY PROC[n: PrivateHandle, v: BOOLEAN] = {
	Scheduler.NotifyQueue[];
	DO
		WAIT n.cond;
		IF v=NARROW[n.value, REF BOOLEAN]↑ THEN EXIT;
		ENDLOOP;
	Scheduler.IncCurrent[];
	};

WakeUp: ENTRY PROC [h: PrivateHandle] = {
	BROADCAST h.cond};


}.