vip_t::updatelock u(vip); { vip_t::writelock w(vip); // ... w->n=4; } vipintvalue val=*vip_t::readlock(vip); u.notify(val);
An x::vipobj::updatelock implements a formal
notification mechanism for very important objects.
Only one x::vipobj::updatelock may exist
concurrently, and it blocks all other
x::vipobj::updatelocks and
x::vipobj::handlerlocks.
A x::vipobj::updatelock is not a write lock,
and does not offer any access to the underlying very important
object. After instantiating a
x::vipobj::updatelock, use other
x::vipobj::writelocks and/or
x::vipobj::readlocks to access the underlying
very important object.
notify() invokes all registered callbacks.
The argument to notify() is the very important
object's value to report to all registered callbacks.
All x::vipobj::writelocks and/or
x::vipobj::readlocks should be released before
invoking notify(), which does not return until
all registered callback handlers were called.
If any x::vipobj::writelocks and/or
x::vipobj::readlocks still remain in scope,
they will remain in scope while all the callback handlers get invoked,
and affect their access to the underlying very important object.
It's preferrable to have the callback handlers refer to the value they
receive as an argument; although nothing stops the callbacks from
instantiating and using their own
x::vipobj::writelocks and/or
x::vipobj::readlocks on the same object.
An x::vipobj::updatelock only blocks other
x::vipobj::updatelocks and
x::vipobj::handlerlocks, and does not affect
x::vipobj::writelocks and
x::vipobj::readlocks.
In particular, while an
x::vipobj::updatelock gets held, nothing
prevents another thread from acquiring a
x::vipobj::writelock and modifying the
very important object's value.
A x::vipobj::updatelock merely assures that
reportable updates of a very important objects are synchronized.
In most cases, the usual convention is to always obtain an
x::vipobj::updatelock, followed by
a x::vipobj::writelock, use to modify the
very important object, release the write lock, invoke
notify(), and then release the update lock.
If the very important object does not end up getting modified,
notify() does not need to get called, so
release both locks, and proceed on your way.
One way to think of it is that the update lock and the write lock implement parallel “tracks” for updating very important objects. The update lock is for changes that must be reported to all registered handlers. The write lock is for changes to the very important object that do not require any notification.
vip_t::updatelock u(vip); vipintvalue val=*vip_t::readlock(vip); val.n += 2; u.update(val);
The update() method is a convenience function that:
Acquires a x::vipobj::writelock.
Invokes the very important object's assignment operator, giving it
the value passed as an argument to update(),
basically “assigning” a new value to the object.
Releases the x::vipobj::writelock.
Invokes notify(), passing it the value given
to update() as an argument.