@Override
 public void run() {
   WebSocketImpl ws = null;
   try {
     while (true) {
       ByteBuffer buf = null;
       ws = iqueue.take();
       buf = ws.in.poll();
       assert (buf != null);
       try {
         ws.decode(buf);
         // ws.flush();
       } catch (IOException e) {
         handleIOException(ws, e);
       } finally {
         pushBuffer(buf);
       }
     }
   } catch (RuntimeException e) {
     handleFatal(ws, e);
   } catch (InterruptedException e) {
   } catch (Throwable e) {
     e.printStackTrace();
   }
 }
 private void registerWrite() {
   int size = oqueue.size();
   for (int i = 0; i < size; i++) {
     WebSocketImpl conn = oqueue.remove();
     try {
       conn.key.channel().register(selector, SelectionKey.OP_READ | SelectionKey.OP_WRITE, conn);
     } catch (ClosedChannelException ex) {
       onWebsocketError(null, ex);
       conn.eot(null);
       return;
     }
   }
 }
 private void queue(WebSocketImpl ws) throws InterruptedException {
   if (ws.workerThread == null) {
     ws.workerThread = decoders.get(queueinvokes % decoders.size());
     queueinvokes++;
   }
   ws.workerThread.put(ws);
 }
 @Override
 public void run() {
   WebSocketImpl ws = null;
   try {
     while (true) {
       ByteBuffer buf = null;
       ws = iqueue.take();
       buf = ws.inQueue.poll();
       assert (buf != null);
       try {
         ws.decode(buf);
       } catch (Exception e) {
         System.err.println("Error while reading from remote connection: " + e);
       } finally {
         pushBuffer(buf);
       }
     }
   } catch (InterruptedException e) {
   } catch (RuntimeException e) {
     handleFatal(ws, e);
   }
 }
  // Runnable IMPLEMENTATION /////////////////////////////////////////////////
  public void run() {
    synchronized (this) {
      if (selectorthread != null)
        throw new IllegalStateException(getClass().getName() + " can only be started once.");
      selectorthread = Thread.currentThread();
      if (isclosed.get()) {
        return;
      }
    }
    selectorthread.setName("WebsocketSelector" + selectorthread.getId());
    try {
      server = ServerSocketChannel.open();
      server.configureBlocking(false);
      ServerSocket socket = server.socket();
      socket.setReceiveBufferSize(WebSocket.RCVBUF);
      socket.bind(address);
      selector = Selector.open();
      server.register(selector, server.validOps());
    } catch (IOException ex) {
      handleFatal(null, ex);
      return;
    }
    try {
      while (!selectorthread.isInterrupted()) {
        SelectionKey key = null;
        WebSocketImpl conn = null;
        try {
          selector.select();
          registerWrite();

          Set<SelectionKey> keys = selector.selectedKeys();
          Iterator<SelectionKey> i = keys.iterator();

          while (i.hasNext()) {
            key = i.next();

            if (!key.isValid()) {
              // Object o = key.attachment();
              continue;
            }

            if (key.isAcceptable()) {
              if (!onConnect(key)) {
                key.cancel();
                continue;
              }

              SocketChannel channel = server.accept();
              channel.configureBlocking(false);
              WebSocketImpl w = wsf.createWebSocket(this, drafts, channel.socket());
              w.key = channel.register(selector, SelectionKey.OP_READ, w);
              w.channel = wsf.wrapChannel(channel, w.key);
              i.remove();
              allocateBuffers(w);
              continue;
            }

            if (key.isReadable()) {
              conn = (WebSocketImpl) key.attachment();
              ByteBuffer buf = takeBuffer();
              try {
                if (SocketChannelIOHelper.read(buf, conn, (ByteChannel) conn.channel)) {
                  conn.inQueue.put(buf);
                  queue(conn);
                  i.remove();
                  if (conn.channel instanceof WrappedByteChannel) {
                    if (((WrappedByteChannel) conn.channel).isNeedRead()) {
                      iqueue.add(conn);
                    }
                  }
                } else {
                  pushBuffer(buf);
                }
              } catch (IOException e) {
                pushBuffer(buf);
                throw e;
              } catch (RuntimeException e) {
                pushBuffer(buf);
                throw e;
              }
            }
            if (key.isWritable()) {
              conn = (WebSocketImpl) key.attachment();
              if (SocketChannelIOHelper.batch(conn, (ByteChannel) conn.channel)) {
                if (key.isValid()) key.interestOps(SelectionKey.OP_READ);
              }
            }
          }
          while (!iqueue.isEmpty()) {
            conn = iqueue.remove(0);
            WrappedByteChannel c = ((WrappedByteChannel) conn.channel);
            ByteBuffer buf = takeBuffer();
            try {
              if (SocketChannelIOHelper.readMore(buf, conn, c)) iqueue.add(conn);
              conn.inQueue.put(buf);
              queue(conn);
            } finally {
              pushBuffer(buf);
            }
          }
        } catch (CancelledKeyException e) {
          // an other thread may cancel the key
        } catch (IOException ex) {
          if (key != null) key.cancel();
          handleIOException(conn, ex);
        } catch (InterruptedException e) {
          return; // FIXME controlled shutdown
        }
      }

    } catch (RuntimeException e) {
      // should hopefully never occur
      handleFatal(null, e);
    }
  }
  // Runnable IMPLEMENTATION /////////////////////////////////////////////////
  public void run() {
    if (selectorthread != null)
      throw new IllegalStateException(
          "This instance of "
              + getClass().getSimpleName()
              + " can only be started once the same time.");
    selectorthread = Thread.currentThread();
    selectorthread.setName("WebsocketSelector" + selectorthread.getId());
    try {
      server = ServerSocketChannel.open();
      server.configureBlocking(false);
      ServerSocket socket = server.socket();
      socket.setReceiveBufferSize(WebSocket.RCVBUF);
      socket.bind(address);
      selector = Selector.open();
      server.register(selector, server.validOps());
    } catch (IOException ex) {
      onWebsocketError(null, ex);
      return;
    }
    try {
      while (!selectorthread.isInterrupted()) {
        SelectionKey key = null;
        WebSocketImpl conn = null;
        try {
          selector.select();
          registerWrite();

          Set<SelectionKey> keys = selector.selectedKeys();
          Iterator<SelectionKey> i = keys.iterator();

          while (i.hasNext()) {
            key = i.next();

            if (!key.isValid()) {
              // Object o = key.attachment();
              continue;
            }

            if (key.isAcceptable()) {
              SocketChannel channel = server.accept();
              channel.configureBlocking(false);
              WebSocketImpl c = wsf.createWebSocket(this, drafts, channel.socket());
              c.key = channel.register(selector, SelectionKey.OP_READ, c);
              c.ioobject = wsf.wrapChannel(channel);
              i.remove();
              allocateBuffers(c);
              continue;
            }

            if (key.isReadable()) {
              conn = (WebSocketImpl) key.attachment();
              ByteBuffer buf = takeBuffer();
              try {
                if (SocketChannelIOHelper.read(buf, conn, (ByteChannel) conn.ioobject)) {
                  conn.in.put(buf);
                  queue(conn);
                  i.remove();
                } else {
                  pushBuffer(buf);
                }
              } catch (IOException e) {
                pushBuffer(buf);
                throw e;
              } catch (RuntimeException e) {
                pushBuffer(buf);
                throw e;
              }
            }
            if (key.isWritable()) {
              conn = (WebSocketImpl) key.attachment();
              if (SocketChannelIOHelper.batch(conn, (ByteChannel) conn.ioobject)) {
                if (key.isValid())
                  key.channel().register(selector, SelectionKey.OP_READ, key.attachment());
              }
            }
          }
        } catch (CancelledKeyException e) {
          // an other thread may cancel the key
        } catch (IOException ex) {
          if (key != null) key.cancel();
          handleIOException(conn, ex);
        } catch (InterruptedException e) {
          return;
        }
      }
    } catch (RuntimeException e) {
      // should hopefully never occur
      handleFatal(null, e);
    }
  }