release method

void release()

Release a lock.

Release the lock that was previously acquired.

When the lock is released, locks waiting to be acquired can be acquired depending on the type of lock waiting and if other locks have been acquired.

A StateError is thrown if the mutex does not currently have a lock on it.

Implementation

void release() {
  if (_state == -1) {
    // Write lock released
    _state = 0;
  } else if (0 < _state) {
    // Read lock released
    _state--;
  } else if (_state == 0) {
    throw StateError('no lock to release');
  } else {
    assert(false, 'invalid state');
  }

  // If there are jobs waiting and the next job can acquire the mutex,
  // let it acquire it and remove it from the queue.
  //
  // This is a while loop, because there could be multiple jobs on the
  // queue waiting for a read-only mutex. So they can all be allowed to run.

  while (_waiting.isNotEmpty) {
    final nextJob = _waiting.first;
    if (_jobAcquired(nextJob)) {
      _waiting.removeAt(0);
    } else {
      // The next job cannot acquire the mutex. This only occurs when: the
      // the currently running job has a write mutex (_state == -1); or the
      // next job wants write mutex and there is a job currently running
      // (regardless of what type of mutex it has acquired).
      assert(_state < 0 || !nextJob.isRead,
          'unexpected: next job cannot be acquired');
      break; // no more can be removed from the queue
    }
  }
}