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