+/*******************************************************************************
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management
+ * in Industry THTH ry.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * VTT Technical Research Centre of Finland - initial API and implementation
+ *******************************************************************************/
+package org.simantics.db.common.procedure;
+
+import java.util.concurrent.Semaphore;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import org.simantics.db.AsyncReadGraph;
+import org.simantics.db.common.utils.Logger;
+import org.simantics.db.exception.DatabaseException;
+import org.simantics.db.procedure.AsyncProcedure;
+
+public class BlockingAsyncProcedure<Result> implements AsyncProcedure<Result> {
+
+ final private Object key;
+ private Result result = null;
+ private Throwable exception = null;
+ final private AsyncProcedure<Result> procedure;
+ final private Semaphore semaphore = new Semaphore(0);
+// final private AtomicBoolean latch;
+
+ public BlockingAsyncProcedure(AsyncProcedure<Result> procedure, Object key) {
+// assert(procedure != null);
+ this.key = key;
+ this.procedure = procedure;
+ if(key == null)
+ System.err.println("asd");
+ //System.err.println("BlockingAsyncProcedure " + key);
+// latch = new AtomicBoolean(false);
+ }
+
+ @Override
+ public void execute(AsyncReadGraph graph, Result result) {
+ this.result = result;
+ semaphore.release();
+// if(latch.compareAndSet(false, true)) {
+ try {
+ if(procedure != null) procedure.execute(graph, result);
+ } catch (Throwable throwable) {
+ Logger.defaultLogError("AsyncProcedure.execute threw for " + procedure, throwable);
+ }
+// } finally {
+//// System.err.println("ResultCallWrappedSingleQueryProcedure4 dec " + key);
+// }
+// } else {
+// Logger.defaultLogError("Procedure was called many times (this time is execute)");
+// }
+ }
+
+ @Override
+ public void exception(AsyncReadGraph graph, Throwable t) {
+ this.exception = t;
+ semaphore.release();
+// if(latch.compareAndSet(false, true)) {
+ try {
+ if(procedure != null) procedure.exception(graph, t);
+ } catch (Throwable throwable) {
+ Logger.defaultLogError("AsyncProcedure.exception threw for " + procedure, throwable);
+ } finally {
+ }
+// } else {
+// Logger.defaultLogError("Procedure was called many times (this time is exception)");
+// }
+
+ }
+
+ public Result get() throws DatabaseException {
+
+ try {
+ boolean success = semaphore.tryAcquire(10, TimeUnit.SECONDS);
+ if(!success) throw new DatabaseException("Timeout while waiting for async request to complete: " + key);
+ } catch (InterruptedException e) {
+ throw new DatabaseException(e);
+ }
+
+ if(exception != null) {
+ if(exception instanceof DatabaseException) throw (DatabaseException)exception;
+ throw new DatabaseException(exception);
+ } else {
+ return result;
+ }
+
+ }
+
+ public Result getResult() {
+ return result;
+ }
+
+ public Throwable getException() {
+ return exception;
+ }
+
+ @Override
+ public String toString() {
+ return "." + procedure;
+ }
+
+}