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::updatelock
s and
x::vipobj::handlerlock
s.
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::writelock
s and/or
x::vipobj::readlock
s 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::writelock
s and/or
x::vipobj::readlock
s should be released before
invoking notify
(), which does not return until
all registered callback handlers were called.
If any x::vipobj::writelock
s and/or
x::vipobj::readlock
s 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::writelock
s and/or
x::vipobj::readlock
s on the same object.
An x::vipobj::updatelock
only blocks other
x::vipobj::updatelock
s and
x::vipobj::handlerlock
s, and does not affect
x::vipobj::writelock
s and
x::vipobj::readlock
s.
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.