Controls a resource
Provides mutual exclusion by owning the code that accesses the resource
Proprietor provides service to clients
Like a subroutine call to the client
Monitor | Proprietor | Comments | |
access to resource | localized | localized | Means one at a time. |
service model | self-service | full-service | Easily adapted to multi-core |
service structure | subroutine of client | independent task | Easily adapted to multi-core |
priority | client | probably different | Do we want client priority or resource priority? |
address space | client | separate | Hardware vs software protection |
permissions | client | different | Does client have permission to run certain instructions? |
CPU | same | could be different | Modern hardware works hard to support threads. |
Proprietor begins processing
Can other requests be processed? Possible strategies
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( request.type ) { case CLIENT: parsedRequest = parse( request ); if ( happened( parsedRequest, DB ) ) Reply( requester ); else insert( db, parsedRequest ); break; case WORKER: updateDB ( request ); Reply( requester ); foreach ( queuedRequest ) if ( happened( parsedRequest, DB ) ) { delete( parsedRequest ); Reply( client ); } break; } }
This is the code of a detective.
Initialize; Synchronize with detective; WhoIs( "clockserver" ); FOREVER { Send( detective, {sequence-no, rrrrring}, {sequence-no, time}, ... ); Delay( time ); }
FOREVER { Receive( requester, ... ); switch ( request-type ): case CLIENT: insert( db, {requester, event, time} ); if( !empty( evt-worker-Q ) ) Reply( dequeue( evt-worker-Q ), lookup-event( requester ) ); else { enqueue( evtQ, requester ); Create( event-worker ); } if( !empty( alarm-worker-QQ ) ) Reply( dequeue( alarm-worker-Q ), lookup-time( requester ) ); else { enqueue( evtQ, requester ); Create( alarm-worker ); } break; case EVT_WORKER: update( db, message ); enqueue( event-worker-Q, requester ); if( !empty( evtQ ) ) Reply( dequeue( event-worker-Q ), lookup-event( dequeue( evtQ ) ) ); break; case ALARM_WORKER: update( db, message ); enqueue( alarm-worker-Q, requester ); if( !empty( evtQ ) ) Reply( dequeue( alarm-worker-Q ), lookup-time( dequeue( alarmQ ) ) ); break; } while ( client = ready( db ) ) Reply( client, result ); }
.
Return to: