예제 #1
0
  /**
   * Sends a message to an {@link java.util.concurrent.ArrayBlockingQueue#ArrayBlockingQueue(int)
   * ArrayBlockingQueue}, and dispatch messages on the current queue while blocking on the passed in
   * AsyncResult. If maxTimeout > 0 and the cannot get the permission from the semaphore within
   * maxTimeout, throw an error and return.
   *
   * @param message The message to send.
   * @param targetMessenger The TiMessenger to send it to.
   * @param asyncArg argument to be added to the AsyncResult put on the message.
   * @param maxTimeout the maximum time to wait for a permit from the semaphore.
   * @return The getResult() value of the AsyncResult put on the message.
   */
  private Object sendBlockingMessage(
      Message message, TiMessenger targetMessenger, Object asyncArg, final long maxTimeout) {
    @SuppressWarnings("serial")
    AsyncResult wrappedAsyncResult =
        new AsyncResult(asyncArg) {
          @Override
          public Object getResult() {
            int timeout = 0;
            long elapsedTime = 0;
            try {
              // TODO: create a multi-semaphore condition
              // here so we don't unnecessarily poll
              while (!tryAcquire(timeout, TimeUnit.MILLISECONDS)) {
                if (messageQueue.size() == 0) {
                  timeout = 50;
                } else {
                  dispatchPendingMessages();
                }

                elapsedTime += timeout;
                if (maxTimeout > 0 && elapsedTime > maxTimeout) {
                  setException(new Throwable("getResult() has timed out."));
                  break;
                }
              }
            } catch (InterruptedException e) {
              if (Log.isDebugModeEnabled()) {
                Log.e(TAG, "Interrupted waiting for async result", e);
              }
              dispatchPendingMessages();
            }

            if (exception != null && Log.isDebugModeEnabled()) {
              Log.e(TAG, "Unable to get the result from the blocking message.", exception);
            }

            return result;
          }

          @Override
          public void setResult(Object result) {
            super.setResult(result);
          }
        };

    blockingMessageCount.incrementAndGet();
    message.obj = wrappedAsyncResult;
    targetMessenger.sendMessage(message);

    Object messageResult = wrappedAsyncResult.getResult();
    blockingMessageCount.decrementAndGet();
    dispatchPendingMessages();

    return messageResult;
  }