public int get(byte[] data, int offset, int len) {
        if (len == 0) return 0;
        int dataLen = 0;
        
        synchronized (signal) {
            // see if we have enough data
            while (getAvailable() <= 0) {
                if (eof) return (-1);
                try { signal.wait(1000); } catch (Exception e) { System.out.println("Get.Signal.wait:" + e); }
            }
            len = Math.min(len, getAvailable());
            
            // copy data
            if (getHere < putHere) {
                int l = Math.min(len, putHere - getHere);
                System.arraycopy(buffer, getHere, data, offset, l);
                getHere += l;
                if (getHere >= bufferSize) getHere = 0;
                dataLen = l;
            } else {
                int l = Math.min(len, bufferSize - getHere);
                System.arraycopy(buffer, getHere, data, offset, l);
                getHere += l;
                if (getHere >= bufferSize) getHere = 0;
                dataLen = l;
                if (len > l) dataLen += get(data, offset + l, len - l);
            }
            signal.notify();
        }
        
        return dataLen;
    }