@Override
  public void flush() throws IOException {
    //RC: flush is logically a read-op, hence only readLock is needed. But we also need to update
    //    a modified region, which is a write-op.
    //    There are few ways to deal with dirty region updates: e.g. update modifiedRegion with CAS.
    //    Together (readLock + CAS update) implicitly avoids concurrent flushes: by holding readLock
    //    we already ensure nobody _modifies_ page concurrently with us. The only possible contender
    //    is another .flush() call -- and by CAS-ing modifiedRegion to empty _before_ actual
    //    .flushBytes() we ensure such competing .flush() will short-circuit. This is the 'most
    //    concurrent' approach, but it has issues with consistency: namely, storage is notified
    //    about dirty page 'flushed' only after actual CAS updates modifiedRegion to empty. This
    //    means what other thread could see page.isDirty()=false, but at the same time
    //    storage.isDirty() = true, since page flush is not yet propagated to storage. Even worse:
    //    another thread could call page.flush() and still see storage.isDirty()=true -- because
    //    .flush() short-circuits on early .isDirty() check.
    //
    //    This is a trade-off: 'more concurrent' data structures have 'less consistent' state --
    //    basically, state becomes more distributed. But such a tradeoff seems unjustified here:
    //    really, we don't need concurrent flushes, while 'eventually consistent' .isDirty() could
    //    create a lot of confusion for storage users. Hence, I've chosen another approach: use
    //    additional lock inside .flush() to completely avoid concurrent flushes. This lock allows
    //    to reset dirty region _after_ actual .flushBytes().
    //
    //    This still creates an 'inconsistency' though: another thread could see storage.isDirty()
    //    = false, while some page.isDirty()=true -- but I tend to think there are fewer possibilities
    //    for confusion here. Let's see how it goes.
    flushWithReadLock();
  }
@Override
  public void flush()