An update lock

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.

Note

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: