/** * Copyright (C) 2010-2012, FuseSource Corp. All rights reserved. * * http://fusesource.com * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.fusesource.mqtt.client; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; /** * <p> * </p> * * @author <a href="http://hiramchirino.com">Hiram Chirino</a> */ public class Promise<T> implements Callback<T>, Future<T> { private final CountDownLatch latch = new CountDownLatch(1); private Callback<T> next; private Throwable error; private T value; public void onFailure(Throwable value) { Callback<T> callback = null; synchronized(this) { error = value; latch.countDown(); callback = next; } if( callback!=null ) { callback.onFailure(value); } } public void onSuccess(T value) { Callback<T> callback = null; synchronized(this) { this.value = value; latch.countDown(); callback = next; } if( callback!=null ) { callback.onSuccess(value); } } public void then(Callback<T> callback) { boolean fire = false; synchronized(this) { next = callback; if( latch.getCount() == 0 ) { fire = true; } } if( fire ) { if( error!=null ) { callback.onFailure(error); } else { callback.onSuccess(value); } } } public T await(long amount, TimeUnit unit) throws Exception { if( latch.await(amount, unit) ) { return get(); } else { throw new TimeoutException(); } } public T await() throws Exception { latch.await(); return get(); } private T get() throws Exception { Throwable e = error; if( e !=null ) { if( e instanceof RuntimeException ) { throw (RuntimeException) e; } else if( e instanceof Exception) { throw (Exception) e; } else if( e instanceof Error) { throw (Error) e; } else { // don't expect to hit this case. throw new RuntimeException(e); } } return value; } }