public void close() throws IOException {
   try {
     lock.getBusyFlag();
     reslen = 0; // Clear Buffer
     EOF = true; // Mark End Of File
     empty.cvBroadcast(); // Alert all Threads
     full.cvBroadcast();
   } finally {
     lock.freeBusyFlag();
   }
 }
  public void run() {
    try {
      while (true) {
        int c = in.read();
        try {
          lock.getBusyFlag();
          if ((c == -1) || (EOF)) {
            EOF = true; // Mark End Of File
            in.close(); // Close Input Source
            return; // End IO Thread
          } else {
            putChar((byte) c); // Store the byte read
          }
          if (EOF) {
            in.close(); // Close Input Source
            return; // End IO Thread
          }
        } finally {
          lock.freeBusyFlag();
        }
      }

    } catch (IOException e) {
      IOError = e; //  Store Exception
      return;
    } finally {
      try {
        lock.getBusyFlag();
        empty.cvBroadcast(); //  Alert all Threads
      } finally {
        lock.freeBusyFlag();
      }
    }
  }
 private void putChar(byte c) {
   try {
     lock.getBusyFlag();
     while ((reslen == result.length) && (!EOF)) {
       try {
         full.cvWait();
       } catch (InterruptedException ie) {
       }
     }
     if (!EOF) {
       result[reslen++] = c;
       empty.cvSignal();
     }
   } finally {
     lock.freeBusyFlag();
   }
 }
 private byte getChar() {
   try {
     lock.getBusyFlag();
     byte c = result[0];
     System.arraycopy(result, 1, result, 0, --reslen);
     full.cvSignal();
     return c;
   } finally {
     lock.freeBusyFlag();
   }
 }
 private byte[] getChars(int chars) {
   try {
     lock.getBusyFlag();
     byte c[] = new byte[chars];
     System.arraycopy(result, 0, c, 0, chars);
     reslen -= chars;
     System.arraycopy(result, chars, result, 0, reslen);
     full.cvSignal();
     return c;
   } finally {
     lock.freeBusyFlag();
   }
 }
 public int read() throws IOException {
   try {
     lock.getBusyFlag();
     while (reslen == 0) {
       try {
         if (EOF) return (-1);
         if (IOError != null) throw IOError;
         empty.cvWait();
       } catch (InterruptedException e) {
       }
     }
     return (int) getChar();
   } finally {
     lock.freeBusyFlag();
   }
 }
  public int read(byte b[], int off, int len) throws IOException {
    try {
      lock.getBusyFlag();
      while (reslen == 0) {
        try {
          if (EOF) return (-1);
          if (IOError != null) throw IOError;
          empty.cvWait();
        } catch (InterruptedException e) {
        }
      }

      int sizeread = Math.min(reslen, len);
      byte c[] = getChars(sizeread);
      System.arraycopy(c, 0, b, off, sizeread);
      return (sizeread);
    } finally {
      lock.freeBusyFlag();
    }
  }