bool lock(SessionId owner,bool exclusive, unsigned timeout)
 {
     CTimeMon tm(timeout);
     sect.enter();
     loop {
         unsigned num = owners.ordinality();
         if (exclusive) {
             if (num==0) {
                 owners.append(owner);
                 exclusivenest = 1;
                 break;
             }
             else if (exclusivenest && (owners.item(0)==owner)) {
                 exclusivenest++;
                 break;
             }
         }
         else if (!exclusivenest) {
             owners.append(owner);
             break;
         }
         waiting++;
         sect.leave();
         unsigned remaining;
         if (tm.timedout(&remaining)||!sem.wait(remaining)) {
             sect.enter();
             if (!sem.wait(0)) {
                 waiting--;
                 sect.leave();
                 return false;
             }
         }
         else
             sect.enter();
     }
     sect.leave();
     return true;
 }
 void unlock(SessionId owner)
 {
     sect.enter();
     if (exclusivenest) {
         exclusivenest--;
         if (exclusivenest) { // still locked
             assertex(owners.item(0)==owner);
             sect.leave();
             return;
         }
     }
     verifyex(owners.zap(owner));
     if (owners.ordinality()==0) {
         exclusivenest = 0;
         if (waiting) {
             sem.signal(waiting);
             waiting = 0;
         }
     }
     else {
         assertex(!exclusivenest);
     }
     sect.leave();
 }