예제 #1
0
  // Can't throw.
  private void wakeConnectionWaitersLocked() {
    // Unpark all waiters that have requests that we can fulfill.
    // This method is designed to not throw runtime exceptions, although we might send
    // a waiter an exception for it to rethrow.
    ConnectionWaiter predecessor = null;
    ConnectionWaiter waiter = mConnectionWaiterQueue;
    boolean primaryConnectionNotAvailable = false;
    boolean nonPrimaryConnectionNotAvailable = false;
    while (waiter != null) {
      boolean unpark = false;
      if (!mIsOpen) {
        unpark = true;
      } else {
        try {
          SQLiteConnection connection = null;
          if (!waiter.mWantPrimaryConnection && !nonPrimaryConnectionNotAvailable) {
            connection =
                tryAcquireNonPrimaryConnectionLocked(
                    waiter.mSql, waiter.mConnectionFlags); // might throw
            if (connection == null) {
              nonPrimaryConnectionNotAvailable = true;
            }
          }
          if (connection == null && !primaryConnectionNotAvailable) {
            connection = tryAcquirePrimaryConnectionLocked(waiter.mConnectionFlags); // might throw
            if (connection == null) {
              primaryConnectionNotAvailable = true;
            }
          }
          if (connection != null) {
            waiter.mAssignedConnection = connection;
            unpark = true;
          } else if (nonPrimaryConnectionNotAvailable && primaryConnectionNotAvailable) {
            // There are no connections available and the pool is still open.
            // We cannot fulfill any more connection requests, so stop here.
            break;
          }
        } catch (RuntimeException ex) {
          // Let the waiter handle the exception from acquiring a connection.
          waiter.mException = ex;
          unpark = true;
        }
      }

      final ConnectionWaiter successor = waiter.mNext;
      if (unpark) {
        if (predecessor != null) {
          predecessor.mNext = successor;
        } else {
          mConnectionWaiterQueue = successor;
        }
        waiter.mNext = null;

        LockSupport.unpark(waiter.mThread);
      } else {
        predecessor = waiter;
      }
      waiter = successor;
    }
  }
예제 #2
0
  // Can't throw.
  private void cancelConnectionWaiterLocked(ConnectionWaiter waiter) {
    if (waiter.mAssignedConnection != null || waiter.mException != null) {
      // Waiter is done waiting but has not woken up yet.
      return;
    }

    // Waiter must still be waiting.  Dequeue it.
    ConnectionWaiter predecessor = null;
    ConnectionWaiter current = mConnectionWaiterQueue;
    while (current != waiter) {
      assert current != null;
      predecessor = current;
      current = current.mNext;
    }
    if (predecessor != null) {
      predecessor.mNext = waiter.mNext;
    } else {
      mConnectionWaiterQueue = waiter.mNext;
    }

    // Send the waiter an exception and unpark it.
    waiter.mException = new OperationCanceledException();
    LockSupport.unpark(waiter.mThread);

    // Check whether removing this waiter will enable other waiters to make progress.
    wakeConnectionWaitersLocked();
  }
예제 #3
0
 private void recycleConnectionWaiterLocked(ConnectionWaiter waiter) {
   waiter.mNext = mConnectionWaiterPool;
   waiter.mThread = null;
   waiter.mSql = null;
   waiter.mAssignedConnection = null;
   waiter.mException = null;
   waiter.mNonce += 1;
   mConnectionWaiterPool = waiter;
 }