code: @Override
  	public void close() throws IOException {
  		boolean enqueueOnSocketClose;
  		synchronized(closeLock) {
  			if(closeTime == null) {
  				// Remove this from the context
  				socketContext.onClose(this);
  				closeTime = System.currentTimeMillis();
  				enqueueOnSocketClose = true;
  			} else {
  				enqueueOnSocketClose = false;
  			}
  		}
  		if(enqueueOnSocketClose) {
  			Future<?> future = listenerManager.enqueueEvent(
  				new ConcurrentListenerManager.Event<SocketListener>() {
  					@Override
  					public Runnable createCall(final SocketListener listener) {
  						return new Runnable() {
  							@Override
  							public void run() {
  								listener.onSocketClose(AbstractSocket.this);
  							}
  						};
  					}
  				}
  			);
  			try {
  				logger.log(Level.FINE, "Waiting for calls to onSocketClose to complete");
  				future.get();
  				logger.log(Level.FINE, "All calls to onSocketClose finished");
  			} catch(ExecutionException e) {
  				logger.log(Level.SEVERE, null, e);
  			} catch(InterruptedException e) {
  				logger.log(Level.SEVERE, null, e);
  				// Restore the interrupted status
  				Thread.currentThread().interrupt();
  			}
  		}
  		listenerManager.close();
  	}
docs: Any overriding implementation must call super.close() first.