|
Boost : |
From: Alexander Terekhov (terekhov_at_[hidden])
Date: 2001-08-07 14:04:51
> Could you explain again what you mean by "cleanup handler" semantics
> and why traditional C++ cleanup semantics won't suffice?
e.g. (just an illustration; not real code):
void foo ( )
{
{ // do some synchronized stuff
synch_region_guard srg( mtxLock );
//...
// this_region_cleanup_handler function does:
// a) restore/fix invariants with respect to shared
// data under protection of still locked mtxLock;
// b) enforce early unlock (e.g. srg.synch_exit())
// due to c);
// c) do some heavy stuff (e.g. somecnd.broadcast) w/o
// synchronization in place while doing these final
// operations;
srg.attach_cleanup_handler( this_region_cleanup_handler,.... );
while ( !.... ) // cancelable wait
cndSomeState.wait( mtxLock );
//...
// cleanup handler should become deactivated NOW
// w/o doing any cleanup actions
srg.detach_cleanup_handler();
// w/o srg.detach_ it would still run
// on exit from synch. region (srg.destr
// would invoke cleanup handler function)
//...
}
// do some more non-synchronized stuff
//...
{ // try do some synchronized stuff
synch_region_guard srg( semLock,TRY );
if ( srg.access_granted () ) {
//...
if ( .... ) {
// keep semaphore locked
srg.disable_cleanup();
}
}
else {
//...
}
}
{ // try do some synchronized stuff with synch. timeout
synch_region_guard srg( rwlock,timeout,READ_LOCK );
if ( srg.access_granted() ) {
//...
}
else {
//...
}
}
}
synch_region_guard basically does three things:
1) marks the begin of synch. region -- performs
try/timed/infinite synch. via specified synch
object and specified (or default) synch operation
(with timeout for timed synch);
2) keeps track of optional synch region cleanup handler;
3) on synch region exit performs required cleanup; note
that an optional cleanup handler could enforce early
"unlock" in order to do some heavy stuff (e.g. cnd.broadcast)
w/o synchronization in place while doing these final
operations.
the idea is to match posix cancellation cleanup handlers
with *ONE* C++ object (which would work with all kinds of
locks, semaphores, events, ... any other synchronization
mechanisms); consider the following C example:
void waiting_writer_cleanup(void *arg)
{
rwlock *l;
int do_broadcast;
l = (rwlock *) arg;
do_broadcast = ((--l->waiting_writers == 0) && (l->lock_count >= 0));
pthread_mutex_unlock(&l->lock);
/*
* This only happens if we have been canceled.
*/
if (do_broadcast)
pthread_cond_broadcast(&l->wcond);
}
void lock_for_write(rwlock *l)
{
pthread_mutex_lock(&l->lock);
l->waiting_writers++;
pthread_cleanup_push(waiting_writer_cleanup, l);
while (l->lock_count != 0)
pthread_cond_wait(&l->wcond, &l->lock);
l->lock_count = -1;
/*
* Note the pthread_cleanup_pop executes
* waiting_writer_cleanup.
*/
pthread_cleanup_pop(1);
}
regards,
alexander.
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk