docs: public void terminate()
      {
          slotSync.lock();
          try {
              // Connect up any pending inproc connections, otherwise we will hang
              for (Entry<PendingConnection, String> pending : pendingConnections.entries()) {
                  SocketBase s = createSocket(ZMQ.ZMQ_PAIR);
                  // create_socket might fail eg: out of memory/sockets limit reached
                  assert (s != null);
                  s.bind(pending.getValue());
                  s.close();
              }
  
              if (!starting.get()) {
                  //  Check whether termination was already underway, but interrupted and now
                  //  restarted.
                  boolean restarted = terminating;
                  terminating = true;
  
                  //  First attempt to terminate the context.
                  if (!restarted) {
                      //  First send stop command to sockets so that any blocking calls
                      //  can be interrupted. If there are no sockets we can ask reaper
                      //  thread to stop.
                      for (SocketBase socket : sockets) {
                          socket.stop();
                      }
                      if (sockets.isEmpty()) {
                          reaper.stop();
                      }
                  }
              }
          }
          finally {
              slotSync.unlock();
          }
  
          if (!starting.get()) {
              //  Wait till reaper thread closes all the sockets.
              Command cmd = termMailbox.recv(WAIT_FOREVER);
              if (cmd == null) {
                  throw new IllegalStateException(ZError.toString(errno.get()));
              }
              assert (cmd.type == Command.Type.DONE) : cmd;
  
              slotSync.lock();
              try {
                  assert (sockets.isEmpty());
              }
              finally {
                  slotSync.unlock();
              }
          }
  
          //  Deallocate the resources.
          try {
              destroy();
          }
          catch (IOException e) {
              throw new RuntimeException(e);
          }
      }