// AbstractInterruptibleChannel synchronizes invocations of this method
  // using AbstractInterruptibleChannel.closeLock, and also ensures that this
  // method is only ever invoked once.  Before we get to this method, isOpen
  // (which is volatile) will have been set to false.
  //
  protected void implCloseSelectableChannel() throws IOException {
    synchronized (stateLock) {
      isInputOpen = false;
      isOutputOpen = false;

      closeImpl();

      // Signal native threads, if needed.  If a target thread is not
      // currently blocked in an I/O operation then no harm is done since
      // the signal handler doesn't actually do anything.
      //
      if (readerThread != 0) NativeThread.signal(readerThread);

      if (writerThread != 0) NativeThread.signal(writerThread);

      // If this channel is not registered then it's safe to close the fd
      // immediately since we know at this point that no thread is
      // blocked in an I/O operation upon the channel and, since the
      // channel is marked closed, no thread will start another such
      // operation.  If this channel is registered then we don't close
      // the fd since it might be in use by a selector.  In that case
      // closing this channel caused its keys to be cancelled, so the
      // last selector to deregister a key for this channel will invoke
      // kill() to close the fd.
      //
      if (!isRegistered()) kill();
    }
  }
  protected void implCloseSelectableChannel() throws IOException {
    synchronized (stateLock) {
      if (state != ST_KILLED) nd.preClose(fd);
      ResourceManager.afterUdpClose();

      // if member of mulitcast group then invalidate all keys
      if (registry != null) registry.invalidateAll();

      long th;
      if ((th = readerThread) != 0) NativeThread.signal(th);
      if ((th = writerThread) != 0) NativeThread.signal(th);
      if (!isRegistered()) kill();
    }
  }
 public long write0(ByteBuffer[] bufs) throws IOException {
   if (bufs == null) throw new NullPointerException();
   synchronized (writeLock) {
     ensureWriteOpen();
     long n = 0;
     try {
       begin();
       synchronized (stateLock) {
         if (!isOpen()) return 0;
         writerThread = NativeThread.current();
       }
       for (; ; ) {
         n = Net.write(fd, bufs);
         if ((n == IOStatus.INTERRUPTED) && isOpen()) continue;
         return IOStatus.normalize(n);
       }
     } finally {
       writerCleanup();
       end((n > 0) || (n == IOStatus.UNAVAILABLE));
       synchronized (stateLock) {
         if ((n <= 0) && (!isOutputOpen)) throw new AsynchronousCloseException();
       }
       assert IOStatus.check(n);
     }
   }
 }
  private long read0(ByteBuffer[] bufs) throws IOException {
    if (bufs == null) throw new NullPointerException();
    synchronized (readLock) {
      if (!ensureReadOpen()) return -1;
      long n = 0;
      try {
        begin();
        synchronized (stateLock) {
          if (!isOpen()) return 0;
          readerThread = NativeThread.current();
        }

        for (; ; ) {
          n = Net.read(fd, bufs);
          if ((n == IOStatus.INTERRUPTED) && isOpen()) continue;
          return IOStatus.normalize(n);
        }
      } finally {
        readerCleanup();
        end(n > 0 || (n == IOStatus.UNAVAILABLE));
        synchronized (stateLock) {
          if ((n <= 0) && (!isInputOpen)) return IOStatus.EOF;
        }
        assert IOStatus.check(n);
      }
    }
  }
  public boolean connect(SocketAddress sa) throws IOException {
    int trafficClass = 0; // ## Pick up from options
    int localPort = 0;

    synchronized (readLock) {
      synchronized (writeLock) {
        ensureOpenAndUnconnected();
        InetSocketAddress isa = Net.checkAddress(sa);
        SecurityManager sm = System.getSecurityManager();
        if (sm != null) sm.checkConnect(isa.getAddress().getHostAddress(), isa.getPort());
        synchronized (blockingLock()) {
          int n = 0;
          try {
            try {
              begin();
              synchronized (stateLock) {
                if (!isOpen()) {
                  return false;
                }
                readerThread = NativeThread.current();
              }
              for (; ; ) {
                InetAddress ia = isa.getAddress();
                if (ia.isAnyLocalAddress()) ia = InetAddress.getLocalHost();
                n = connectImpl(ia, isa.getPort(), trafficClass);
                if ((n == IOStatus.INTERRUPTED) && isOpen()) continue;
                break;
              }
            } finally {
              readerCleanup();
              end((n > 0) || (n == IOStatus.UNAVAILABLE));
              assert IOStatus.check(n);
            }
          } catch (IOException x) {
            // If an exception was thrown, close the channel after
            // invoking end() so as to avoid bogus
            // AsynchronousCloseExceptions
            close();
            throw x;
          }
          synchronized (stateLock) {
            remoteAddress = isa;
            if (n > 0) {

              // Connection succeeded; disallow further
              // invocation
              state = ST_CONNECTED;
              return true;
            }
            // If nonblocking and no exception then connection
            // pending; disallow another invocation
            if (!isBlocking()) state = ST_PENDING;
            else assert false;
          }
        }
        return false;
      }
    }
  }
 public void shutdownOutput() throws IOException {
   synchronized (stateLock) {
     if (!isOpen()) throw new ClosedChannelException();
     isOutputOpen = false;
     shutdown(fd, SHUT_WR);
     if (writerThread != 0) NativeThread.signal(writerThread);
   }
 }
  public int send(ByteBuffer src, SocketAddress target) throws IOException {
    if (src == null) throw new NullPointerException();

    synchronized (writeLock) {
      ensureOpen();
      InetSocketAddress isa = Net.checkAddress(target);
      InetAddress ia = isa.getAddress();
      if (ia == null) throw new IOException("Target address not resolved");
      synchronized (stateLock) {
        if (!isConnected()) {
          if (target == null) throw new NullPointerException();
          SecurityManager sm = System.getSecurityManager();
          if (sm != null) {
            if (ia.isMulticastAddress()) {
              sm.checkMulticast(ia);
            } else {
              sm.checkConnect(ia.getHostAddress(), isa.getPort());
            }
          }
        } else { // Connected case; Check address then write
          if (!target.equals(remoteAddress)) {
            throw new IllegalArgumentException("Connected address not equal to target address");
          }
          return write(src);
        }
      }

      int n = 0;
      try {
        begin();
        if (!isOpen()) return 0;
        writerThread = NativeThread.current();
        do {
          n = send(fd, src, isa);
        } while ((n == IOStatus.INTERRUPTED) && isOpen());

        synchronized (stateLock) {
          if (isOpen() && (localAddress == null)) {
            localAddress = Net.localAddress(fd);
          }
        }
        return IOStatus.normalize(n);
      } finally {
        writerThread = 0;
        end((n > 0) || (n == IOStatus.UNAVAILABLE));
        assert IOStatus.check(n);
      }
    }
  }
 public SocketAddress receive(ByteBuffer dst) throws IOException {
   if (dst.isReadOnly()) throw new IllegalArgumentException("Read-only buffer");
   if (dst == null) throw new NullPointerException();
   synchronized (readLock) {
     ensureOpen();
     // Socket was not bound before attempting receive
     if (localAddress() == null) bind(null);
     int n = 0;
     ByteBuffer bb = null;
     try {
       begin();
       if (!isOpen()) return null;
       SecurityManager security = System.getSecurityManager();
       readerThread = NativeThread.current();
       if (isConnected() || (security == null)) {
         do {
           n = receive(fd, dst);
         } while ((n == IOStatus.INTERRUPTED) && isOpen());
         if (n == IOStatus.UNAVAILABLE) return null;
       } else {
         bb = Util.getTemporaryDirectBuffer(dst.remaining());
         for (; ; ) {
           do {
             n = receive(fd, bb);
           } while ((n == IOStatus.INTERRUPTED) && isOpen());
           if (n == IOStatus.UNAVAILABLE) return null;
           InetSocketAddress isa = (InetSocketAddress) sender;
           try {
             security.checkAccept(isa.getAddress().getHostAddress(), isa.getPort());
           } catch (SecurityException se) {
             // Ignore packet
             bb.clear();
             n = 0;
             continue;
           }
           bb.flip();
           dst.put(bb);
           break;
         }
       }
       return sender;
     } finally {
       if (bb != null) Util.releaseTemporaryDirectBuffer(bb);
       readerThread = 0;
       end((n > 0) || (n == IOStatus.UNAVAILABLE));
       assert IOStatus.check(n);
     }
   }
 }
  // package-private
  int poll(int events, long timeout) throws IOException {
    assert Thread.holdsLock(blockingLock()) && !isBlocking();

    synchronized (readLock) {
      int n = 0;
      try {
        begin();
        synchronized (stateLock) {
          if (!isOpen()) return 0;
          readerThread = NativeThread.current();
        }
        n = Net.poll(fd, events, timeout);
      } finally {
        readerThread = 0;
        end(n > 0);
      }
      return n;
    }
  }
 public int write(ByteBuffer buf) throws IOException {
   if (buf == null) throw new NullPointerException();
   synchronized (writeLock) {
     synchronized (stateLock) {
       ensureOpen();
       if (!isConnected()) throw new NotYetConnectedException();
     }
     int n = 0;
     try {
       begin();
       if (!isOpen()) return 0;
       writerThread = NativeThread.current();
       do {
         n = IOUtil.write(fd, buf, -1, nd);
       } while ((n == IOStatus.INTERRUPTED) && isOpen());
       return IOStatus.normalize(n);
     } finally {
       writerThread = 0;
       end((n > 0) || (n == IOStatus.UNAVAILABLE));
       assert IOStatus.check(n);
     }
   }
 }
 public long write(ByteBuffer[] srcs, int offset, int length) throws IOException {
   if ((offset < 0) || (length < 0) || (offset > srcs.length - length))
     throw new IndexOutOfBoundsException();
   synchronized (writeLock) {
     synchronized (stateLock) {
       ensureOpen();
       if (!isConnected()) throw new NotYetConnectedException();
     }
     long n = 0;
     try {
       begin();
       if (!isOpen()) return 0;
       writerThread = NativeThread.current();
       do {
         n = IOUtil.write(fd, srcs, offset, length, nd);
       } while ((n == IOStatus.INTERRUPTED) && isOpen());
       return IOStatus.normalize(n);
     } finally {
       writerThread = 0;
       end((n > 0) || (n == IOStatus.UNAVAILABLE));
       assert IOStatus.check(n);
     }
   }
 }
 public boolean finishConnect() throws IOException {
   synchronized (readLock) {
     synchronized (writeLock) {
       synchronized (stateLock) {
         if (!isOpen()) throw new ClosedChannelException();
         if (state == ST_CONNECTED) return true;
         if (state != ST_PENDING) throw new NoConnectionPendingException();
       }
       int n = 0;
       try {
         try {
           begin();
           synchronized (blockingLock()) {
             synchronized (stateLock) {
               if (!isOpen()) {
                 return false;
               }
               readerThread = NativeThread.current();
             }
             if (!isBlocking()) {
               for (; ; ) {
                 n = checkConnect(fd, false, readyToConnect);
                 if ((n == IOStatus.INTERRUPTED) && isOpen()) continue;
                 break;
               }
             } else {
               for (; ; ) {
                 n = checkConnect(fd, true, readyToConnect);
                 if (n == 0) {
                   // Loop in case of
                   // spurious notifications
                   continue;
                 }
                 if ((n == IOStatus.INTERRUPTED) && isOpen()) continue;
                 break;
               }
             }
           }
         } finally {
           synchronized (stateLock) {
             readerThread = 0;
             if (state == ST_KILLPENDING) {
               kill();
               // poll()/getsockopt() does not report
               // error (throws exception, with n = 0)
               // on Linux platform after dup2 and
               // signal-wakeup. Force n to 0 so the
               // end() can throw appropriate exception
               n = 0;
             }
           }
           end((n > 0) || (n == IOStatus.UNAVAILABLE));
           assert IOStatus.check(n);
         }
       } catch (IOException x) {
         // If an exception was thrown, close the channel after
         // invoking end() so as to avoid bogus
         // AsynchronousCloseExceptions
         close();
         throw x;
       }
       if (n > 0) {
         synchronized (stateLock) {
           state = ST_CONNECTED;
         }
         return true;
       }
       return false;
     }
   }
 }
  public int read(ByteBuffer buf) throws IOException {

    if (buf == null) throw new NullPointerException();

    synchronized (readLock) {
      if (!ensureReadOpen()) return -1;
      int n = 0;
      try {

        // Set up the interruption machinery; see
        // AbstractInterruptibleChannel for details
        //
        begin();

        synchronized (stateLock) {
          if (!isOpen()) {
            // Either the current thread is already interrupted, so
            // begin() closed the channel, or another thread closed the
            // channel since we checked it a few bytecodes ago.  In
            // either case the value returned here is irrelevant since
            // the invocation of end() in the finally block will throw
            // an appropriate exception.
            //
            return 0;
          }

          // Save this thread so that it can be signalled on those
          // platforms that require it
          //
          readerThread = NativeThread.current();
        }

        // Between the previous test of isOpen() and the return of the
        // IOUtil.read invocation below, this channel might be closed
        // or this thread might be interrupted.  We rely upon the
        // implicit synchronization point in the kernel read() call to
        // make sure that the right thing happens.  In either case the
        // implCloseSelectableChannel method is ultimately invoked in
        // some other thread, so there are three possibilities:
        //
        //   - implCloseSelectableChannel() invokes nd.preClose()
        //     before this thread invokes read(), in which case the
        //     read returns immediately with either EOF or an error,
        //     the latter of which will cause an IOException to be
        //     thrown.
        //
        //   - implCloseSelectableChannel() invokes nd.preClose() after
        //     this thread is blocked in read().  On some operating
        //     systems (e.g., Solaris and Windows) this causes the read
        //     to return immediately with either EOF or an error
        //     indication.
        //
        //   - implCloseSelectableChannel() invokes nd.preClose() after
        //     this thread is blocked in read() but the operating
        //     system (e.g., Linux) doesn't support preemptive close,
        //     so implCloseSelectableChannel() proceeds to signal this
        //     thread, thereby causing the read to return immediately
        //     with IOStatus.INTERRUPTED.
        //
        // In all three cases the invocation of end() in the finally
        // clause will notice that the channel has been closed and
        // throw an appropriate exception (AsynchronousCloseException
        // or ClosedByInterruptException) if necessary.
        //
        // *There is A fourth possibility. implCloseSelectableChannel()
        // invokes nd.preClose(), signals reader/writer thred and quickly
        // moves on to nd.close() in kill(), which does a real close.
        // Then a third thread accepts a new connection, opens file or
        // whatever that causes the released "fd" to be recycled. All
        // above happens just between our last isOpen() check and the
        // next kernel read reached, with the recycled "fd". The solution
        // is to postpone the real kill() if there is a reader or/and
        // writer thread(s) over there "waiting", leave the cleanup/kill
        // to the reader or writer thread. (the preClose() still happens
        // so the connection gets cut off as usual).
        //
        // For socket channels there is the additional wrinkle that
        // asynchronous shutdown works much like asynchronous close,
        // except that the channel is shutdown rather than completely
        // closed.  This is analogous to the first two cases above,
        // except that the shutdown operation plays the role of
        // nd.preClose().
        for (; ; ) {
          n = Net.read(fd, buf);
          if ((n == IOStatus.INTERRUPTED) && isOpen()) {
            // The system call was interrupted but the channel
            // is still open, so retry
            continue;
          }
          return IOStatus.normalize(n);
        }

      } finally {
        readerCleanup(); // Clear reader thread
        // The end method, which is defined in our superclass
        // AbstractInterruptibleChannel, resets the interruption
        // machinery.  If its argument is true then it returns
        // normally; otherwise it checks the interrupt and open state
        // of this channel and throws an appropriate exception if
        // necessary.
        //
        // So, if we actually managed to do any I/O in the above try
        // block then we pass true to the end method.  We also pass
        // true if the channel was in non-blocking mode when the I/O
        // operation was initiated but no data could be transferred;
        // this prevents spurious exceptions from being thrown in the
        // rare event that a channel is closed or a thread is
        // interrupted at the exact moment that a non-blocking I/O
        // request is made.
        //
        end(n > 0 || (n == IOStatus.UNAVAILABLE));

        // Extra case for socket channels: Asynchronous shutdown
        //
        synchronized (stateLock) {
          if ((n <= 0) && (!isInputOpen)) return IOStatus.EOF;
        }

        assert IOStatus.check(n);
      }
    }
  }