import EDU.oswego.cs.dl.util.concurrent.*; /** * Callback version of Fibonacci. Computes: *
 * Computes fibonacci(n) = fibonacci(n-1) + fibonacci(n-2);  for n> 1
 *          fibonacci(0) = 0; 
 *          fibonacci(1) = 1.       
 * 
**/ public class FibVCB extends FJTask { // Performance-tuning constant: static int sequentialThreshold = 1; public static void main(String[] args) { try { int procs; int num; try { procs = Integer.parseInt(args[0]); num = Integer.parseInt(args[1]); if (args.length > 2) sequentialThreshold = Integer.parseInt(args[2]); } catch (Exception e) { System.out.println("Usage: java FibVCB []"); return; } FJTaskRunnerGroup g = new FJTaskRunnerGroup(procs); FibVCB f = new FibVCB(num, null); g.invoke(f); g.stats(); long result = f.getAnswer(); System.out.println("FibVCB: Size: " + num + " Answer: " + result); } catch (InterruptedException ex) {} } volatile int number = 0; final FibVCB parent; // callback target int callbacksExpected = 0; volatile int callbacksReceived = 0; FibVCB(int n, FibVCB p) { number = n; parent = p; } // Callback method called from subtasks upon completion synchronized void addResult(int n) { number += n; ++callbacksReceived; } synchronized int getAnswer() { if (!isDone()) throw new Error("Not yet computed"); return number; } public void run() { // same structure as join-based version int n = number; if (n <= 1) { // nothing } else if (n <= sequentialThreshold) { number = seqFib(n); } else { // clear number so subtasks can fill in number = 0; // establish number of callbacks expected callbacksExpected = 2; new FibVCB(n - 1, this).fork(); new FibVCB(n - 2, this).fork(); // Wait for callbacks from children while (callbacksReceived < callbacksExpected) yield(); } // Call back parent if (parent != null) parent.addResult(number); } // Sequential version for arguments less than threshold static int seqFib(int n) { if (n <= 1) return n; else return seqFib(n-1) + seqFib(n-2); } }