org.chromium.sdk/src/org/chromium/sdk/CallbackSemaphore.java
changeset 2 e4420d2515f1
equal deleted inserted replaced
1:ef76fc2ac88c 2:e4420d2515f1
       
     1 // Copyright (c) 2009 The Chromium Authors. All rights reserved.
       
     2 // Use of this source code is governed by a BSD-style license that can be
       
     3 // found in the LICENSE file.
       
     4 
       
     5 package org.chromium.sdk;
       
     6 
       
     7 import java.util.concurrent.Semaphore;
       
     8 import java.util.concurrent.TimeUnit;
       
     9 
       
    10 import org.chromium.sdk.internal.tools.v8.MethodIsBlockingException;
       
    11 
       
    12 /**
       
    13  * Convenient implementation of {@code SyncCallback}. Client may create one,
       
    14  * then call asynchronous command, and finally wait on blocking method
       
    15  * {@code #tryAcquire()}.
       
    16  */
       
    17 public class CallbackSemaphore implements SyncCallback {
       
    18   public static final long OPERATION_TIMEOUT_MS = 120000;
       
    19 
       
    20   private final Semaphore sem = new Semaphore(0);
       
    21   private Exception savedException;
       
    22 
       
    23   /**
       
    24    * Tries to acquire semaphore with some reasonable default timeout.
       
    25    * @return false if {@code #OPERATION_TIMEOUT_MS} was exceeded and we gave up
       
    26    * @throws MethodIsBlockingException if called from a callback
       
    27    */
       
    28   public boolean tryAcquireDefault() throws MethodIsBlockingException {
       
    29     return tryAcquire(OPERATION_TIMEOUT_MS, TimeUnit.MILLISECONDS);
       
    30   }
       
    31 
       
    32   /**
       
    33    * Tries to acquire the semaphore. This method blocks until the semaphore is
       
    34    * released; typically release call comes from a worker thread of
       
    35    * org.chromium.sdk, the same thread that may call all other callbacks.
       
    36    * It is vital not to call this method from any callback of org.chromium.sdk,
       
    37    * because it's a sure deadlock.
       
    38    * To prevent, this the method declares throwing
       
    39    * {@code MethodIsBlockingException} which is symbolically thrown whenever
       
    40    * someone violates this rule (i.e. invokes this method from a callback).
       
    41    * Though currently nobody actually throws it, such declarations help to
       
    42    * track blocking methods.
       
    43    * @return false if {@code timeout} was exceeded and we gave up
       
    44    * @throws MethodIsBlockingException if called from a callback
       
    45    */
       
    46   public boolean tryAcquire(long timeout, TimeUnit unit) throws MethodIsBlockingException {
       
    47     boolean res;
       
    48     try {
       
    49       res = sem.tryAcquire(timeout, unit);
       
    50     } catch (InterruptedException e) {
       
    51       throw new RuntimeException(e);
       
    52     }
       
    53     if (savedException != null) {
       
    54       throw new RuntimeException("Exception occured in callback", savedException);
       
    55     }
       
    56     return res;
       
    57   }
       
    58   /**
       
    59    * Implementation of {@code SyncCallback#callbackDone(RuntimeException)}.
       
    60    */
       
    61   public void callbackDone(RuntimeException e) {
       
    62     if (e == null) {
       
    63       savedException = null;
       
    64     } else {
       
    65       savedException = new Exception("Exception saved from callback", e);
       
    66     }
       
    67     sem.release();
       
    68   }
       
    69 }