Deadlock intended for calling enqueue(...).get() from render thread?

I have a situation where makeTask() below can be called from the render thread and also from another thread. This leads to a deadlock when the render thread makes the call (since get() blocks and the task never gets executed). So is this intended behaviour meaning I should refactor my code or can you add a check like when the render thread is calling enquque() the task will be executed direcly instead of adding it to the task queue?



[java] @Override

public void simpleUpdate(float tpf) {

makeTask();

}



@Override

public void run() {

makeTask();

}



public void makeTask() {

try {

enqueue(new Callable<Void>() {



@Override

public Void call() throws Exception {

// TODO Auto-generated method stub

return null;

}



}).get();

} catch (Exception ex) { }

}[/java]

Don’t use get().



Really, I always strongly discourage users from ever using Future.get() because it will only get them into trouble (like you have found yourself in).



Future.get() means “execute this in the background but wait here until it’s done”.

A fast solution, in the initGame do



openglthread = Thread.currentThread()



now in the Task do



if(Thread.equals(Application.openglthread)){

do stuff now,

}else{

enqueue

}

Ok in my example code I don’t return anything but what if I need the actual result from a calculation as soon as possible?

Well, ok then I do that @EmpirePhoenix

Then you will be 1000000000000000000000x happier with an asynchronous event model.



Enqueue the task in one thread, enque the result from the other thread.



The list of caveats for using enqueue() (without get()) is really short. The list of caveats for using get() is as long as my arm (ie: don’t enqueue from the render thread, don’t enqueue from the AWT thread, be super careful with any resources you might be sharing that have synchronization, etc.)



Whenever you block unnecessarily you open yourself up to issues. In my opinion, you should try to block as little as possible.

@douter said:
Ok in my example code I don't return anything but what if I need the actual result from a calculation as soon as possible?

The issue with the blocking is that enqueueing the callable implies that you want to run it on the OpenGL update loop thread. If you at the same time block the update thread to wait for the result it obviously can never be actually run. But if you have to wait for a Future on the same thread where you want the callable to be executed you do something wrong anyway. As @EmpirePhoenix suggested you can just run whatever is in the callable directly then. Though I would not suggest having "auto-enqueueing" going on, ideally you should know what you call from what thread.

Using get() is completely fine if you do your threading right, if you want to be sure it never blocks or causes issues like these, just add a isFinished() check before and you're safe. I don't know what traumatic experience made @pspeed fear get() so much but it must have been bad ;)

So, if you have an external thread that at some point needs current info from the scene graph or needs to do calculations on the update loop, using get() is the quickest way to retrieve your results. It will only block the execution of the external thread until the callable has been run on the update loop and returned its information. Again if you don't want blocking, add a isFinished() check.

It’s not traumatic. Experience has taught me that Future.get() (without isFinished) is usually the sign of inexperience or a badly thought out design.



Even the isFinished() case seems cumbersome to me in the general sense because it requires you to do additional book-keeping and continuing checks when you could have easily extended the same async pattern to handle the results, too.



We aren’t talking about nicely threaded lock-step systems here like you prefer. We’re talking about users poorly implementing a worker pattern. Maybe we need the equivalent of a swing worker for the OpenGL thread (execute in the background then execute in the render thread).

…yeah but Future.get() hasn’t been created to do bad patterns but to get the value off your task ^^ The issue with a “swing worker” is that another thread is supposed to run the payload, not the OpenGL thread. We’d have to provide the whole thread pool infrastructure etc. somehow…

I don’t think this should be jme core, each developer should decide for himself what is the best situation for his usecase, and write the abstractions needed for that. (I for example create a threadpoolexecutor with processors-1 threads for such purposes)

@EmpirePhoenix said:
I don't think this should be jme core, each developer should decide for himself what is the best situation for his usecase, and write the abstractions needed for that. (I for example create a threadpoolexecutor with processors-1 threads for such purposes)


Actually, I do that too. Though recently I've stopped using ThreadPoolExecutor and gone back to home-grown versions of the same thing because ThreadPoolExector swallows exceptions and it requires a lot of work to fix that.