Interface ChannelGroupFuture

  • All Superinterfaces:
    io.netty5.util.concurrent.Future<Void>, Iterable<io.netty5.util.concurrent.Future<Void>>

    public interface ChannelGroupFuture
    extends io.netty5.util.concurrent.Future<Void>, Iterable<io.netty5.util.concurrent.Future<Void>>
    The result of an asynchronous ChannelGroup operation. ChannelGroupFuture is composed of Futures which represent the outcome of the individual I/O operations that affect the Channels in the ChannelGroup.

    All I/O operations in ChannelGroup are asynchronous. It means any I/O calls will return immediately with no guarantee that the requested I/O operations have been completed at the end of the call. Instead, you will be returned with a ChannelGroupFuture instance which tells you when the requested I/O operations have succeeded, failed, or cancelled.

    Various methods are provided to let you check if the I/O operations has been completed, wait for the completion, and retrieve the result of the I/O operation. It also allows you to add more than one ChannelGroupFutureListener so you can get notified when the I/O operation have been completed.

    Prefer addListener(FutureListener) to FutureCompletionStage.await()

    It is recommended to prefer addListener(FutureListener) to FutureCompletionStage.await() wherever possible to get notified when I/O operations are done and to do any follow-up tasks.

    addListener(FutureListener) is non-blocking. It simply adds the specified ChannelGroupFutureListener to the ChannelGroupFuture, and I/O thread will notify the listeners when the I/O operations associated with the future is done. ChannelGroupFutureListener yields the best performance and resource utilization because it does not block at all, but it could be tricky to implement a sequential logic if you are not used to event-driven programming.

    By contrast, FutureCompletionStage.await() is a blocking operation. Once called, the caller thread blocks until all I/O operations are done. It is easier to implement a sequential logic with FutureCompletionStage.await(), but the caller thread blocks unnecessarily until all I/O operations are done and there's relatively expensive cost of inter-thread notification. Moreover, there's a chance of dead lock in a particular circumstance, which is described below.

    Do not call FutureCompletionStage.await() inside ChannelHandler

    The event handler methods in ChannelHandler is often called by an I/O thread. If FutureCompletionStage.await() is called by an event handler method, which is called by the I/O thread, the I/O operation it is waiting for might never be complete because FutureCompletionStage.await() can block the I/O operation it is waiting for, which is a deadlock.

     // BAD - NEVER DO THIS
     @Override
     public void messageReceived(ChannelHandlerContext ctx, ShutdownMessage msg) {
         ChannelGroup allChannels = MyServer.getAllChannels();
         ChannelGroupFuture future = allChannels.close();
         future.asStage().await();
         // Perform post-shutdown operation
         // ...
    
     }
    
     // GOOD
     @Override
     public void messageReceived(ChannelHandlerContext ctx, ShutdownMessage msg) {
         ChannelGroup allChannels = MyServer.getAllChannels();
         ChannelGroupFuture future = allChannels.close();
         future.addListener(new ChannelGroupFutureListener() {
             public void operationComplete(ChannelGroupFuture future) {
                 // Perform post-closure operation
                 // ...
             }
         });
     }
     

    In spite of the disadvantages mentioned above, there are certainly the cases where it is more convenient to call FutureCompletionStage.await(). In such a case, please make sure you do not call FutureCompletionStage.await() in an I/O thread. Otherwise, IllegalStateException will be raised to prevent a dead lock.

    • Method Detail

      • find

        io.netty5.util.concurrent.Future<Void> find​(Channel channel)
        Returns the Future of the individual I/O operation which is associated with the specified Channel.
        Returns:
        the matching Future if found. null otherwise.
      • isSuccess

        boolean isSuccess()
        Returns true if and only if all I/O operations associated with this future were successful without any failure.
      • isPartialSuccess

        boolean isPartialSuccess()
        Returns true if and only if the I/O operations associated with this future were partially successful with some failure.
      • isPartialFailure

        boolean isPartialFailure()
        Returns true if and only if the I/O operations associated with this future have failed partially with some success.
      • addListener

        ChannelGroupFuture addListener​(io.netty5.util.concurrent.FutureListener<? super Void> listener)
        Specified by:
        addListener in interface io.netty5.util.concurrent.Future<Void>
      • iterator

        Iterator<io.netty5.util.concurrent.Future<Void>> iterator()
        Returns the Iterator that enumerates all Futures which are associated with this future. Please note that the returned Iterator is is unmodifiable, which means a Future cannot be removed from this future.
        Specified by:
        iterator in interface Iterable<io.netty5.util.concurrent.Future<Void>>
      • cancel

        boolean cancel()
      • isFailed

        boolean isFailed()
      • isCancelled

        boolean isCancelled()
      • isDone

        boolean isDone()
      • isCancellable

        boolean isCancellable()
      • getNow

        V getNow()
      • executor

        io.netty5.util.concurrent.EventExecutor executor()