+#### `ulock()` and `withULockPtr()`
+
+`Synchronized` also supports upgrading and downgrading mutex lock levels as
+long as the mutex type used to instantiate the `Synchronized` type has the
+same interface as the mutex types in the C++ standard library, or if
+`LockTraits` is specialized for the mutex type and the specialization is
+visible.
+
+An upgrade lock can be acquired as usual either with the `ulock()` method or
+the `withULockPtr()` method as so
+
+``` Cpp
+ {
+ // only const access allowed to the underlying object when an upgrade lock
+ // is acquired
+ auto ulock = vec.ulock();
+ auto newSize = ulock->size();
+ }
+
+ auto newSize = vec.withULockPtr([](auto ulock) {
+ // only const access allowed to the underlying object when an upgrade lock
+ // is acquired
+ return ulock->size();
+ });
+```
+
+An upgrade lock acquired via `ulock()` or `withULockPtr()` can be upgraded or
+downgraded by calling any of the following methods on the `LockedPtr` proxy
+
+* `moveFromUpgradeToWrite()`
+* `moveFromWriteToUpgrade()`
+* `moveFromWriteToShared()`
+* `moveFromUpgradeToShared()`
+
+Calling these leaves the `LockedPtr` object on which the method was called in
+an invalid `null` state and returns another LockedPtr proxy holding the
+specified lock. The upgrade or downgrade is done atomically - the
+`Synchronized` object is never in an unlocked state during the lock state
+transition. For example
+
+``` Cpp
+ auto ulock = obj.ulock();
+ if (ulock->needsUpdate()) {
+ auto wlock = ulock.moveFromUpgradeToWrite();
+
+ // ulock is now null
+
+ wlock->updateObj();
+ }
+```
+
+This "move" can also occur in the context of a `withULockPtr()`
+(`withWLockPtr()` or `withRLockPtr()` work as well!) function as so
+
+``` Cpp
+ auto newSize = obj.withULockPtr([](auto ulock) {
+ if (ulock->needsUpdate()) {
+
+ // release upgrade lock get write lock atomically
+ auto wlock = ulock.moveFromUpgradeToWrite();
+ // ulock is now null
+ wlock->updateObj();
+
+ // release write lock and acquire shared lock atomically
+ auto rlock = wlock.moveFromWriteToShared();
+ // wlock is now null
+ return rlock->newSize();
+
+ } else {
+
+ // release upgrade lock and acquire shared lock atomically
+ auto rlock = ulock.moveFromUpgradeToShared();
+ // ulock is now null
+ return rlock->newSize();
+ }
+ });
+```
+