/** * 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; }