definition module scheduler


//	********************************************************************************
//	Clean Standard Object I/O library.
//	
//	Process creation, termination, and handling functions.
//	********************************************************************************

import	StdString
import	deviceevents, StdMaybe
import	osevent, ostime, ostoolbox
from	id				import :: Id
from	iostate			import :: PSt, :: CProcess, :: CProcesses, :: RR
from	receivertable	import :: ReceiverTable
from	processstack	import :: ProcessKind, :: ProcessStack, :: ProcessShowState
from	systemid		import :: SystemId
from	StdIOCommon		import :: ProcessAttribute, :: IdFun
from	StdProcessDef	import :: DocumentInterface, :: ProcessInit


::	*Environs
	=	{	envsEvents		:: !*OSEvents
		,	envsWorld		:: !*World
		}
::	*Context	// DvA: can be made abstract if we move modalDialogExists from windowcreate to here...
	=	{	cEnvs			:: !*Environs			// The global environments
		,	cProcessStack	:: !ProcessStack		// The global process stack
		,	cMaxIONr		:: !SystemId			// The global maximum system number
		,	cProcesses		:: !*CProcesses			// All processes
		,	cModalProcess	:: !Maybe SystemId		// The SystemId of the interactive process that has a modal window
		,	cReceiverTable	:: !*ReceiverTable		// The global receiver-process table
		,	cTimerTable		:: !*TimerTable			// The table of all currently active timers
		,	cIdTable		:: !*IdTable			// The table of all bound Ids
		,	cOSTime			:: !OSTime				// The current OSTime
		,	cIdSeed			:: !Int					// The global id generating number (actually the World)
		,	cOSToolbox		:: !*OSToolbox			// The toolbox environment
		}

initContext		:: !*(ProcessInit (PSt .l)) !String !.l !DocumentInterface !ProcessKind !*World -> (!Context,!*OSToolbox)
/*	Generate an initial Context, given the initial actions, state, and (document/process)kind of an interactive
	process, and World.
*/
initContext`	:: !*World -> (!Context,!*OSToolbox)

handleEvents	:: !Context !*OSToolbox -> (!Context,!*OSToolbox)
/*	Consecutively handle events until termination of all interactive processes.
*/

chandleEvents :: !(St Context Bool) !Context !*OSToolbox -> (!Context,!*OSToolbox)
/*	chandleEvents consecutively handles events while condition holds.
*/

handleContextOSEvent :: !OSEvent !Context -> (![Int],!Context)
/*	Handle one OSEvent. Context MUST not be a final context, otherwise a runtime error occurs!
*/

closeContext	:: !Context !*OSToolbox -> *World
/*	Retrieve the final World value from the Context. Context MUST be a final context, otherwise a runtime error occurs!
*/


handleOneEventForDevices :: !SchedulerEvent !(PSt .l) -> (!Bool,!SchedulerEvent,!PSt .l)
/*	Apply the given event to all devices in the current interactive process.
	The Boolean result indicates whether one of the devices actually handled the event.
	The DeviceEvent result may contain a response of type [o], or an error indication.
*/


addVirtualProcess		:: !*(ProcessInit (PSt .l)) String .l !(PSt .l`) -> PSt .l`
/*	addVirtualProcess adds a process to the process administration as a virtual process.
	For virtual processes no initial devices are created. If the initial actions of the
	virtual process attempt to create a device instance this results in a runtime error.
	Virtual processes always share the GUI of their parent process. Termination is
	detected and handled by the system.
*/

ShareGUI			:==	True
NotShareGUI			:==	False

addInteractiveProcess	:: ![ProcessAttribute (PSt .l)] !*(ProcessInit (PSt .l)) String .l 
							!Bool !DocumentInterface !(PSt .l`) -> PSt .l`
/*	addInteractiveProcess adds a process to the process administration as an interactive process.
	For interactive processes initial devices are created. 
	The Boolean argument determines whether the process shares (ShareGUI) or not shares 
	(NotShareGUI) the GUI of the current process. If it does, then the current process
	becomes the parent process of the new process, and the new process its child.
*/


quitProcess			:: !(PSt .l) -> PSt .l
/*	QuitProcess removes all abstract devices that are held in the interactive process
	and takes care that all processes that share its GUI are also terminated recursively.
	The resulting IOSt is a terminal value and will be removed from the process administration.
*/


//	Context-switching operations:

::	SwitchError
	=	SwitchToYourself
	|	SwitchToDoesNotExist
	|	SwitchToReceiverDoesNotExist
	|	SwitchReceiverUnable
	|	SwitchEndsUpInDeadlock

cswitchProcess :: !SystemId !SchedulerEvent !(PSt .l) -> (!Maybe SwitchError, ![SemiDynamic], !PSt .l)
/*	cswitchProcess processId msgEvent pstate switches to PSt identified by processId, lets that process 
	handle the msgEvent, and switches back to pstate.
	Nothing SwitchError is returned if no exceptions were detected. 
	Exceptions are:
	-	SwitchToYourself:				processId is the current PSt. 
	-	SwitchToDoesNotExist:			no current process can be identified by processId. 
	-	SwitchToReceiverDoesNotExist:	process  exists, but receiver doesn't.
	-	SwitchReceiverUnable:			receiver exists, but is not Able.
	-	SwitchEndsUpInDeadlock:			if this process would block for the process with 
										id processId to get unblocked, a deadlock would occur.
	In all exceptional cases the PSt remains unchanged.
	Observe that in case Nothing is returned, the ps PSt component may have changed value.
*/

appContext :: !.(IdFun Context) !(PSt .l) -> PSt .l
accContext :: !.(St Context .x) !(PSt .l) -> (!.x, !PSt .l)
/*	(app/acc)Context applies the Context access function to the switched out process state (which creates a
	Context value), and switches back to the process state. The Context access function must not
	remove the argument process, otherwise a run-time error will occur!
*/


//	Function threading operations:

::	Result r
	:==	(	!Bool			//	object is found
		,	!Maybe r		//	optional access information
		)

accessLocals :: !(St CProcess (Result r)) !*CProcesses -> (!Result r,!*CProcesses)
/*	Let f::(IOSt .l .p) -> (Result r,IOSt .l .p) be an IOSt access function. 
	To thread f through *CProcesses until fst(fst(f io)), define gLocals as follows:
	
		gLocals :: *CProcesses -> (Result r, *CProcesses)
		gLocals locals = accessLocals f` locals
		where	f` localIO	= (r,{localIO & localIOSt=ioState})
				where	(r,ioState)	= f localIO.localIOSt
*/
