--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/org.chromium.sdk/src/org/chromium/sdk/CallbackSemaphore.java Wed Dec 23 17:13:18 2009 -0800
@@ -0,0 +1,69 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.sdk;
+
+import java.util.concurrent.Semaphore;
+import java.util.concurrent.TimeUnit;
+
+import org.chromium.sdk.internal.tools.v8.MethodIsBlockingException;
+
+/**
+ * Convenient implementation of {@code SyncCallback}. Client may create one,
+ * then call asynchronous command, and finally wait on blocking method
+ * {@code #tryAcquire()}.
+ */
+public class CallbackSemaphore implements SyncCallback {
+ public static final long OPERATION_TIMEOUT_MS = 120000;
+
+ private final Semaphore sem = new Semaphore(0);
+ private Exception savedException;
+
+ /**
+ * Tries to acquire semaphore with some reasonable default timeout.
+ * @return false if {@code #OPERATION_TIMEOUT_MS} was exceeded and we gave up
+ * @throws MethodIsBlockingException if called from a callback
+ */
+ public boolean tryAcquireDefault() throws MethodIsBlockingException {
+ return tryAcquire(OPERATION_TIMEOUT_MS, TimeUnit.MILLISECONDS);
+ }
+
+ /**
+ * Tries to acquire the semaphore. This method blocks until the semaphore is
+ * released; typically release call comes from a worker thread of
+ * org.chromium.sdk, the same thread that may call all other callbacks.
+ * It is vital not to call this method from any callback of org.chromium.sdk,
+ * because it's a sure deadlock.
+ * To prevent, this the method declares throwing
+ * {@code MethodIsBlockingException} which is symbolically thrown whenever
+ * someone violates this rule (i.e. invokes this method from a callback).
+ * Though currently nobody actually throws it, such declarations help to
+ * track blocking methods.
+ * @return false if {@code timeout} was exceeded and we gave up
+ * @throws MethodIsBlockingException if called from a callback
+ */
+ public boolean tryAcquire(long timeout, TimeUnit unit) throws MethodIsBlockingException {
+ boolean res;
+ try {
+ res = sem.tryAcquire(timeout, unit);
+ } catch (InterruptedException e) {
+ throw new RuntimeException(e);
+ }
+ if (savedException != null) {
+ throw new RuntimeException("Exception occured in callback", savedException);
+ }
+ return res;
+ }
+ /**
+ * Implementation of {@code SyncCallback#callbackDone(RuntimeException)}.
+ */
+ public void callbackDone(RuntimeException e) {
+ if (e == null) {
+ savedException = null;
+ } else {
+ savedException = new Exception("Exception saved from callback", e);
+ }
+ sem.release();
+ }
+}
\ No newline at end of file