code: @SuppressWarnings({ "rawtypes", "unchecked" })
      public Future<Void> close() {
          log.info("Shutting down.");
  
          final Future<Void> closeFuture;
  
          if (this.isClosed.compareAndSet(false, true)) {
              // Since we're (maybe) going to clobber the main event loop group, we should have this promise use the global
              // event executor to notify listeners.
              final Promise<Void> closePromise = new DefaultPromise<>(GlobalEventExecutor.INSTANCE);
  
              this.channelPool.close().addListener(new GenericFutureListener<Future<Void>>() {
  
                  @Override
                  public void operationComplete(final Future<Void> closePoolFuture) throws Exception {
                      if (ApnsClient.this.shouldShutDownEventLoopGroup) {
                          ApnsClient.this.eventLoopGroup.shutdownGracefully().addListener(new GenericFutureListener() {
  
                              @Override
                              public void operationComplete(final Future future) throws Exception {
                                  closePromise.trySuccess(null);
                              }
                          });
                      } else {
                          closePromise.trySuccess(null);
                      }
                  }
              });
  
              closeFuture = closePromise;
          } else {
              closeFuture = new SucceededFuture<>(GlobalEventExecutor.INSTANCE, null);
          }
  
          return closeFuture;
      }
docs: <p>Gracefully shuts down the client, closing all connections and releasing all persistent resources. The
  disconnection process will wait until notifications that have been sent to the APNs server have been either
  accepted or rejected. Note that some notifications passed to
  {@link ApnsClient#sendNotification(ApnsPushNotification)} may still be enqueued and not yet sent by the time the
  shutdown process begins; the {@code Futures} associated with those notifications will fail.</p>
  
  <p>The returned {@code Future} will be marked as complete when all connections in this client's pool have closed
  completely and (if no {@code EventLoopGroup} was provided at construction time) the client's event loop group has
  shut down. If the client has already shut down, the returned {@code Future} will be marked as complete
  immediately.</p>
  
  <p>Clients may not be reused once they have been closed.</p>
  
  @return a {@code Future} that will be marked as complete when the client has finished shutting down
  
  @since 0.11