Two issues:
Define `bottleneck'.
Called a guard.
What this amounts to is
Server should be lean and hungry
FOREVER {
Receive( );
switch ( )
case courier && XMIT { (Reply, Reply) or enqueue }
case courier && RCV { enqueue or (Reply, Reply) }
case client && XMIT { (Reply, Reply) or enqueue }
case client && RCV { enqueue or (Reply, Reply) }
FOREVER {
Send( secretary )
Send( prop )
}
Generalization of proprietor
Administrator maintains an array of records
Administrator works as he can on any one of the tasks.
Real administrators manage workers
Receive( &bossTid, <initData> );
Reply( bossTid, ... );
FOREVER {
Send( administrator, workResult, order );
doWork( workOrder );
}
Administrator( ) {
Initialize( ); // orderQ, workerQ
for ( i = 0; i < NUM_WORKERS; i++ ) worker[i] = Create( workerCode );
for ( i = 0; i < NUM_WORKERS; i++ ) {
Send( worker[i], initData , ... );
enqueue( workerQ, worker[i] );
}
// RegisterAs
FOREVER {
error = Receive( requester, request );
switch( request.type ) {
case CLIENT: // enqueue w/o or Reply w/o
enqueue( orderQ, workOrder = {requester, request}; {
if( !empty( workerQ ) && available( <resources> ) )
Reply( dequeue( workerQ ), { dequeue( orderQ ), <resources> );
break;
case WORKER: // Reply result, enqueue w'r or Reply w/o
Reply( request.client, request.result );
enqueue( workerQ, requester );
if( !empty( orderQ ) && available( <resources> ))
Reply( dequeue( workerQ ), { dequeue( orderQ ), <resources> } );
break;
}
}
}
Administrator( ) {
Initialize( );
for ( i = 0; i < NUM_WORKERS; i++ ) worker[i] = Create( workerCode );
for ( i = 0; i < NUM_WORKERS; i++ ) Send( worker[i], ... , ... );
// Initialize orderQueue, workerQueue
// RegisterAs
FOREVER {
error = Receive( requester, request );
switch( request.type ) {
case CLIENT:
enqueue ( workfifo, workorder );
while ( !empty( workfifo ) )
if ( complete ( workorder, data ) && workerTid = next( workerQ ) ) {
Reply( client, workerTid, ... );
Reply( worker, workorder );
}
break;
case WORKER:
if( ( workOrder = deQueue( orderQueue) ) ) {
workOrder = {workOrder.client, workOrder.request};
Reply( requester, workOrder );
} else enqueue( workerQueue, requester );
}
}
}
The notifier is a task that waits on events.
It has two features
FOREVER {
AwaitEvent( eventId );
Send( server );
}
You could call a notifier a detective,
In an application there is likely to be lots of waiting on combinations of events.
We use the detective to discover that a complex event has occurred.
Code could be
FOREVER {
Send( part1 );
Send( part2 );
...
Send( master );
}
Code above doesn't work! Try instead
// InitializeDB;
// Create workers and synchronize;
// Synchronize with client;
FOREVER {
Receive( *requester, request );
switch ( reqest.type )
case CLIENT:
insert( reqQ, request );
if ( happened( DB, request ) ) Reply( dequeue( reqQ ), ... );
break;
case WORKER:
update ( DB, request );
// Reply or enquqe requester
foreach request in reqQ
if ( happened( DB, request ) ) Reply( extract( reqQ ), ... );
break;
}
This is the code of a detective.
We can say that an event has not happened yet.
Only at the end of the universe can we say that an event simply has not happened.
Time-outs are needed for NOT
Who is the client of the detective
Housekeeper of the system who will clean up pathologies (Idletask?))
Return to: