0
votes

I am reading netty 4 source code. eventLoop.inEventLoop() appears everywhere. According to Netty in Action:

A Channel is registered for its lifetime with a single EventLoop. A single EventLoop may be assigned to one or more Channels. a channel has and only has one eventLoop/thread.

Theoretically, eventLoop.inEventLoop() is to make sure code blocks are executed by the assigned eventLoop/thread. Furthermore, if you call something from non-io thread, eventLoop.inEventLoop() goes to false, and will be executed by assigned eventLoop/thread.

For example, the following code goes to else block(NioSocketChannel$NioSocketChannelUnsafe(AbstractChannel$AbstractUnsafe).register(EventLoop, ChannelPromise)) where the channel is not registered(assigned to an eventloop/thread).

if (eventLoop.inEventLoop()) {
    register0(promise);
} else {
    try {
        eventLoop.execute(new Runnable() {
            @Override
            public void run() {
                register0(promise);
            }
        });
    } catch (Throwable t) {
...
    }
}

I am really confused, whats the point of eventLoop.inEventLoop(). What does eventLoop.inEventLoop() protect from?

Besides the above one, can you give me some more specific examples in practice to demonstrate why and how eventloop.inEventLoop() == false? What kind of code do you call? Where do you call? How does the code make eventloop.inEventLoop() == false?

1

1 Answers

0
votes

This kind of code ensures that only the correct eventLoop/thread works with/change the Channel object. This solves a lot of race conditions and multi threading problems when only one specific thread can work with the Channel object. This has something to do with what is called "thread safe" and if or if not a class is considered "thread safe" or not. The code can be read as follow:

if (amIOnTheCorrectThread()) {
    doTheActualWork(); // I do the work
} else {
   scheduleOnTheCorrectThread.performAction({ doTheActualWork(); }); // let him do the work
}

Depending on if you are on the correct thread, the work is done directly (on the correct thread) or the task is off-loaded to the correct thread, so that the other thread does the work. The other thread does that by having an endless loop and check if there are any new tasks to execute. As an example, check the run() method of the io.netty.channel.ThreadPerChannelEventLoop class:

@Override
protected void run() {
    for (;;) {
        Runnable task = takeTask();
        if (task != null) {
            task.run();
            // [...]
        }
    [...]