Skip to content

Commit

Permalink
Expose callback type to promises
Browse files Browse the repository at this point in the history
In libqi, we can specify the "future callback type".

This influences the execution of callbacks: if the type is
Sync, then the callback is executed synchronously during setValue(…) or
then(…)/andThen(…). Otherwise, it is executed asynchronously.

For example:

    Promise<String> promise = new Promise<>(FutureCallbackType.Sync);
    System.out.println("#0");
    promise.getFuture().andThen(new QiCallback<String>() {
        @OverRide
        public void onResult(String result) {
            // executed in the same thread
            System.out.println("#2");
        }
    });
    System.out.println("#1");
    promise.setValue("hello");
    System.out.println("#3");

This code sample prints:

    #0
    #1
    #2
    #3

Change-Id: I732a76070a7ec67b58c1e666f0e538571689fede
Reviewed-on: http://gerrit.aldebaran.lan/72640
Reviewed-by: rvimont <[email protected]>
Tested-by: gerrit
Reviewed-by: epinault <[email protected]>
  • Loading branch information
rom1v authored and Erwan Pinault committed Dec 16, 2016
1 parent bd492dd commit 898daf1
Show file tree
Hide file tree
Showing 5 changed files with 59 additions and 6 deletions.
2 changes: 1 addition & 1 deletion jni/jni/promise_jni.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ extern "C" {
* Signature: ()J
*/
JNIEXPORT jlong JNICALL Java_com_aldebaran_qi_Promise__1newPromise
(JNIEnv *, jobject);
(JNIEnv *, jobject, jint);

/*
* Class: com_aldebaran_qi_Promise
Expand Down
5 changes: 3 additions & 2 deletions jni/src/promise_jni.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,10 @@ qiLogCategory("qimessaging.java");
* Signature: ()J
*/
JNIEXPORT jlong JNICALL Java_com_aldebaran_qi_Promise__1newPromise
(JNIEnv *QI_UNUSED(env), jobject QI_UNUSED(obj))
(JNIEnv *QI_UNUSED(env), jobject QI_UNUSED(obj), jint futureCallbackType)
{
auto promisePtr = new qi::Promise<qi::AnyValue>();
qi::FutureCallbackType type = static_cast<qi::FutureCallbackType>(futureCallbackType);
auto promisePtr = new qi::Promise<qi::AnyValue>(type);
return reinterpret_cast<jlong>(promisePtr);
}

Expand Down
14 changes: 14 additions & 0 deletions qimessaging/src/main/java/com/aldebaran/qi/FutureCallbackType.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.aldebaran.qi;

public enum FutureCallbackType
{
// keep values synchronized with qi::FutureCallbackType in libqi/qi/detail/future_fwd.hpp
Sync(0), Async(1), Auto(2);

int nativeValue;

private FutureCallbackType(int nativeValue)
{
this.nativeValue = nativeValue;
}
}
11 changes: 8 additions & 3 deletions qimessaging/src/main/java/com/aldebaran/qi/Promise.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,17 @@ public class Promise<T>

private Future<T> future;

public Promise()
public Promise(FutureCallbackType type)
{
promisePtr = _newPromise();
promisePtr = _newPromise(type.nativeValue);
future = new Future<T>(_getFuture(promisePtr));
}

public Promise()
{
this(FutureCallbackType.Auto);
}

public Future<T> getFuture()
{
return future;
Expand Down Expand Up @@ -75,7 +80,7 @@ public void onCancel() throws Exception
});
}

private native long _newPromise();
private native long _newPromise(int futureCallbackType);

private native long _getFuture(long promisePtr);

Expand Down
33 changes: 33 additions & 0 deletions qimessaging/src/test/java/com/aldebaran/qi/PromiseTest.java
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
package com.aldebaran.qi;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicLong;

import org.junit.Assert;
import org.junit.Test;
Expand Down Expand Up @@ -70,4 +72,35 @@ public void run()
int value = future.get();
Assert.assertEquals(42, value);
}

public static boolean isCallbackExecutedOnSameThread(FutureCallbackType futureCallbackType) throws InterruptedException
{
Promise<Void> promise = new Promise<Void>(futureCallbackType);
promise.setValue(null);
final CountDownLatch countDownLatch = new CountDownLatch(1);
final AtomicLong callbackThreadId = new AtomicLong();
promise.getFuture().andThen(new QiCallback<Void>()
{
@Override
public void onResult(Void result)
{
callbackThreadId.set(Thread.currentThread().getId());
countDownLatch.countDown();
}
});
countDownLatch.await();
return Thread.currentThread().getId() == callbackThreadId.get();
}

@Test
public void testAsyncType() throws InterruptedException
{
Assert.assertFalse(isCallbackExecutedOnSameThread(FutureCallbackType.Async));
}

@Test
public void testSyncType() throws InterruptedException
{
Assert.assertTrue(isCallbackExecutedOnSameThread(FutureCallbackType.Sync));
}
}

0 comments on commit 898daf1

Please sign in to comment.