Writer locks

hierclass::base::writerlock lock=h->create_writelock();

A writer lock implements all methods that a reader lock does, and is type-convertible to a reader lock. The sole exception is that the writer lock's clone() throws an exception (this applies to the writer lock that gets accessed as a reader lock, too).

Only one writer lock can exist at a time, create_writelock() waits until no other reader or writer locks exist, before it returns. This is why its clone() throws an exception, since another lock cannot exist until the writer lock itself goes away.

bool flag=lock->insert([]
                      {
                          return valueRef::create();
                      }, key,
                      []
                      (valueRef &&existing)
                      {
                          return false;
                      });

insert() adds or replaces a value in the hierarchical container. The second parameter is a hierarchical key relative to the writer lock's current node. create_writelock(), like create_readlock(), constructs a lock initially referring to the hierarchy's root node, in which case the key specifies the absolute container key. However, the writer lock implements all of reader lock's to_child() and to_parent() methods, to reposition the writer lock to any existing key in the container. The key parameter to insert() gets interpreted relative to the writer lock's current node position. An empty list refers to the writer lock's current position.

The first parameter to insert() is a lambda or a functor that returns the new value for the container, an x::ref value. insert() calls it to obtain the value to install for the referenced key. If the referenced key already has a value, the third parameter determines whether the existing value gets replaced, or not.

The third parameter to insert() is also a lambda or a functor. It receives the key's existing value, as an rvalue reference. Returning true replaces the existing value in the container. The first lambda/functor gets called to obtain the new value for the key. Returning false does not replace the existing value in the container.

The first lamba/functor parameter to insert() does not get invoked if there's already an existing value for the referenced key, and the third lambda/functor parameter returns false.

bool flag=lock->erase(key);

bool flag=lock->prune(key);

bool flag=lock->prune_if(key, []
                              (valueRef &&value, const key &name)
                              {
                                  return true;
                              });

erase() removes an existing key from the container. key specifies a hierarchical key, relative to the writer lock's current node (an empty list for the current node). erase() returns false if the referenced key did not have a value in the container. If the key had a value, erase() returns true after changing the writer node's current position to the removed key's closest parent node that has a value, or to the container's root node.

erase() removes only the referenced key's value, and does not remove the values for any existing inferior child nodes (the referenced key becomes an intermediate node). prune() removes all inferior nodes of the referenced key, but does not erase the value for the referenced key. If the referenced key exists, when prune() returns the writer lock's current node becomes the referenced key, otherwise it current node becomes the closest parent with a value (or the root node).

prune_if() calls the lambda/functor before pruning each individual inferior node, with two parameters: the value itself, and its full container key. If the lamba/functor returns true the value gets removed, otherwise it does not get removed from the container.

prune() is equivalent to prune_if() with the functor always returning true.

bool flag=lock->erase();

bool flag=lock->prune();

This is equivalent to specifying a key that's an empty list: the erasure/prune for the writer lock's current node.