/*
 * Written by Doug Lea with assistance from members of JCP JSR-166
 * Expert Group and released to the public domain, as explained at
 * http://creativecommons.org/licenses/publicdomain
 */

import java.util.concurrent.*;
import java.util.concurrent.atomic.*;

public class TPEFib {
    static final ThreadPoolExecutor pool = 
        new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                               60L, TimeUnit.SECONDS,
                               new SynchronousQueue<Runnable>());

    static class Fib implements Callable<Long> {
        final long arg;
        Fib(long arg) { this.arg = arg; }
        public Long call() throws Exception {
            if (arg <= 1)
                return arg;
            Future<Long> l = pool.submit(new Fib(arg - 1));
            Future<Long> r = pool.submit(new Fib(arg - 2));
            return l.get() + r.get();
        }
    }

    public static void main(String[] args) throws Exception {
        long last = 0;
        long ARG = 17;
        long seqResult = seqFib(ARG);
        for (int i = 0; i < 10; ++i) {
            long start = System.nanoTime();
            long ans = pool.submit(new Fib(ARG)).get();
            if (ans != seqResult)
                throw new Error();
            long elapsed = System.nanoTime() - start;
            long t = pool.getCompletedTaskCount();
            long nt = t - last;
            last = t;
            System.out.println((elapsed / nt) + "ns per task");

        }
        pool.shutdown();
    }

    // Sequential version for arguments less than threshold
    static long seqFib(long n) {
        if (n <= 1) 
            return n;
        else 
            return seqFib(n-1) + seqFib(n-2);
    }

}
