import java.io.IOException;
import java.util.concurrent.atomic.AtomicInteger;

public class PipeTest {
    private static final int NUM_ITERATIONS = 100;
    private static final int NUM_THREADS = 100;
    
    private static final Writer WRITER = new Writer();
    private static final Reader READER = new Reader();
    
    private static final AtomicInteger COUNTER = new AtomicInteger(1);
    private static final Pipe PIPE = new Pipe();

    public static void main(String[] args) throws InterruptedException {
        Thread[] w = new Thread[NUM_THREADS];
        Thread[] r = new Thread[NUM_THREADS];
        for(int i = 0; i < NUM_THREADS; i++) {
            w[i] = new Thread(WRITER, "Writer " + i);
            r[i] = new Thread(READER, "Reader " + i);
            w[i].start();
            r[i].start();
        }
        Thread.sleep(1000);
        PIPE.writeFinal(Character.MAX_VALUE);
        for(int i = 0; i < NUM_THREADS; i++) {
            w[i].join();
            r[i].join();
        }
        System.exit(0);
    }

    private static class Writer implements Runnable {
        public void run() {
            for(int i = 0; i < NUM_ITERATIONS; i++) {
                char ch = (char) COUNTER.getAndIncrement();
                System.err.println(ch + ", Writing");
                PIPE.write(ch);
                System.err.println(ch + ", Done writing");
            }
        }
    }

    private static class Reader implements Runnable {
        public void run() {
            while(true) {
                try {
                    int val = PIPE.read();
                    if(val < 0) {
                        System.err.println("EOF, Read");
                        return;
                    } else {
                        char ch = (char) val;
                        System.err.println(ch + ", Read");
                    }
                } catch(IOException e) {
                    System.err.println("Failed to read a character.");
                }
            }
        }
    }
}
