How can I tell if the current code is run inside executeBlocking (vert.x 3)?

1,457 views
Skip to first unread message

Jochen Bedersdorfer

unread,
Apr 14, 2015, 10:49:46 PM4/14/15
to ve...@googlegroups.com
Is there a function similar to isEventLoopContext or isWorker to figure out if the current closure is running in blocking mode?

I'm running this code in the closure: 

        console.log("in event loop? " + vertx.getOrCreateContext().isEventLoopContext());
        console.log("in worker? " + vertx.getOrCreateContext().isWorker());
        console.log("in multi worker?" + vertx.getOrCreateContext().isMultiThreaded());

and it prints:

in event loop? true
in worker? false
in multi worker?false

(Not sure what multiThreaded means)

The docs are stating:
"In the case of worker verticles and running inline blocking code a worker context will be associated with the execution which will use a thread from the worker thread pool."

Am I missing anything? (which I assume, since I haven't played around with vert.x in quite a while and still adapting to the vert.x 3 changes)

Thanks,
  Jochen


Jordan Halterman

unread,
Apr 15, 2015, 4:41:28 AM4/15/15
to ve...@googlegroups.com
I think you left out some context.

Why would you think you missed something? Is the closure being run in a worker verticle where you expect to see "in worker? true" or something?

If the handler - e.g. an event bus handler - was registered inside a worker then it will always be executed on a thread from the worker pool since it "belongs" to the worker that registered it. Similarly, if the handler was registered in an event loop verticle then it will always be called on the same event loop thread in which it was registered. But if the handler is registered outside any verticle AFAIK it will be executed on an event loop thread.

That is, handlers are called in the context (thread for event loops or thread pool for workers) in which they're registered.

I'm not sure what you mean by "blocking mode." Assuming you mean a context in which blocking is okay, isWorker will tell you that. But Vert.x follows well defined patterns in executing callbacks, so you should generally be able to make assumptions about the context in most scenarios without having to explicitly check the Context.

Think of Context in terms of threads and the isWorker method as returning a boolean that indicates whether the current thread is a worker thread. If isWorker returns true then it's safe to perform blocking operations.

You can read about multi-threaded workers in the documentation. Multi-threaded is a worker deployment option that's generally only recommended for advanced use cases because enabling that option requires that you - the user - enforce thread safety. I would strongly advise against it if you don't have a thorough understanding of concurrency in Java.
--
You received this message because you are subscribed to the Google Groups "vert.x" group.
To unsubscribe from this group and stop receiving emails from it, send an email to vertx+un...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Julien Viet

unread,
Apr 15, 2015, 5:15:21 AM4/15/15
to ve...@googlegroups.com, Jordan Halterman
today this is misleading in Vert.x 3

since there is ability to run blocking code in an event loop context and so to have a worker thread using an event loop context, so this

    Vertx vertx = Vertx.vertx();
    vertx.runOnContext(v -> {
      Context ctx = vertx.getOrCreateContext();
      System.out.println(Thread.currentThread() + ":" + ctx.isWorker());
      vertx.executeBlocking(fut -> {
        System.out.println(Thread.currentThread() + ":" + ctx.isWorker());
      }, ar -> {
      });
    });

prints
      
Thread[vert.x-eventloop-thread-0,5,main]:false
Thread[vert.x-worker-thread-0,5,main]:false

-- 
Julien Viet
www.julienviet.com

Jochen Bedersdorfer

unread,
Apr 15, 2015, 2:00:55 PM4/15/15
to ve...@googlegroups.com
Well, if I execute vertx.executeBlocking(myClosure);
myClosure is not run in the event loop thread.
It seems it is also not run in a worker thread.
I would like myClosure be able to detect if blocking is ok or not, basically.
I guess I could look at Thread.currentThread(); but that seems silly.

My use case is having a legacy API I would like to support in both synchronous as well as asynchronous mode without having to maintain two different yet very very similar code bases.
(essentially, there are only two methods I need to change that would either return the final result (in blocking mode) or a Promise/Future (in non-blocking mode).

Hope that explains it better.

Thanks,
 Jochen

Jordan Halterman

unread,
Apr 15, 2015, 5:16:11 PM4/15/15
to ve...@googlegroups.com
I see. That makes sense.

I'm not totally familiar with that part of the code base, but it looks (from a quick glance at the code) like calls to the public executeBlocking method are run on the worker pool. Are all of the is* methods returning false? I can definitely see how it would make sense for something to indicate it's safe to block. It seems like isWorker returning true would suffice. Might need to file a bug report if that's not what it does or if the threads seem unpredictable.

I haven't finished reading the event loop docs yet Julien (awesome idea BTW), but I guess that documentation may also include context for executeBlocking. AFAIK for the user it's a worker thread, and internal blocking APIs use a separate pool, but I could be wrong.

Tim Fox

unread,
Apr 16, 2015, 3:04:15 AM4/16/15
to ve...@googlegroups.com
On 15/04/15 19:00, 'Jochen Bedersdorfer' via vert.x wrote:
Well, if I execute vertx.executeBlocking(myClosure);
myClosure is not run in the event loop thread.
It seems it is also not run in a worker thread.
I would like myClosure be able to detect if blocking is ok or not, basically.
I guess I could look at Thread.currentThread(); but that seems silly.

My use case is having a legacy API I would like to support in both synchronous as well as asynchronous mode without having to maintain two different yet very very similar code bases.
(essentially, there are only two methods I need to change that would either return the final result (in blocking mode) or a Promise/Future (in non-blocking mode).

Could you explain this use case a bit more? I don't think I have understood it yet.

Jochen Bedersdorfer

unread,
Apr 16, 2015, 12:55:20 PM4/16/15
to ve...@googlegroups.com
Hi Tim,

the general use case would be: Can I figure out the context I'm running in? There seem to be 3 now (or 4?):
- running in the event loop thread
- running in a worker thread
- running in a separate set of threads fed by vertx.executeBlocking 

In the third case vertx.getOrCreateContext().isEventLoopContext()will return true, which is a bit surprising as the closure is run in a separate thread.

In my specific use case I have a rather complex legacy JavaScript API and my users have written code against that API (which uses blocking I/O). 
I'm trying to move away from grails (shudder) to vert.x 3 and still be able to support code my users have written(think of that code as something like 'stored procedures' which can be uploaded and run by users) while offering basically the same API in non-blocking mode as well. 

I solved it by changing my API for now, but nevertheless, I think the general use case is a valid one. What do you think?

Cheers,
 Jochen

Tim Fox

unread,
Apr 16, 2015, 12:58:09 PM4/16/15
to ve...@googlegroups.com
I understand you want to know what kind of thread you're running on, the question is "why?".

Jochen Bedersdorfer

unread,
Apr 16, 2015, 1:57:50 PM4/16/15
to ve...@googlegroups.com
So I can switch the behavior of my code if I want to. 
Why do you have vertx.getOrCreateContext().isEventLoopContext()?

If you think code shouldn't care in what particular context it is running, that is fine, but if you provide a facility to detect context at runtime, returning true for that method call if you are running inside  vertx.executeBlocking is misleading. 
The documentation of executeBlocking says: Executes the blocking code in the handler {@code blockingCodeHandler} using a thread from the worker pool.
which is also actually not the case. The code is executed by the orderedInternalPoolExec

The ask here is to either correct the documentation or have isEventLoopContext return false and isWorker return true in that case or have an orthogonal canBlockIO();

Tim Fox

unread,
Apr 17, 2015, 3:06:34 AM4/17/15
to ve...@googlegroups.com
On 16/04/15 18:57, 'Jochen Bedersdorfer' via vert.x wrote:
So I can switch the behavior of my code if I want to. 
Why do you have vertx.getOrCreateContext().isEventLoopContext()?

If you think code shouldn't care in what particular context it is running,

I'm not saying that, I'm just trying to understand your use case, and issue. That's just the way I like to approach potential issues :)

Quite often posts jump straight to a solution without first describing the issue or the use case. I prefer to forget the solution at first and really try to understand _why_ you are doing it that way. Once that has been understood, perhaps there is a better way of doing it that avoids the issue, or perhaps its really just a non issue.

If after that, there really is an issue there then we start to talk about solutions.

Can you give me a concrete example of why your code needs to know if it's running on an event loop or not? (Something more than 'So I can switch the behavior of my code if I want to' ;) )


that is fine, but if you provide a facility to detect context at runtime, returning true for that method call if you are running inside  vertx.executeBlocking is misleading.

I think the current behaviour is correct. If you have a standard verticle that calls executeBlocking, then there is no new context created for the blocking code, the context of that is still the standard verticle, so it's still an event loop context. This is important so if you do something like vertx.runOnContext() from inside the blocking code that causes the result to be run on the event loop.


The documentation of executeBlocking says: Executes the blocking code in the handler {@code blockingCodeHandler} using a thread from the worker pool.
which is also actually not the case. The code is executed by the orderedInternalPoolExec

Julien Viet

unread,
Apr 17, 2015, 7:48:33 AM4/17/15
to ve...@googlegroups.com
Hi Tim,

one issue I see with using the same context is that the event loop context map for get/put/remove context operation uses a simple hashmap and it should be instead a concurrent hashmap like in the worker context.

Jochen Bedersdorfer

unread,
Apr 17, 2015, 1:59:52 PM4/17/15
to ve...@googlegroups.com
I'm sorry, Tim.
It must be my lack of language skills that I can't explain the use case properly.

I'm maintaining a rather large API (currently running deep inside a grails app) and I want to use that same API (written in JS) with vert.x.
Depending on context, I want some of the functions of this API to either return a Promise or the final value.
Note that I have three environments to support: Grails (blocking I/O), Vert.x (blocking I/O and non-blocking I/O).
That would have been very easy to do if I could detect the context from within that API.
I was hoping I could use Context for that.

(You are right, internal is false when called from user code (my bad). Yet, console.log("in worker? " + vertx.getOrCreateContext().isWorker()); will return false, which is still confusing)

So the answer seems to be that right now: I can't detect that particular context, so I'll go and run the same code on a proper worker thread and use .isWorker().

Thanks for your help
 Jochen

yahim stnsc

unread,
Feb 23, 2017, 1:19:20 PM2/23/17
to vert.x
Hi all,

I've just hit the same problem.

Well, my concrete problem is that i want to prevent miss-usage in the following case.

I would like to have a synchronous API when called from worker verticles and an asynchronous API for when called from event loop verticles and i just want to guarantee the usage.

Julien Viet

unread,
Feb 23, 2017, 6:50:33 PM2/23/17
to ve...@googlegroups.com
have you tried Context#isOnWorkerThread / Context#isOnEventLoopThread ?



Mihai Stanescu

unread,
Feb 24, 2017, 1:33:25 AM2/24/17
to ve...@googlegroups.com
yes, the context is eventloop although the thread is worker. as a workaround now i check the thread name :) 

To unsubscribe from this group and stop receiving emails from it, send an email to vertx+unsubscribe@googlegroups.com.

--
You received this message because you are subscribed to a topic in the Google Groups "vert.x" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/vertx/88gFx63ZB_k/unsubscribe.
To unsubscribe from this group and all its topics, send an email to vertx+unsubscribe@googlegroups.com.

Mihai Stanescu

unread,
Feb 24, 2017, 1:34:26 AM2/24/17
to ve...@googlegroups.com
sorry, yeah will try this 

Tim Fox

unread,
Feb 24, 2017, 5:24:06 AM2/24/17
to vert.x


On Friday, 24 February 2017 06:33:25 UTC, yahim stnsc wrote:
yes, the context is eventloop although the thread is worker. as a workaround now i check the thread name :) 


This is to be expected, if you use executeBlocking from a non worker context, then when you're executing in the blocking code you are running with a different thread (now a worker thread) but you have the same context associated. Thread != context.

If you want to know whether you are running on a worker thread you can use Julien's suggestion above.

Mihai Stanescu

unread,
Feb 24, 2017, 5:42:42 AM2/24/17
to ve...@googlegroups.com
Yes, sorry i missed this function but i was on a 3.3.1 and did not have this function.

Reply all
Reply to author
Forward
0 new messages