Skip to content

Instantly share code, notes, and snippets.

@lvctr
Last active April 30, 2022 10:17
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save lvctr/66e7e8f1bc30449396c8d87f3f5edc64 to your computer and use it in GitHub Desktop.
Save lvctr/66e7e8f1bc30449396c8d87f3f5edc64 to your computer and use it in GitHub Desktop.
Issues faced while porting pepper-tickle

Problems faced during porting of app pepper-tickle

While porting the Pepper Tickling app from the old Python base to the new Android/Java base, I faced a big problem trying to handle the same Say action amongst multiple asynchronous methods.

Confusion in regards to Futures

Futures are objects that wrap asynchronous methods. It allows for asynchronous processing of code despite writing in a sequential manner. [More on Futures here.]

In the official Pepper API documentation, explanations and examples are provided for the use case where one multiple Futures can be used within a single method in order to chain operations together, but within the use case of pepper-tickle, it was necessary to make use of multiple shared Futures within multiple asynchronous methods, and because REASON THIS IS NOT POSSILE, this was not possible unless we made use of Atomic Variables.

Confusion in regards to Atomic Variables

As previously stated, due to concurrency issues, it is not possible to share Futures within multiple methods via conventional means. In this case, Atomic Variables may be used, which will handle concurrency issues for us.

While Atomic Variables are not at all documented in regards to the Pepper API, fortunately, it is possible to cast an Atomic Reference to a Future making it possible to share Futures within multiple asynchronous methods.

Handling Futures and Atomic Variables in regards to Pepper API

1. Casting Future into an Atomic Reference

Conventionally, this is how one would declare a Future for an action.

Future<Void> sayFuture;

But, this would return an error ERROR HERE when trying to share said Future within multiple asynchronous methods. In order to make it usable, it is necessary to cast it into an Atomic Reference like so.

AtomicReference<Future<Void>> sayFuture;

2. Implementing a helper method to handle chainings and cancellations

In my use case, it was only necessary to have a single Say function to say various different phrases, and it was necessary to be able to cancel it as it is run.

First, I wrote this function with phrase as a parameter. This will run the Say action in a new thread.

public Future<Void> speakNow(QiContext qiContext, Phrase phrase) {
    Future<Say> say = SayBuilder.with(qiContext).withPhrase(phrase).buildAsync();
    Future<Void> sayFuture = null;

    try {
        sayFuture = say.get().async().run();
    } catch (ExecutionException | InterruptedException e) {
        e.printStackTrace();
    }

    return sayFuture;
}

Next, we will implement this function into the actual main codebase. As an example, I will use the head touch sensor.

headTouchSensor.addOnStateChangedListener(touchState -> {
    Log.i("TAG", "Sensor " + (touchState.getTouched() ? "touched" : "released") + " at " + touchState.getTime());
    if (touchState.getTouched()) {
        String randomHand = whichHand();
        gameRunning.set(true);
        sayFuture.get().cancel(true);
        sayFuture.set(speakNow(qiContext, phraseStartGame));
        Log.i("TAG", "Game is now running, correct hand is " + randomHand);
    }
});

Over here, we make use of another Atomic Variable AtomicReference<Boolean> gameRunning which will determine whether the tickle game is still running or not. As you can see, we make use of sayFuture.get().cancel(true); to first cancel the previously running Say action (and if there is none running, it will simply continue), and sayFuture.set(speakNow(qiContext, phraseStartGame)); in order to pass the Say action to the future with the phrase as a parameter in order to run it asynchronously.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment