KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > EDU > oswego > cs > dl > util > concurrent > misc > SynchronizationTimer


1 /*
2   File: SynchronizationTimer.java
3
4   Originally written by Doug Lea and released into the public domain.
5   This may be used for any purposes whatsoever without acknowledgment.
6   Thanks for the assistance and support of Sun Microsystems Labs,
7   and everyone contributing, testing, and using this code.
8
9   History:
10   Date Who What
11   7Jul1998 dl Create public version
12   16Jul1998 dl fix intialization error for compute loops
13                               combined into one frame
14                               misc layout and defaults changes
15                               increase printed precision
16                               overlap get/set in Executor tests
17                               Swap defaults for swing import
18                               Active thread counts reflect executors
19   30Aug1998 dl Misc revisions to mesh with 1.1.0
20   27jan1999 dl Eliminate GC calls
21   24Nov2001 dl Increase some default values
22 */

23
24 package EDU.oswego.cs.dl.util.concurrent.misc;
25
26 // Swap the following sets of imports if necessary.
27

28 import javax.swing.*;
29 import javax.swing.border.*;
30
31 //import com.sun.java.swing.*;
32
//import com.sun.java.swing.border.*;
33

34 import EDU.oswego.cs.dl.util.concurrent.*;
35 import java.awt.*;
36 import java.awt.event.*;
37 import java.io.*;
38 import java.net.*;
39 import java.lang.reflect.*;
40
41 /**
42  *
43  * This program records times for various fine-grained synchronization
44  * schemes, and provides some ways of measuring them over different
45  * context parameters.
46  *
47  * <p>
48  * Quick start:
49  * <ol>
50  * <li>javac -d <em>base of some CLASSPATH</em> *.java <br>
51  * You'll need Swing (JFC). (This
52  * program currently imports the javax.swing versions.
53  * You can edit imports to instead use other versions.)
54  * <li>java EDU.oswego.cs.dl.util.concurrent.misc.SynchronizationTimer <br>
55  * <li> Click<em> start</em>.
56  * Clicking <em>stop</em> cancels the run. Cancellation can take
57  * a while when there are a lot of threads.
58  * <li>For more explanation about tested classes, see
59  * <a HREF="http://gee.cs.oswego.edu/dl/classes/EDU/oswego/cs/dl/util/concurrent/intro.html">Documentation for util.concurrent</a>
60  * </ol>
61  *
62  * <p>
63  * Synchronization schemes are tested around implementations and
64  * subclasses of <code>RNG</code>, which is just a hacked random
65  * number generator class. Objects of this class have just enough
66  * state and require just enough computation to be reasonable minimal
67  * targets. (Additionally, random numbers are needed a lot in these
68  * kinds of time tests, so basing them on objects that produce random
69  * numbers is convenient.) Computation of each random number is
70  * padded a bit with an adjustable compute loop running a random
71  * number of times to avoid getting schedulers locked into
72  * uninteresting patterns.
73  *
74  * <p>
75  * Each iteration of each test ultimately somehow calls
76  * the random number generation
77  * method of an RNG. The time listed is the average time it took to do
78  * one iteration, in microseconds. These are just based on wallclock
79  * time (System.currentTimeMillis()). Thread
80  * construction time is <em>NOT</em> included in these times.
81  * In tests with many threads, construction and other bookkeeping
82  * can take longer than the tests themselves.
83  * <p>
84  * Results are listed in a table, and optionally printed on standard output.
85  * You can redirect standard output to save to a file.
86  * <p>
87  * The total amount of ``real'' computation reported in each cell is
88  * the same. Thus, the unobtainably ideal pattern of results would be
89  * for every cell of the table to be the same (and very small).
90  * <p>
91  * A thread pool (PooledExecutor) is used to manage the threads used in
92  * test runs. The current number of active threads is indicated in
93  * the panel. It should normally be at most three plus the number of threads used in the
94  * indicated test column (there are at most three overhead threads per run), although
95  * it may transiently climb, and is larger in those tests that
96  * generate their own internal threads (for example ThreadedExceutor). If the
97  * indicated size fails to return to zero within about 10 seconds of
98  * either hitting stop
99  * or the end of a run, you may have a
100  * problem with interruption handling on your Java VM.
101  *
102  * <p>
103  * This program cannot
104  * tell you how busy your computer is while running tests.
105  * You can run a utility program (for
106  * example <code>perfmeter</code> or <code>top</code> on unix)
107  * alongside this program
108  * to find out.
109  * <p>
110  * A number of control parameters can be changed at any time.
111  * Most combinations of parameter settings create contexts
112  * that are completely unrepresentative of those seen in practical
113  * applications. However, they can be set to provide rough analogs of
114  * real applications, and the results used as rough guesses about
115  * performance impact. Also, do not be too upset about slow
116  * performance on tests representing situations
117  * that would never occur in practice.
118  * <p>
119  *
120  * You can control parameters by clicking any of the following,
121  * at any time. (You can even change parameters
122  * while tests are running, in which case they will take
123  * effect as soon as possible. Most controls momentarily stall
124  * while test objects and threads are being constructed, to avoid
125  * inconsistencies during test runs.)
126  * <dl>
127  *
128  * <dt> Number of threads
129  *
130  * <dd> Controls concurrency. The indicated number of threads are
131  * started simultaneously and then waited out.
132  *
133  * <dt>Contention.
134  *
135  * <dd>Percent sharing among threads. Zero percent means that each
136  * thread has its own RNG object, so there is no
137  * interference among threads. The zero
138  * percent case thus shows the cost of synchronization mechanics that
139  * happen to never be needed.
140  * 100 percent sharing means that all
141  * threads call methods on the same object, so each thread will have to
142  * wait until the RNG objects are not being used by others.
143  * In between is in between: Only the given percentage of calls are
144  * made to shared RNG objects; others are to unshared.
145  * Contention in classes that use Channels works slightly differently:
146  * The Channels are shared, not the base RNG objects. (Another way
147  * of looking at it is that tests demonstrate effects of multiple
148  * producers and consumers on the same channel.)
149  *
150  * <dt>Classes
151  * <dd>You can choose to only test the indicated classes. You can
152  * probably figure out how to add more classes to run yourself.
153  *
154  * <dt>Calls per thread per test
155  *
156  * <dd>Specifies number of iterations per thread per test. The listed
157  * times are averages over these iterations. The default seems to
158  * provide precise enough values for informal testing purposes.
159  * You should expect to see a fair amount of variation across
160  * repeated runs.
161  * If you get zeroes printed in any cell, this means that the
162  * test ran too fast to measure in milleconds, so you should increase the
163  * iterations value.
164  *
165  * <dt> Computations per call
166  *
167  * <dd>Specifies length of each call by setting an internal looping
168  * parameter inside each RNG object. Shorter calls lead to shorter
169  * times between synchronization measures. Longer calls, along with
170  * high contention can be used to force timeouts to occur.
171  *
172  * <dt> Iterations per barrier.
173  *
174  * <dd> Specifies the number of iterations performed by each thread until
175  * a synchronization barrier is forced with other threads, forcing
176  * it to wait for other threads to reach the same number of iterations. This
177  * controls the amount of interaction (versus contention) among threads.
178  * Setting to a value greater than the number of iterations per test
179  * effectively disables barriers.
180  *
181  * <dt> Threads per barrier
182  *
183  * <dd> Specifies how many threads are forced to synchronize at each
184  * barrier point. Greater numbers cause more threads to wait for each
185  * other at barriers. Setting to 1 means that a thread only has to
186  * wait for itself, which means not to wait at all.
187  *
188  * <dt>Lock mode
189  *
190  * <dd>For classes that support it, this controls whether mutual
191  * exclusion waits are done via standard blocking synchronization, or
192  * a loop repeatedly calling a timed wait.
193  *
194  * <dt>Producer mode
195  *
196  * <dd>For classes that support it, this controls whether producers
197  * perform blocking puts versus loops repeatedly calling offer.
198  *
199  * <dt>Consumer mode
200  *
201  * <dd>For classes that support it, this controls whether consumers
202  * perform blocking takes versus loops repeatedly calling poll.
203  *
204  * <dt> Timeouts
205  *
206  * <dd> Specifies the duration of timeouts used in timeout mode. A
207  * value of zero results in pure spin-loops.
208  *
209  * <dt>Producer/consumer rates.
210  *
211  * <dd>For tests involving producer/consumer pairs, this controls
212  * whether the producer is much faster, about the same speed, or much
213  * slower than the consumer. This is implemented by having the
214  * producer do all, half, or none of the actual calls to update, in
215  * addition to adding elements to channel.
216  *
217  * <dt>Buffer capacity
218  *
219  * <dd>For tests involving finite capacity
220  * buffers, this controls maximum buffer size.
221  *
222  * </dl>
223  *
224  * <p>
225  * To scaffold all this, the RNG class is defined in
226  * layers. Each RNG has internal non-public methods that do the actual
227  * computation, and public methods that call the internal ones. The
228  * particular classes run in tests might change over time, but
229  * currently includes the following general kinds:
230  *
231  * <dl>
232  *
233  *
234  * <dt> Using built-in synchronization
235  * <dd> Versions of RNG classes that use (or don't use)
236  * synchronized methods and/or blocks. Also some tests of
237  * simple SynchronizedVariables. Tests that would not
238  * be thread-safe are not run when there is more than one
239  * thread and non-zero contention.
240  *
241  *
242  * <dt> Using <code>Sync</code> classes as locks
243  * <dd> Classes protecting public methods via Semaphores, mutexes, etc.
244  * In each case, the outer public methods delegate actions to
245  * another RNG object, surrounded by acquire/release/etc. The
246  * class called SDelegated does this using builtin
247  * synchronization rather than Sync locks
248  * so might be a useful comparison.
249  *
250  * <dt> Using Channels
251  * <dd> These classes work a little bit differently than the others.
252  * Each test arranges that half of the threads behave as producers,
253  * and half as consumers. Each test iteration puts/takes an RNG object
254  * through a channel before or after executing its update
255  * method. When the number of threads is one, each producer
256  * simply consumers its own object. Some Channels (notably
257  * SynchronousChannels) cannot be used with only one thread,
258  * in which case the test is skipped.
259  *
260  * <dt> Using Executors
261  * <dd> These classes arrange for each RNG update to occur
262  * as an executable command. Each test iteration passes a
263  * command to an Executor, which eventually executes it.
264  * Execution is overlapped: Each iteration starts a new
265  * command, and then waits for the previous command to complete.
266  *
267  * </dl>
268  *
269  * <p>
270  *
271  * The test code is ugly; it has just evolved over the years. Sorry.
272 **/

273
274 public class SynchronizationTimer {
275
276   /** Start up this application **/
277   public static void main(String JavaDoc[] args) {
278
279     JFrame frame = new JFrame("Times per call in microseconds");
280
281     frame.addWindowListener(new WindowAdapter() {
282       public void windowClosing(WindowEvent e) {System.exit(0);}
283     });
284   
285     frame.getContentPane().add(new SynchronizationTimer().mainPanel());
286     frame.pack();
287     frame.setVisible(true);
288   }
289
290   /**
291    * Information about classes to be tested
292    **/

293   static class TestedClass {
294     final String JavaDoc name;
295     final Class JavaDoc cls;
296     final boolean multipleOK;
297     final boolean singleOK;
298     final Class JavaDoc buffCls;
299     Boolean JavaDoc enabled_ = new Boolean JavaDoc(true);
300
301     synchronized void setEnabled(Boolean JavaDoc b) { enabled_ = b; }
302     synchronized Boolean JavaDoc getEnabled() { return enabled_; }
303
304     synchronized void toggleEnabled() {
305       boolean enabled = enabled_.booleanValue();
306       enabled_ = new Boolean JavaDoc(!enabled);
307     }
308     
309     synchronized boolean isEnabled(int nthreads, Fraction shared) {
310       boolean enabled = enabled_.booleanValue();
311       if (!enabled) return false;
312       if (!singleOK && nthreads <= 1) return false;
313       if (!multipleOK && nthreads > 1 && shared.compareTo(0) > 0) return false;
314       return true;
315     }
316     
317     
318     TestedClass(String JavaDoc n, Class JavaDoc c, boolean m, boolean sok) {
319       name = n; cls = c; multipleOK = m; singleOK = sok;
320       buffCls = null;
321     }
322     
323     TestedClass(String JavaDoc n, Class JavaDoc c, boolean m, boolean sok, Class JavaDoc bc) {
324       name = n; cls = c; multipleOK = m; singleOK = sok;
325       buffCls = bc;
326     }
327     
328     static final TestedClass dummy =
329       new TestedClass("", null, false, false);
330
331     static final TestedClass[] classes = {
332       
333       new TestedClass("NoSynchronization", NoSynchRNG.class, false, true),
334       new TestedClass("PublicSynchronization", PublicSynchRNG.class, true, true),
335       new TestedClass("NestedSynchronization", AllSynchRNG.class, true, true),
336       
337       new TestedClass("SDelegated", SDelegatedRNG.class, true, true),
338       
339       new TestedClass("SynchLongUsingSet", SynchLongRNG.class, true, true),
340       new TestedClass("SynchLongUsingCommit", AClongRNG.class, true, true),
341       
342       new TestedClass("Semaphore", SemRNG.class, true, true),
343       new TestedClass("WaiterPrefSemaphore", WpSemRNG.class, true, true),
344       new TestedClass("FIFOSemaphore", FifoRNG.class, true, true),
345       new TestedClass("PrioritySemaphore", PrioritySemRNG.class, true, true),
346       new TestedClass("Mutex", MutexRNG.class, true, true),
347       new TestedClass("ReentrantLock", RlockRNG.class, true, true),
348       
349       new TestedClass("WriterPrefRWLock", WpRWlockRNG.class, true, true),
350       new TestedClass("ReaderPrefRWLock", ReaderPrefRWlockRNG.class, true, true),
351       new TestedClass("FIFORWLock", FIFORWlockRNG.class, true, true),
352       new TestedClass("ReentrantRWL", ReentrantRWlockRNG.class, true, true),
353       
354       
355       
356       new TestedClass("LinkedQueue", ChanRNG.class, true, true,
357                       LinkedQueue.class),
358
359       new TestedClass("WaitFreeQueue", ChanRNG.class, true, true,
360                       WaitFreeQueue.class),
361
362       new TestedClass("BoundedLinkedQueue", ChanRNG.class, true, true,
363                       BoundedLinkedQueue.class),
364       new TestedClass("BoundedBuffer", ChanRNG.class, true, true,
365                       BoundedBuffer.class),
366       new TestedClass("CondVarBoundedBuffer", ChanRNG.class, true, true,
367                       CVBuffer.class),
368       new TestedClass("BoundedPriorityQueue", ChanRNG.class, true, true,
369                       BoundedPriorityQueue.class),
370       new TestedClass("Slot", ChanRNG.class, true, true,
371                       Slot.class),
372       // new TestedClass("FIFOSlot", ChanRNG.class, true, true, FIFOSlot.class),
373
new TestedClass("SynchronousChannel", ChanRNG.class, true, false,
374                       SynchronousChannel.class),
375
376       
377       new TestedClass("DirectExecutor", DirectExecutorRNG.class, true, true),
378       new TestedClass("SemaphoreLckExecutor", LockedSemRNG.class, true, true),
379       new TestedClass("QueuedExecutor", QueuedExecutorRNG.class, true, true),
380       new TestedClass("ThreadedExecutor", ThreadedExecutorRNG.class, true, true),
381       new TestedClass("PooledExecutor", PooledExecutorRNG.class, true, true),
382       
383       // new TestedClass("Pipe", ChanRNG.class, true, true, PipedChannel.class),
384
};
385   }
386
387
388
389   // test parameters
390

391   static final int[] nthreadsChoices = {
392     1,
393     2,
394     4,
395     8,
396     16,
397     32,
398     64,
399     128,
400     256,
401     512,
402     1024
403   };
404
405   static final int BLOCK_MODE = 0;
406   static final int TIMEOUT_MODE = 1;
407
408   static final int[] syncModes = { BLOCK_MODE, TIMEOUT_MODE, };
409
410   // misc formatting utilities
411

412   static String JavaDoc modeToString(int m) {
413     String JavaDoc sms;
414     if (m == BLOCK_MODE) sms = "block";
415     else if (m == TIMEOUT_MODE) sms = "timeout";
416     else sms = "No such mode";
417     return sms;
418   }
419
420   static String JavaDoc biasToString(int b) {
421     String JavaDoc sms;
422     if (b < 0) sms = "slower producer";
423     else if (b == 0) sms = "balanced prod/cons rate";
424     else if (b > 0) sms = "slower consumer";
425     else sms = "No such bias";
426     return sms;
427   }
428
429
430   static String JavaDoc p2ToString(int n) { // print power of two
431
String JavaDoc suf = "";
432     if (n >= 1024) {
433       n = n / 1024;
434       suf = "K";
435       if (n >= 1024) {
436         n = n / 1024;
437         suf = "M";
438       }
439     }
440     return n + suf;
441   }
442
443   static final int PRECISION = 10; // microseconds
444

445   static String JavaDoc formatTime(long ns, boolean showDecimal) {
446     long intpart = ns / PRECISION;
447     long decpart = ns % PRECISION;
448     if (!showDecimal) {
449       if (decpart >= PRECISION/2)
450         ++intpart;
451       return Long.toString(intpart);
452     }
453     else {
454       String JavaDoc sint = Long.toString(intpart);
455       String JavaDoc sdec = Long.toString(decpart);
456       if (decpart == 0) {
457         int z = PRECISION;
458         while (z > 10) {
459           sdec = "0" + sdec;
460           z /= 10;
461         }
462       }
463       String JavaDoc ts = sint + "." + sdec;
464       return ts;
465     }
466   }
467     
468   static class ThreadInfo {
469     final String JavaDoc name;
470     final int number;
471     Boolean JavaDoc enabled;
472     ThreadInfo(int nthr) {
473       number = nthr;
474       name = p2ToString(nthr);
475       enabled = new Boolean JavaDoc(true);
476     }
477
478     synchronized Boolean JavaDoc getEnabled() { return enabled; }
479     synchronized void setEnabled(Boolean JavaDoc v) { enabled = v; }
480     synchronized void toggleEnabled() {
481       enabled = new Boolean JavaDoc(!enabled.booleanValue());
482     }
483   }
484
485   final ThreadInfo[] threadInfo = new ThreadInfo[nthreadsChoices.length];
486
487   boolean threadEnabled(int nthreads) {
488     return threadInfo[nthreads].getEnabled().booleanValue();
489   }
490
491   // This used to be a JTable datamodel, but now just part of this class ...
492

493   final static int headerRows = 1;
494   final static int classColumn = 0;
495   final static int headerColumns = 1;
496   final int tableRows = TestedClass.classes.length + headerRows;
497   final int tableColumns = nthreadsChoices.length + headerColumns;
498   
499   final JComponent[][] resultTable_ = new JComponent[tableRows][tableColumns];
500   
501   JPanel resultPanel() {
502
503     JPanel[] colPanel = new JPanel[tableColumns];
504     for (int col = 0; col < tableColumns; ++col) {
505       colPanel[col] = new JPanel();
506       colPanel[col].setLayout(new GridLayout(tableRows, 1));
507       if (col != 0)
508         colPanel[col].setBackground(Color.white);
509     }
510
511     Color hdrbg = colPanel[0].getBackground();
512     Border border = new LineBorder(hdrbg);
513
514     Font font = new Font("Dialog", Font.PLAIN, 12);
515     Dimension labDim = new Dimension(40, 16);
516     Dimension cbDim = new Dimension(154, 16);
517
518     JLabel cornerLab = new JLabel(" Classes \\ Threads");
519     cornerLab.setMinimumSize(cbDim);
520     cornerLab.setPreferredSize(cbDim);
521     cornerLab.setFont(font);
522     resultTable_[0][0] = cornerLab;
523     colPanel[0].add(cornerLab);
524     
525     for (int col = 1; col < tableColumns; ++col) {
526       final int nthreads = col - headerColumns;
527       JCheckBox tcb = new JCheckBox(threadInfo[nthreads].name, true);
528       tcb.addActionListener(new ActionListener() {
529         public void actionPerformed(ActionEvent evt) {
530           threadInfo[nthreads].toggleEnabled();
531         }});
532       
533       
534       tcb.setMinimumSize(labDim);
535       tcb.setPreferredSize(labDim);
536       tcb.setFont(font);
537       tcb.setBackground(hdrbg);
538       resultTable_[0][col] = tcb;
539       colPanel[col].add(tcb);
540     }
541     
542     
543     for (int row = 1; row < tableRows; ++row) {
544       final int cls = row - headerRows;
545       
546       JCheckBox cb = new JCheckBox(TestedClass.classes[cls].name, true);
547       cb.addActionListener(new ActionListener() {
548         public void actionPerformed(ActionEvent evt) {
549           TestedClass.classes[cls].toggleEnabled();
550         }});
551       
552       resultTable_[row][0] = cb;
553       cb.setMinimumSize(cbDim);
554       cb.setPreferredSize(cbDim);
555       cb.setFont(font);
556       colPanel[0].add(cb);
557       
558       for (int col = 1; col < tableColumns; ++col) {
559         int nthreads = col - headerColumns;
560         JLabel lab = new JLabel("");
561         resultTable_[row][col] = lab;
562         
563         lab.setMinimumSize(labDim);
564         lab.setPreferredSize(labDim);
565         lab.setBorder(border);
566         lab.setFont(font);
567         lab.setBackground(Color.white);
568         lab.setForeground(Color.black);
569         lab.setHorizontalAlignment(JLabel.RIGHT);
570         
571         colPanel[col].add(lab);
572       }
573     }
574     
575     JPanel tblPanel = new JPanel();
576     tblPanel.setLayout(new BoxLayout(tblPanel, BoxLayout.X_AXIS));
577     for (int col = 0; col < tableColumns; ++col) {
578       tblPanel.add(colPanel[col]);
579     }
580     
581     return tblPanel;
582     
583   }
584
585   void setTime(final long ns, int clsIdx, int nthrIdx) {
586     int row = clsIdx+headerRows;
587     int col = nthrIdx+headerColumns;
588     final JLabel cell = (JLabel)(resultTable_[row][col]);
589
590     SwingUtilities.invokeLater(new Runnable JavaDoc() {
591       public void run() {
592         cell.setText(formatTime(ns, true));
593       }
594     });
595   }
596   
597      
598
599   void clearTable() {
600     for (int i = 1; i < tableRows; ++i) {
601       for (int j = 1; j < tableColumns; ++j) {
602         ((JLabel)(resultTable_[i][j])).setText("");
603       }
604     }
605   }
606
607   void setChecks(final boolean setting) {
608     for (int i = 0; i < TestedClass.classes.length; ++i) {
609       TestedClass.classes[i].setEnabled(new Boolean JavaDoc(setting));
610       ((JCheckBox)resultTable_[i+1][0]).setSelected(setting);
611     }
612   }
613
614
615   public SynchronizationTimer() {
616     for (int i = 0; i < threadInfo.length; ++i)
617       threadInfo[i] = new ThreadInfo(nthreadsChoices[i]);
618
619   }
620   
621   final SynchronizedInt nextClassIdx_ = new SynchronizedInt(0);
622   final SynchronizedInt nextThreadIdx_ = new SynchronizedInt(0);
623
624
625   JPanel mainPanel() {
626     new PrintStart(); // classloader bug workaround
627
JPanel paramPanel = new JPanel();
628     paramPanel.setLayout(new GridLayout(5, 3));
629
630     JPanel buttonPanel = new JPanel();
631     buttonPanel.setLayout(new GridLayout(1, 3));
632     
633     startstop_.addActionListener(new ActionListener() {
634       public void actionPerformed(ActionEvent evt) {
635         if (running_.get())
636           cancel();
637         else {
638           try {
639             startTestSeries(new TestSeries());
640           }
641           catch (InterruptedException JavaDoc ex) {
642             endTestSeries();
643           }
644         }
645       }});
646     
647     paramPanel.add(startstop_);
648     
649     JPanel p1 = new JPanel();
650     p1.setLayout(new GridLayout(1, 2));
651     
652     JButton continueButton = new JButton("Continue");
653
654     continueButton.addActionListener(new ActionListener() {
655       public void actionPerformed(ActionEvent evt) {
656         if (!running_.get()) {
657           try {
658             startTestSeries(new TestSeries(nextClassIdx_.get(),
659                                            nextThreadIdx_.get()));
660           }
661           catch (InterruptedException JavaDoc ex) {
662             endTestSeries();
663           }
664         }
665       }});
666
667     p1.add(continueButton);
668
669     JButton clearButton = new JButton("Clear cells");
670     
671     clearButton.addActionListener(new ActionListener(){
672       public void actionPerformed(ActionEvent evt) {
673         clearTable();
674       }
675     });
676
677     p1.add(clearButton);
678
679     paramPanel.add(p1);
680
681     JPanel p3 = new JPanel();
682     p3.setLayout(new GridLayout(1, 2));
683     
684     JButton setButton = new JButton("All classes");
685     
686     setButton.addActionListener(new ActionListener(){
687       public void actionPerformed(ActionEvent evt) {
688         setChecks(true);
689       }
690     });
691
692     p3.add(setButton);
693
694
695     JButton unsetButton = new JButton("No classes");
696     
697     unsetButton.addActionListener(new ActionListener(){
698       public void actionPerformed(ActionEvent evt) {
699         setChecks(false);
700       }
701     });
702
703     p3.add(unsetButton);
704     paramPanel.add(p3);
705
706     JPanel p2 = new JPanel();
707     // p2.setLayout(new GridLayout(1, 2));
708
p2.setLayout(new BoxLayout(p2, BoxLayout.X_AXIS));
709
710
711     JCheckBox consoleBox = new JCheckBox("Console echo");
712     consoleBox.addItemListener(new ItemListener() {
713       public void itemStateChanged(ItemEvent evt) {
714         echoToSystemOut.complement();
715       }
716     });
717
718     
719
720     JLabel poolinfo = new JLabel("Active threads: 0");
721
722     p2.add(poolinfo);
723     p2.add(consoleBox);
724
725     paramPanel.add(p2);
726
727     paramPanel.add(contentionBox());
728     paramPanel.add(itersBox());
729     paramPanel.add(cloopBox());
730     paramPanel.add(barrierBox());
731     paramPanel.add(exchangeBox());
732     paramPanel.add(biasBox());
733     paramPanel.add(capacityBox());
734     paramPanel.add(timeoutBox());
735     paramPanel.add(syncModePanel());
736     paramPanel.add(producerSyncModePanel());
737     paramPanel.add(consumerSyncModePanel());
738
739     startPoolStatus(poolinfo);
740
741     JPanel mainPanel = new JPanel();
742     mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.Y_AXIS));
743
744     JPanel tblPanel = resultPanel();
745
746     mainPanel.add(tblPanel);
747     mainPanel.add(paramPanel);
748     return mainPanel;
749   }
750
751   
752   
753   
754   JComboBox syncModePanel() {
755     JComboBox syncModeComboBox = new JComboBox();
756     
757     for (int j = 0; j < syncModes.length; ++j) {
758       String JavaDoc lab = "Locks: " + modeToString(syncModes[j]);
759       syncModeComboBox.addItem(lab);
760     }
761     syncModeComboBox.addItemListener(new ItemListener() {
762       public void itemStateChanged(ItemEvent evt) {
763         JComboBox src = (JComboBox)(evt.getItemSelectable());
764         int idx = src.getSelectedIndex();
765         RNG.syncMode.set(syncModes[idx]);
766       }
767     });
768     
769     RNG.syncMode.set(syncModes[0]);
770     syncModeComboBox.setSelectedIndex(0);
771     return syncModeComboBox;
772   }
773
774   JComboBox producerSyncModePanel() {
775     JComboBox producerSyncModeComboBox = new JComboBox();
776     
777     for (int j = 0; j < syncModes.length; ++j) {
778       String JavaDoc lab = "Producers: " + modeToString(syncModes[j]);
779       producerSyncModeComboBox.addItem(lab);
780     }
781     producerSyncModeComboBox.addItemListener(new ItemListener() {
782       public void itemStateChanged(ItemEvent evt) {
783         JComboBox src = (JComboBox)(evt.getItemSelectable());
784         int idx = src.getSelectedIndex();
785         RNG.producerMode.set(syncModes[idx]);
786       }
787     });
788     
789     RNG.producerMode.set(syncModes[0]);
790     producerSyncModeComboBox.setSelectedIndex(0);
791     return producerSyncModeComboBox;
792   }
793
794   JComboBox consumerSyncModePanel() {
795     JComboBox consumerSyncModeComboBox = new JComboBox();
796     
797     for (int j = 0; j < syncModes.length; ++j) {
798       String JavaDoc lab = "Consumers: " + modeToString(syncModes[j]);
799       consumerSyncModeComboBox.addItem(lab);
800     }
801     consumerSyncModeComboBox.addItemListener(new ItemListener() {
802       public void itemStateChanged(ItemEvent evt) {
803         JComboBox src = (JComboBox)(evt.getItemSelectable());
804         int idx = src.getSelectedIndex();
805         RNG.consumerMode.set(syncModes[idx]);
806       }
807     });
808     
809     RNG.consumerMode.set(syncModes[0]);
810     consumerSyncModeComboBox.setSelectedIndex(0);
811     return consumerSyncModeComboBox;
812   }
813
814
815   
816   JComboBox contentionBox() {
817     final Fraction[] contentionChoices = {
818       new Fraction(0, 1),
819       new Fraction(1, 16),
820       new Fraction(1, 8),
821       new Fraction(1, 4),
822       new Fraction(1, 2),
823       new Fraction(1, 1)
824     };
825     
826     JComboBox contentionComboBox = new JComboBox();
827     
828     for (int j = 0; j < contentionChoices.length; ++j) {
829       String JavaDoc lab = contentionChoices[j].asDouble() * 100.0 +
830         "% contention/sharing";
831       contentionComboBox.addItem(lab);
832     }
833     contentionComboBox.addItemListener(new ItemListener() {
834       public void itemStateChanged(ItemEvent evt) {
835         JComboBox src = (JComboBox)(evt.getItemSelectable());
836         int idx = src.getSelectedIndex();
837         contention_.set(contentionChoices[idx]);
838       }
839     });
840     
841     contention_.set(contentionChoices[3]);
842     contentionComboBox.setSelectedIndex(3);
843     return contentionComboBox;
844   }
845   
846   JComboBox itersBox() {
847     final int[] loopsPerTestChoices = {
848       1,
849       16,
850       256,
851       1024,
852       2 * 1024,
853       4 * 1024,
854       8 * 1024,
855       16 * 1024,
856       32 * 1024,
857       64 * 1024,
858       128 * 1024,
859       256 * 1024,
860       512 * 1024,
861       1024 * 1024,
862     };
863     
864     JComboBox precComboBox = new JComboBox();
865     
866     for (int j = 0; j < loopsPerTestChoices.length; ++j) {
867       String JavaDoc lab = p2ToString(loopsPerTestChoices[j]) +
868         " calls per thread per test";
869       precComboBox.addItem(lab);
870     }
871     precComboBox.addItemListener(new ItemListener() {
872       public void itemStateChanged(ItemEvent evt) {
873         JComboBox src = (JComboBox)(evt.getItemSelectable());
874         int idx = src.getSelectedIndex();
875         loopsPerTest_.set(loopsPerTestChoices[idx]);
876       }
877     });
878     
879     loopsPerTest_.set(loopsPerTestChoices[8]);
880     precComboBox.setSelectedIndex(8);
881
882     return precComboBox;
883   }
884   
885   JComboBox cloopBox() {
886     final int[] computationsPerCallChoices = {
887       1,
888       2,
889       4,
890       8,
891       16,
892       32,
893       64,
894       128,
895       256,
896       512,
897       1024,
898       2 * 1024,
899       4 * 1024,
900       8 * 1024,
901       16 * 1024,
902       32 * 1024,
903       64 * 1024,
904     };
905     
906     JComboBox cloopComboBox = new JComboBox();
907     
908     for (int j = 0; j < computationsPerCallChoices.length; ++j) {
909       String JavaDoc lab = p2ToString(computationsPerCallChoices[j]) +
910         " computations per call";
911       cloopComboBox.addItem(lab);
912     }
913     cloopComboBox.addItemListener(new ItemListener() {
914       public void itemStateChanged(ItemEvent evt) {
915         JComboBox src = (JComboBox)(evt.getItemSelectable());
916         int idx = src.getSelectedIndex();
917         RNG.computeLoops.set(computationsPerCallChoices[idx]);
918       }
919     });
920     
921     RNG.computeLoops.set(computationsPerCallChoices[3]);
922     cloopComboBox.setSelectedIndex(3);
923     return cloopComboBox;
924   }
925   
926   JComboBox barrierBox() {
927     final int[] itersPerBarrierChoices = {
928       1,
929       2,
930       4,
931       8,
932       16,
933       32,
934       64,
935       128,
936       256,
937       512,
938       1024,
939       2 * 1024,
940       4 * 1024,
941       8 * 1024,
942       16 * 1024,
943       32 * 1024,
944       64 * 1024,
945       128 * 1024,
946       256 * 1024,
947       512 * 1024,
948       1024 * 1024,
949     };
950     
951     JComboBox barrierComboBox = new JComboBox();
952     
953     for (int j = 0; j < itersPerBarrierChoices.length; ++j) {
954       String JavaDoc lab = p2ToString(itersPerBarrierChoices[j]) +
955         " iterations per barrier";
956       barrierComboBox.addItem(lab);
957     }
958     barrierComboBox.addItemListener(new ItemListener() {
959       public void itemStateChanged(ItemEvent evt) {
960         JComboBox src = (JComboBox)(evt.getItemSelectable());
961         int idx = src.getSelectedIndex();
962         RNG.itersPerBarrier.set(itersPerBarrierChoices[idx]);
963       }
964     });
965     
966     RNG.itersPerBarrier.set(itersPerBarrierChoices[13]);
967     barrierComboBox.setSelectedIndex(13);
968
969     // RNG.itersPerBarrier.set(itersPerBarrierChoices[15]);
970
// barrierComboBox.setSelectedIndex(15);
971

972     return barrierComboBox;
973   }
974   
975   JComboBox exchangeBox() {
976     final int[] exchangerChoices = {
977       1,
978       2,
979       4,
980       8,
981       16,
982       32,
983       64,
984       128,
985       256,
986       512,
987       1024,
988     };
989     
990     JComboBox exchComboBox = new JComboBox();
991     
992     for (int j = 0; j < exchangerChoices.length; ++j) {
993       String JavaDoc lab = p2ToString(exchangerChoices[j]) +
994         " max threads per barrier";
995       exchComboBox.addItem(lab);
996     }
997     exchComboBox.addItemListener(new ItemListener() {
998       public void itemStateChanged(ItemEvent evt) {
999         JComboBox src = (JComboBox)(evt.getItemSelectable());
1000        int idx = src.getSelectedIndex();
1001        RNG.exchangeParties.set(exchangerChoices[idx]);
1002      }
1003    });
1004    
1005    RNG.exchangeParties.set(exchangerChoices[1]);
1006    exchComboBox.setSelectedIndex(1);
1007    return exchComboBox;
1008  }
1009  
1010  JComboBox biasBox() {
1011    final int[] biasChoices = {
1012      -1,
1013      0,
1014      1
1015    };
1016    
1017    
1018    JComboBox biasComboBox = new JComboBox();
1019    
1020    for (int j = 0; j < biasChoices.length; ++j) {
1021      String JavaDoc lab = biasToString(biasChoices[j]);
1022      biasComboBox.addItem(lab);
1023    }
1024    biasComboBox.addItemListener(new ItemListener() {
1025      public void itemStateChanged(ItemEvent evt) {
1026        JComboBox src = (JComboBox)(evt.getItemSelectable());
1027        int idx = src.getSelectedIndex();
1028        RNG.bias.set(biasChoices[idx]);
1029      }
1030    });
1031    
1032    RNG.bias.set(biasChoices[1]);
1033    biasComboBox.setSelectedIndex(1);
1034    return biasComboBox;
1035  }
1036  
1037  JComboBox capacityBox() {
1038    
1039    final int[] bufferCapacityChoices = {
1040      1,
1041      4,
1042      64,
1043      256,
1044      1024,
1045      4096,
1046      16 * 1024,
1047      64 * 1024,
1048      256 * 1024,
1049      1024 * 1024,
1050    };
1051    
1052    JComboBox bcapComboBox = new JComboBox();
1053    
1054    for (int j = 0; j < bufferCapacityChoices.length; ++j) {
1055      String JavaDoc lab = p2ToString(bufferCapacityChoices[j]) +
1056        " element bounded buffers";
1057      bcapComboBox.addItem(lab);
1058    }
1059    bcapComboBox.addItemListener(new ItemListener() {
1060      public void itemStateChanged(ItemEvent evt) {
1061        JComboBox src = (JComboBox)(evt.getItemSelectable());
1062        int idx = src.getSelectedIndex();
1063        DefaultChannelCapacity.set(bufferCapacityChoices[idx]);
1064      }
1065    });
1066    
1067    
1068    DefaultChannelCapacity.set(bufferCapacityChoices[3]);
1069    bcapComboBox.setSelectedIndex(3);
1070    return bcapComboBox;
1071  }
1072  
1073  JComboBox timeoutBox() {
1074    
1075    
1076    final long[] timeoutChoices = {
1077      0,
1078      1,
1079      10,
1080      100,
1081      1000,
1082      10000,
1083      100000,
1084    };
1085    
1086    
1087    JComboBox timeoutComboBox = new JComboBox();
1088    
1089    for (int j = 0; j < timeoutChoices.length; ++j) {
1090      String JavaDoc lab = timeoutChoices[j] + " msec timeouts";
1091      timeoutComboBox.addItem(lab);
1092    }
1093    timeoutComboBox.addItemListener(new ItemListener() {
1094      public void itemStateChanged(ItemEvent evt) {
1095        JComboBox src = (JComboBox)(evt.getItemSelectable());
1096        int idx = src.getSelectedIndex();
1097        RNG.timeout.set(timeoutChoices[idx]);
1098      }
1099    });
1100    
1101    RNG.timeout.set(timeoutChoices[3]);
1102    timeoutComboBox.setSelectedIndex(3);
1103    return timeoutComboBox;
1104  }
1105
1106  ClockDaemon timeDaemon = new ClockDaemon();
1107  
1108  void startPoolStatus(final JLabel status) {
1109    Runnable JavaDoc updater = new Runnable JavaDoc() {
1110      int lastps = 0;
1111      public void run() {
1112        final int ps = Threads.activeThreads.get();
1113        if (lastps != ps) {
1114          lastps = ps;
1115          SwingUtilities.invokeLater(new Runnable JavaDoc() {
1116            public void run() {
1117              status.setText("Active threads: " + ps);
1118            } } );
1119        }
1120      }
1121    };
1122    timeDaemon.executePeriodically(250, updater, false);
1123  }
1124
1125  private final SynchronizedRef contention_ = new SynchronizedRef(null);
1126  private final SynchronizedInt loopsPerTest_ = new SynchronizedInt(0);
1127
1128  private final SynchronizedBoolean echoToSystemOut =
1129      new SynchronizedBoolean(false);
1130
1131
1132  private final JButton startstop_ = new JButton("Start");
1133  
1134  private WaitableInt testNumber_ = new WaitableInt(1);
1135
1136  private void runOneTest(Runnable JavaDoc tst) throws InterruptedException JavaDoc {
1137    int nt = testNumber_.get();
1138    Threads.pool.execute(tst);
1139    testNumber_.whenNotEqual(nt, null);
1140  }
1141
1142  private void endOneTest() {
1143    testNumber_.increment();
1144  }
1145
1146  private SynchronizedBoolean running_ = new SynchronizedBoolean(false);
1147
1148  void cancel() {
1149    // not stable enough to cancel during construction
1150
synchronized (RNG.constructionLock) {
1151      try {
1152        Threads.pool.interruptAll();
1153      }
1154      catch(Exception JavaDoc ex) {
1155        System.out.println("\nException during cancel:\n" + ex);
1156        return;
1157      }
1158    }
1159  }
1160
1161
1162  void startTestSeries(Runnable JavaDoc tst) throws InterruptedException JavaDoc {
1163    running_.set(true);
1164    startstop_.setText("Stop");
1165    Threads.pool.execute(tst);
1166  }
1167
1168  // prevent odd class-gc problems on some VMs?
1169
class PrintStart implements Runnable JavaDoc {
1170    public void run() {
1171      startstop_.setText("Start");
1172    }
1173  }
1174
1175
1176  void endTestSeries() {
1177    running_.set(false);
1178    SwingUtilities.invokeLater(new PrintStart());
1179  }
1180
1181  /*
1182  void old_endTestSeries() {
1183    running_.set(false);
1184    SwingUtilities.invokeLater(new Runnable() {
1185      public void run() {
1186        startstop_.setText("Start");
1187      } } );
1188  }
1189  */

1190
1191  class TestSeries implements Runnable JavaDoc {
1192    final int firstclass;
1193    final int firstnthreads;
1194
1195    TestSeries() {
1196      firstclass = 0;
1197      firstnthreads = 0;
1198    }
1199
1200    TestSeries(final int firstc, final int firstnt) {
1201      firstclass = firstc;
1202      firstnthreads = firstnt;
1203    }
1204
1205    public void run() {
1206      Thread.currentThread().setPriority(Thread.NORM_PRIORITY);
1207
1208      try {
1209        int t = firstnthreads;
1210        int c = firstclass;
1211
1212        if (t < nthreadsChoices.length &&
1213            c < TestedClass.classes.length) {
1214
1215          for (;;) {
1216
1217            
1218            // these checks are duplicated in OneTest, but added here
1219
// to minimize unecessary thread construction,
1220
// which can skew results
1221

1222            if (threadEnabled(t)) {
1223
1224              TestedClass entry = TestedClass.classes[c];
1225        
1226              int nthreads = nthreadsChoices[t];
1227              int iters = loopsPerTest_.get();
1228              Fraction pshr = (Fraction)(contention_.get());
1229        
1230              if (entry.isEnabled(nthreads, pshr)) {
1231
1232                runOneTest(new OneTest(c, t));
1233              }
1234            }
1235
1236            if (++c >= TestedClass.classes.length) {
1237              c = 0;
1238              if (++t >= nthreadsChoices.length)
1239                break;
1240            }
1241
1242            nextClassIdx_.set(c);
1243            nextThreadIdx_.set(t);
1244            
1245          }
1246        }
1247
1248      }
1249      catch (InterruptedException JavaDoc ex) {
1250        Thread.currentThread().interrupt();
1251      }
1252      finally {
1253        endTestSeries();
1254      }
1255    }
1256  }
1257
1258  static class BarrierTimer implements Runnable JavaDoc {
1259    private long startTime_ = 0;
1260    private long endTime_ = 0;
1261
1262    public synchronized long getTime() {
1263      return endTime_ - startTime_;
1264    }
1265
1266    public synchronized void run() {
1267      long now = System.currentTimeMillis();
1268      if (startTime_ == 0)
1269        startTime_ = now;
1270      else
1271        endTime_ = now;
1272    }
1273  }
1274      
1275  class OneTest implements Runnable JavaDoc {
1276    final int clsIdx;
1277    final int nthreadsIdx;
1278
1279    OneTest(int idx, int t) {
1280      clsIdx = idx;
1281      nthreadsIdx = t;
1282    }
1283
1284    public void run() {
1285      Thread.currentThread().setPriority(Thread.NORM_PRIORITY-3);
1286
1287      boolean wasInterrupted = false;
1288
1289      final TestedClass entry = TestedClass.classes[clsIdx];
1290
1291      final JLabel cell = (JLabel)(resultTable_[clsIdx+1][nthreadsIdx+1]);
1292      final Color oldfg = cell.getForeground();
1293
1294      try {
1295
1296
1297        if (Thread.interrupted()) return;
1298        if (!threadEnabled(nthreadsIdx)) return;
1299        
1300        int nthreads = nthreadsChoices[nthreadsIdx];
1301        int iters = loopsPerTest_.get();
1302        Fraction pshr = (Fraction)(contention_.get());
1303        
1304        if (!entry.isEnabled(nthreads, pshr)) return;
1305
1306        BarrierTimer timer = new BarrierTimer();
1307        CyclicBarrier barrier = new CyclicBarrier(nthreads+1, timer);
1308
1309        Class JavaDoc cls = entry.cls;
1310        Class JavaDoc chanCls = entry.buffCls;
1311
1312        try {
1313          SwingUtilities.invokeAndWait(new Runnable JavaDoc() {
1314            public void run() {
1315              cell.setForeground(Color.blue);
1316              cell.setText("RUN");
1317              cell.repaint();
1318            }
1319          });
1320        }
1321        catch (InvocationTargetException ex) {
1322          ex.printStackTrace();
1323          System.exit(-1);
1324        }
1325        synchronized (RNG.constructionLock) {
1326          RNG.reset(nthreads);
1327
1328          if (chanCls == null) {
1329            RNG shared = (RNG)(cls.newInstance());
1330            for (int k = 0; k < nthreads; ++k) {
1331              RNG pri = (RNG)(cls.newInstance());
1332              TestLoop l = new TestLoop(shared, pri, pshr, iters, barrier);
1333              Threads.pool.execute(l.testLoop());
1334            }
1335          }
1336          else {
1337            Channel shared = (Channel)(chanCls.newInstance());
1338            if (nthreads == 1) {
1339              ChanRNG single = (ChanRNG)(cls.newInstance());
1340              single.setSingle(true);
1341              PCTestLoop l = new PCTestLoop(single.getDelegate(), single, pshr,
1342                                            iters, barrier,
1343                                            shared, shared);
1344              Threads.pool.execute(l.testLoop(true));
1345            }
1346            else if (nthreads % 2 != 0)
1347              throw new Error JavaDoc("Must have even number of threads!");
1348            else {
1349              int npairs = nthreads / 2;
1350              
1351              for (int k = 0; k < npairs; ++k) {
1352                ChanRNG t = (ChanRNG)(cls.newInstance());
1353                t.setSingle(false);
1354                Channel chan = (Channel)(chanCls.newInstance());
1355                
1356                PCTestLoop l = new PCTestLoop(t.getDelegate(), t, pshr,
1357                                              iters, barrier,
1358                                              shared, chan);
1359                
1360                Threads.pool.execute(l.testLoop(false));
1361                Threads.pool.execute(l.testLoop(true));
1362                
1363              }
1364            }
1365          }
1366
1367          if (echoToSystemOut.get()) {
1368            System.out.print(
1369                             entry.name + " " +
1370                             nthreads + "T " +
1371                             pshr + "S " +
1372                             RNG.computeLoops.get() + "I " +
1373                             RNG.syncMode.get() + "Lm " +
1374                             RNG.timeout.get() + "TO " +
1375                             RNG.producerMode.get() + "Pm " +
1376                             RNG.consumerMode.get() + "Cm " +
1377                             RNG.bias.get() + "B " +
1378                             DefaultChannelCapacity.get() + "C " +
1379                             RNG.exchangeParties.get() + "Xp " +
1380                             RNG.itersPerBarrier.get() + "Ib : "
1381                             );
1382          }
1383
1384        }
1385        
1386        // Uncomment if AWT doesn't update right
1387
// Thread.sleep(100);
1388

1389        barrier.barrier(); // start
1390

1391        barrier.barrier(); // stop
1392

1393        long tm = timer.getTime();
1394        long totalIters = nthreads * iters;
1395        double dns = tm * 1000.0 * PRECISION / totalIters;
1396        long ns = Math.round(dns);
1397
1398        setTime(ns, clsIdx, nthreadsIdx);
1399
1400        if (echoToSystemOut.get()) {
1401          System.out.println(formatTime(ns, true));
1402        }
1403
1404      }
1405      catch (BrokenBarrierException ex) {
1406        wasInterrupted = true;
1407      }
1408      catch (InterruptedException JavaDoc ex) {
1409        wasInterrupted = true;
1410        Thread.currentThread().interrupt();
1411      }
1412      catch (Exception JavaDoc ex) {
1413        ex.printStackTrace();
1414        System.out.println("Construction Exception?");
1415        System.exit(-1);
1416      }
1417      finally {
1418        final boolean clear = wasInterrupted;
1419        SwingUtilities.invokeLater(new Runnable JavaDoc() {
1420          public void run() {
1421            if (clear) cell.setText("");
1422            cell.setForeground(oldfg);
1423            cell.repaint();
1424          }
1425        });
1426
1427        Thread.currentThread().setPriority(Thread.NORM_PRIORITY);
1428        endOneTest();
1429      }
1430    }
1431  }
1432
1433}
1434
1435class Threads implements ThreadFactory {
1436
1437  static final SynchronizedInt activeThreads = new SynchronizedInt(0);
1438
1439  static final Threads factory = new Threads();
1440
1441  static final PooledExecutor pool = new PooledExecutor();
1442
1443  static {
1444    pool.setKeepAliveTime(10000);
1445    pool.setThreadFactory(factory);
1446  }
1447
1448  static class MyThread extends Thread JavaDoc {
1449    public MyThread(Runnable JavaDoc cmd) {
1450      super(cmd);
1451    }
1452
1453    public void run() {
1454      activeThreads.increment();
1455
1456      try {
1457        super.run();
1458      }
1459      finally {
1460        activeThreads.decrement();
1461      }
1462    }
1463  }
1464
1465  public Thread JavaDoc newThread(Runnable JavaDoc cmd) {
1466    return new MyThread(cmd);
1467  }
1468}
1469
1470
1471
1472class TestLoop {
1473
1474  final RNG shared;
1475  final RNG primary;
1476  final int iters;
1477  final Fraction pshared;
1478  final CyclicBarrier barrier;
1479  final boolean[] useShared;
1480  final int firstidx;
1481
1482  public TestLoop(RNG sh, RNG pri, Fraction pshr, int it, CyclicBarrier br) {
1483    shared = sh;
1484    primary = pri;
1485    pshared = pshr;
1486    iters = it;
1487    barrier = br;
1488
1489    firstidx = (int)(primary.get());
1490
1491    int num = (int)(pshared.numerator());
1492    int denom = (int)(pshared.denominator());
1493
1494    if (num == 0 || primary == shared) {
1495      useShared = new boolean[1];
1496      useShared[0] = false;
1497    }
1498    else if (num >= denom) {
1499      useShared = new boolean[1];
1500      useShared[0] = true;
1501    }
1502    else {
1503      // create bool array and randomize it.
1504
// This ensures that always same number of shared calls.
1505

1506      // denom slots is too few. iters is too many. an arbitrary compromise is:
1507
int xfactor = 1024 / denom;
1508      if (xfactor < 1) xfactor = 1;
1509      useShared = new boolean[denom * xfactor];
1510      for (int i = 0; i < num * xfactor; ++i)
1511        useShared[i] = true;
1512      for (int i = num * xfactor; i < denom * xfactor; ++i)
1513        useShared[i] = false;
1514
1515      for (int i = 1; i < useShared.length; ++i) {
1516        int j = ((int) (shared.next() & 0x7FFFFFFF)) % (i + 1);
1517        boolean tmp = useShared[i];
1518        useShared[i] = useShared[j];
1519        useShared[j] = tmp;
1520      }
1521    }
1522  }
1523
1524  public Runnable JavaDoc testLoop() {
1525    return new Runnable JavaDoc() {
1526      public void run() {
1527        int itersPerBarrier = RNG.itersPerBarrier.get();
1528        try {
1529          int delta = -1;
1530          if (primary.getClass().equals(PrioritySemRNG.class)) {
1531            delta = 2 - (int)((primary.get() % 5));
1532          }
1533          Thread.currentThread().setPriority(Thread.NORM_PRIORITY+delta);
1534          
1535          int nshared = (int)(iters * pshared.asDouble());
1536          int nprimary = iters - nshared;
1537          int idx = firstidx;
1538          
1539          barrier.barrier();
1540          
1541          for (int i = iters; i > 0; --i) {
1542            ++idx;
1543            if (i % itersPerBarrier == 0)
1544              primary.exchange();
1545            else {
1546              
1547              RNG r;
1548              
1549              if (nshared > 0 && useShared[idx % useShared.length]) {
1550                --nshared;
1551                r = shared;
1552              }
1553              else {
1554                --nprimary;
1555                r = primary;
1556              }
1557              long rnd = r.next();
1558              if (rnd % 2 == 0 && Thread.currentThread().isInterrupted())
1559                break;
1560            }
1561          }
1562        }
1563        catch (BrokenBarrierException ex) {
1564        }
1565        catch (InterruptedException JavaDoc ex) {
1566          Thread.currentThread().interrupt();
1567        }
1568        finally {
1569          try {
1570            barrier.barrier();
1571          }
1572          catch (BrokenBarrierException ex) {
1573          }
1574          catch (InterruptedException JavaDoc ex) {
1575            Thread.currentThread().interrupt();
1576          }
1577          finally {
1578            Thread.currentThread().setPriority(Thread.NORM_PRIORITY);
1579          }
1580
1581        }
1582      }
1583    };
1584  }
1585}
1586
1587class PCTestLoop extends TestLoop {
1588  final Channel primaryChannel;
1589  final Channel sharedChannel;
1590
1591  public PCTestLoop(RNG sh, RNG pri, Fraction pshr, int it,
1592    CyclicBarrier br, Channel shChan, Channel priChan) {
1593    super(sh, pri, pshr, it, br);
1594    sharedChannel = shChan;
1595    primaryChannel = priChan;
1596  }
1597
1598  public Runnable JavaDoc testLoop(final boolean isProducer) {
1599    return new Runnable JavaDoc() {
1600      public void run() {
1601        int delta = -1;
1602        Thread.currentThread().setPriority(Thread.NORM_PRIORITY+delta);
1603        int itersPerBarrier = RNG.itersPerBarrier.get();
1604        try {
1605          
1606          int nshared = (int)(iters * pshared.asDouble());
1607          int nprimary = iters - nshared;
1608          int idx = firstidx;
1609          
1610          barrier.barrier();
1611          
1612          ChanRNG target = (ChanRNG)(primary);
1613          
1614          for (int i = iters; i > 0; --i) {
1615            ++idx;
1616            if (i % itersPerBarrier == 0)
1617              primary.exchange();
1618            else {
1619              Channel c;
1620            
1621              if (nshared > 0 && useShared[idx % useShared.length]) {
1622                --nshared;
1623                c = sharedChannel;
1624              }
1625              else {
1626                --nprimary;
1627                c = primaryChannel;
1628              }
1629              
1630              long rnd;
1631              if (isProducer)
1632                rnd = target.producerNext(c);
1633              else
1634                rnd = target.consumerNext(c);
1635              
1636              if (rnd % 2 == 0 && Thread.currentThread().isInterrupted())
1637                break;
1638            }
1639          }
1640        }
1641        catch (BrokenBarrierException ex) {
1642        }
1643        catch (InterruptedException JavaDoc ex) {
1644          Thread.currentThread().interrupt();
1645        }
1646        finally {
1647          try {
1648            barrier.barrier();
1649          }
1650          catch (InterruptedException JavaDoc ex) {
1651            Thread.currentThread().interrupt();
1652          }
1653          catch (BrokenBarrierException ex) {
1654          }
1655          finally {
1656            Thread.currentThread().setPriority(Thread.NORM_PRIORITY);
1657          }
1658        }
1659      }
1660    };
1661  }
1662}
1663
1664// -------------------------------------------------------------
1665

1666
1667abstract class RNG implements Serializable, Comparable JavaDoc {
1668  static final int firstSeed = 4321;
1669  static final int rmod = 2147483647;
1670  static final int rmul = 16807;
1671
1672  static int lastSeed = firstSeed;
1673  static final int smod = 32749;
1674  static final int smul = 3125;
1675
1676  static final Object JavaDoc constructionLock = RNG.class;
1677
1678  // Use construction lock for all params to disable
1679
// changes in midst of construction of test objects.
1680

1681  static final SynchronizedInt computeLoops =
1682    new SynchronizedInt(16, constructionLock);
1683  static final SynchronizedInt syncMode =
1684    new SynchronizedInt(0, constructionLock);
1685  static final SynchronizedInt producerMode =
1686    new SynchronizedInt(0, constructionLock);
1687  static final SynchronizedInt consumerMode =
1688    new SynchronizedInt(0, constructionLock);
1689  static final SynchronizedInt bias =
1690    new SynchronizedInt(0, constructionLock);
1691  static final SynchronizedLong timeout =
1692    new SynchronizedLong(100, constructionLock);
1693  static final SynchronizedInt exchangeParties =
1694    new SynchronizedInt(1, constructionLock);
1695  static final SynchronizedInt sequenceNumber =
1696    new SynchronizedInt(0, constructionLock);
1697  static final SynchronizedInt itersPerBarrier =
1698    new SynchronizedInt(0, constructionLock);
1699
1700  static Rendezvous[] exchangers_;
1701
1702  static void reset(int nthreads) {
1703    synchronized(constructionLock) {
1704      sequenceNumber.set(-1);
1705      int parties = exchangeParties.get();
1706      if (nthreads < parties) parties = nthreads;
1707      if (nthreads % parties != 0)
1708        throw new Error JavaDoc("need even multiple of parties");
1709      exchangers_ = new Rendezvous[nthreads / parties];
1710      for (int i = 0; i < exchangers_.length; ++i) {
1711        exchangers_[i] = new Rendezvous(parties);
1712      }
1713    }
1714  }
1715
1716  static long nextSeed() {
1717    synchronized(constructionLock) {
1718      long s = lastSeed;
1719      lastSeed = (lastSeed * smul) % smod;
1720      if (lastSeed == 0)
1721        lastSeed = (int)(System.currentTimeMillis());
1722      return s;
1723    }
1724  }
1725
1726  final int cloops = computeLoops.get();
1727  final int pcBias = bias.get();
1728  final int smode = syncMode.get();
1729  final int pmode = producerMode.get();
1730  final int cmode = consumerMode.get();
1731  final long waitTime = timeout.get();
1732  Rendezvous exchanger_ = null;
1733
1734  synchronized Rendezvous getExchanger() {
1735    if (exchanger_ == null) {
1736      synchronized (constructionLock) {
1737        int idx = sequenceNumber.increment();
1738        exchanger_ = exchangers_[idx % exchangers_.length];
1739      }
1740    }
1741    return exchanger_;
1742  }
1743
1744  public void exchange() throws InterruptedException JavaDoc {
1745    Rendezvous ex = getExchanger();
1746    Runnable JavaDoc r = (Runnable JavaDoc)(ex.rendezvous(new UpdateCommand(this)));
1747    if (r != null) r.run();
1748  }
1749
1750  public int compareTo(Object JavaDoc other) {
1751    int h1 = hashCode();
1752    int h2 = other.hashCode();
1753    if (h1 < h2) return -1;
1754    else if (h1 > h2) return 1;
1755    else return 0;
1756  }
1757
1758  protected final long compute(long l) {
1759    int loops = (int)((l & 0x7FFFFFFF) % (cloops * 2)) + 1;
1760    for (int i = 0; i < loops; ++i) l = (l * rmul) % rmod;
1761    return (l == 0)? firstSeed : l;
1762  }
1763
1764  abstract protected void set(long l);
1765  abstract protected long internalGet();
1766  abstract protected void internalUpdate();
1767
1768  public long get() { return internalGet(); }
1769  public void update() { internalUpdate(); }
1770  public long next() { internalUpdate(); return internalGet(); }
1771}
1772
1773
1774class UpdateCommand implements Runnable JavaDoc, Serializable, Comparable JavaDoc {
1775  private final RNG obj_;
1776  final long cmpVal;
1777  public UpdateCommand(RNG o) {
1778    obj_ = o;
1779    cmpVal = o.get();
1780  }
1781
1782  public void run() { obj_.update(); }
1783
1784  public int compareTo(Object JavaDoc x) {
1785    UpdateCommand u = (UpdateCommand)x;
1786    if (cmpVal < u.cmpVal) return -1;
1787    else if (cmpVal > u.cmpVal) return 1;
1788    else return 0;
1789  }
1790}
1791
1792
1793class GetFunction implements Callable {
1794  private final RNG obj_;
1795  public GetFunction(RNG o) { obj_ = o; }
1796  public Object JavaDoc call() { return new Long JavaDoc(obj_.get()); }
1797}
1798
1799class NextFunction implements Callable {
1800  private final RNG obj_;
1801  public NextFunction(RNG o) { obj_ = o; }
1802  public Object JavaDoc call() { return new Long JavaDoc(obj_.next()); }
1803}
1804
1805
1806class NoSynchRNG extends RNG {
1807  protected long current_ = nextSeed();
1808
1809  protected void set(long l) { current_ = l; }
1810  protected long internalGet() { return current_; }
1811  protected void internalUpdate() { set(compute(internalGet())); }
1812}
1813
1814class PublicSynchRNG extends NoSynchRNG {
1815  public synchronized long get() { return internalGet(); }
1816  public synchronized void update() { internalUpdate(); }
1817  public synchronized long next() { internalUpdate(); return internalGet(); }
1818}
1819
1820class AllSynchRNG extends PublicSynchRNG {
1821  protected synchronized void set(long l) { current_ = l; }
1822  protected synchronized long internalGet() { return current_; }
1823  protected synchronized void internalUpdate() { set(compute(internalGet())); }
1824}
1825
1826
1827class AClongRNG extends RNG {
1828  protected final SynchronizedLong acurrent_ =
1829    new SynchronizedLong(nextSeed());
1830
1831  protected void set(long l) { throw new Error JavaDoc("No set allowed"); }
1832  protected long internalGet() { return acurrent_.get(); }
1833
1834  protected void internalUpdate() {
1835    int retriesBeforeSleep = 100;
1836    int maxSleepTime = 100;
1837    int retries = 0;
1838    for (;;) {
1839      long v = internalGet();
1840      long n = compute(v);
1841      if (acurrent_.commit(v, n))
1842        return;
1843      else if (++retries >= retriesBeforeSleep) {
1844        try {
1845          Thread.sleep(n % maxSleepTime);
1846        }
1847        catch (InterruptedException JavaDoc ex) {
1848          Thread.currentThread().interrupt();
1849        }
1850        retries = 0;
1851      }
1852    }
1853  }
1854  
1855}
1856
1857class SynchLongRNG extends RNG {
1858  protected final SynchronizedLong acurrent_ =
1859    new SynchronizedLong(nextSeed());
1860
1861  protected void set(long l) { acurrent_.set(l); }
1862  protected long internalGet() { return acurrent_.get(); }
1863  protected void internalUpdate() { set(compute(internalGet())); }
1864  
1865}
1866
1867abstract class DelegatedRNG extends RNG {
1868  protected RNG delegate_ = null;
1869  public synchronized void setDelegate(RNG d) { delegate_ = d; }
1870  protected synchronized RNG getDelegate() { return delegate_; }
1871
1872  public long get() { return getDelegate().get(); }
1873  public void update() { getDelegate().update(); }
1874  public long next() { return getDelegate().next(); }
1875
1876  protected void set(long l) { throw new Error JavaDoc(); }
1877  protected long internalGet() { throw new Error JavaDoc(); }
1878  protected void internalUpdate() { throw new Error JavaDoc(); }
1879
1880}
1881
1882class SDelegatedRNG extends DelegatedRNG {
1883  public SDelegatedRNG() { setDelegate(new NoSynchRNG()); }
1884  public synchronized long get() { return getDelegate().get(); }
1885  public synchronized void update() { getDelegate().update(); }
1886  public synchronized long next() { return getDelegate().next(); }
1887}
1888
1889
1890class SyncDelegatedRNG extends DelegatedRNG {
1891  protected final Sync cond_;
1892  public SyncDelegatedRNG(Sync c) {
1893    cond_ = c;
1894    setDelegate(new NoSynchRNG());
1895  }
1896
1897
1898  protected final void acquire() throws InterruptedException JavaDoc {
1899    if (smode == 0) {
1900      cond_.acquire();
1901    }
1902    else {
1903      while (!cond_.attempt(waitTime)) {}
1904    }
1905  }
1906      
1907  public long next() {
1908    try {
1909      acquire();
1910
1911      getDelegate().update();
1912      long l = getDelegate().get();
1913      cond_.release();
1914      return l;
1915    }
1916    catch(InterruptedException JavaDoc x) {
1917      Thread.currentThread().interrupt();
1918      return 0;
1919    }
1920  }
1921
1922  public long get() {
1923    try {
1924      acquire();
1925      long l = getDelegate().get();
1926      cond_.release();
1927      return l;
1928    }
1929    catch(InterruptedException JavaDoc x) {
1930      Thread.currentThread().interrupt();
1931      return 0;
1932    }
1933  }
1934
1935  public void update() {
1936    try {
1937      acquire();
1938      getDelegate().update();
1939      cond_.release();
1940    }
1941    catch(InterruptedException JavaDoc x) {
1942      Thread.currentThread().interrupt();
1943    }
1944  }
1945
1946
1947}
1948
1949class MutexRNG extends SyncDelegatedRNG {
1950  public MutexRNG() { super(new Mutex()); }
1951}
1952
1953
1954class SemRNG extends SyncDelegatedRNG {
1955  public SemRNG() { super(new Semaphore(1)); }
1956}
1957
1958class WpSemRNG extends SyncDelegatedRNG {
1959  public WpSemRNG() { super(new WaiterPreferenceSemaphore(1)); }
1960}
1961
1962class FifoRNG extends SyncDelegatedRNG {
1963  public FifoRNG() { super(new FIFOSemaphore(1)); }
1964}
1965
1966class PrioritySemRNG extends SyncDelegatedRNG {
1967  public PrioritySemRNG() { super(new PrioritySemaphore(1)); }
1968}
1969
1970class RlockRNG extends SyncDelegatedRNG {
1971  public RlockRNG() { super(new ReentrantLock()); }
1972}
1973
1974
1975class RWLockRNG extends NoSynchRNG {
1976  protected final ReadWriteLock lock_;
1977  public RWLockRNG(ReadWriteLock l) {
1978    lock_ = l;
1979  }
1980      
1981  protected final void acquireR() throws InterruptedException JavaDoc {
1982    if (smode == 0) {
1983      lock_.readLock().acquire();
1984    }
1985    else {
1986      while (!lock_.readLock().attempt(waitTime)) {}
1987    }
1988  }
1989
1990  protected final void acquireW() throws InterruptedException JavaDoc {
1991    if (smode == 0) {
1992      lock_.writeLock().acquire();
1993    }
1994    else {
1995      while (!lock_.writeLock().attempt(waitTime)) {}
1996    }
1997  }
1998
1999
2000  public long next() {
2001    long l = 0;
2002    try {
2003      acquireR();
2004      l = current_;
2005      lock_.readLock().release();
2006    }
2007    catch(InterruptedException JavaDoc x) {
2008      Thread.currentThread().interrupt();
2009      return 0;
2010    }
2011
2012    l = compute(l);
2013
2014    try {
2015      acquireW();
2016      set(l);
2017      lock_.writeLock().release();
2018      return l;
2019    }
2020    catch(InterruptedException JavaDoc x) {
2021      Thread.currentThread().interrupt();
2022      return 0;
2023    }
2024  }
2025
2026
2027  public long get() {
2028    try {
2029      acquireR();
2030      long l = current_;
2031      lock_.readLock().release();
2032      return l;
2033    }
2034    catch(InterruptedException JavaDoc x) {
2035      Thread.currentThread().interrupt();
2036      return 0;
2037    }
2038  }
2039
2040  public void update() {
2041    long l = 0;
2042
2043    try {
2044      acquireR();
2045      l = current_;
2046      lock_.readLock().release();
2047    }
2048    catch(InterruptedException JavaDoc x) {
2049      Thread.currentThread().interrupt();
2050      return;
2051    }
2052
2053    l = compute(l);
2054
2055    try {
2056      acquireW();
2057      set(l);
2058      lock_.writeLock().release();
2059    }
2060    catch(InterruptedException JavaDoc x) {
2061      Thread.currentThread().interrupt();
2062    }
2063  }
2064
2065}
2066
2067class WpRWlockRNG extends RWLockRNG {
2068  public WpRWlockRNG() { super(new WriterPreferenceReadWriteLock()); }
2069}
2070
2071class ReaderPrefRWlockRNG extends RWLockRNG {
2072  public ReaderPrefRWlockRNG() {
2073    super(new ReaderPreferenceReadWriteLock());
2074  }
2075
2076
2077}
2078
2079class FIFORWlockRNG extends RWLockRNG {
2080  public FIFORWlockRNG() { super(new FIFOReadWriteLock()); }
2081}
2082
2083
2084class ReentrantRWlockRNG extends RWLockRNG {
2085  public ReentrantRWlockRNG() {
2086    super(new ReentrantWriterPreferenceReadWriteLock());
2087  }
2088
2089  public void update() { // use embedded acquires
2090
long l = 0;
2091
2092    try {
2093      acquireW();
2094
2095      try {
2096        acquireR();
2097        l = current_;
2098        lock_.readLock().release();
2099      }
2100      catch(InterruptedException JavaDoc x) {
2101        Thread.currentThread().interrupt();
2102        return;
2103      }
2104
2105      l = compute(l);
2106
2107      set(l);
2108      lock_.writeLock().release();
2109    }
2110    catch(InterruptedException JavaDoc x) {
2111      Thread.currentThread().interrupt();
2112    }
2113  }
2114
2115}
2116
2117
2118abstract class ExecutorRNG extends DelegatedRNG {
2119  Executor executor_;
2120
2121
2122  synchronized void setExecutor(Executor e) { executor_ = e; }
2123  synchronized Executor getExecutor() { return executor_; }
2124
2125  Runnable JavaDoc delegatedUpdate_ = null;
2126  Callable delegatedNext_ = null;
2127
2128  synchronized Runnable JavaDoc delegatedUpdateCommand() {
2129    if (delegatedUpdate_ == null)
2130      delegatedUpdate_ = new UpdateCommand(getDelegate());
2131    return delegatedUpdate_;
2132  }
2133
2134  synchronized Callable delegatedNextFunction() {
2135    if (delegatedNext_ == null)
2136      delegatedNext_ = new NextFunction(getDelegate());
2137    return delegatedNext_;
2138  }
2139
2140  public void update() {
2141    try {
2142      getExecutor().execute(delegatedUpdateCommand());
2143    }
2144    catch (InterruptedException JavaDoc ex) {
2145      Thread.currentThread().interrupt();
2146    }
2147  }
2148
2149  // Each call to next gets result of previous future
2150
FutureResult nextResult_ = null;
2151
2152  public synchronized long next() {
2153    long res = 0;
2154    try {
2155      if (nextResult_ == null) { // direct call first time through
2156
nextResult_ = new FutureResult();
2157        nextResult_.set(new Long JavaDoc(getDelegate().next()));
2158      }
2159      FutureResult currentResult = nextResult_;
2160
2161      nextResult_ = new FutureResult();
2162      Runnable JavaDoc r = nextResult_.setter(delegatedNextFunction());
2163      getExecutor().execute(r);
2164
2165      res = ((Long JavaDoc)(currentResult.get())).longValue();
2166
2167    }
2168    catch (InterruptedException JavaDoc ex) {
2169      Thread.currentThread().interrupt();
2170    }
2171    catch (InvocationTargetException ex) {
2172      ex.printStackTrace();
2173      throw new Error JavaDoc("Bad Callable?");
2174    }
2175    return res;
2176  }
2177}
2178
2179class DirectExecutorRNG extends ExecutorRNG {
2180  public DirectExecutorRNG() {
2181    setDelegate(new PublicSynchRNG());
2182    setExecutor(new DirectExecutor());
2183  }
2184}
2185
2186class LockedSemRNG extends ExecutorRNG {
2187  public LockedSemRNG() {
2188    setDelegate(new NoSynchRNG());
2189    setExecutor(new LockedExecutor(new Semaphore(1)));
2190  }
2191}
2192
2193class QueuedExecutorRNG extends ExecutorRNG {
2194  static final QueuedExecutor exec = new QueuedExecutor();
2195  static { exec.setThreadFactory(Threads.factory); }
2196  public QueuedExecutorRNG() {
2197    setDelegate(new PublicSynchRNG());
2198    setExecutor(exec);
2199  }
2200}
2201
2202class ForcedStartRunnable implements Runnable JavaDoc {
2203  protected final Latch latch_ = new Latch();
2204  protected final Runnable JavaDoc command_;
2205
2206  ForcedStartRunnable(Runnable JavaDoc command) { command_ = command; }
2207
2208  public Latch started() { return latch_; }
2209
2210  public void run() {
2211    latch_.release();
2212    command_.run();
2213  }
2214}
2215
2216
2217class ForcedStartThreadedExecutor extends ThreadedExecutor {
2218  public void execute(Runnable JavaDoc command) throws InterruptedException JavaDoc {
2219    ForcedStartRunnable wrapped = new ForcedStartRunnable(command);
2220    super.execute(wrapped);
2221    wrapped.started().acquire();
2222  }
2223}
2224
2225class ThreadedExecutorRNG extends ExecutorRNG {
2226  static final ThreadedExecutor exec = new ThreadedExecutor();
2227  static { exec.setThreadFactory(Threads.factory); }
2228
2229  public ThreadedExecutorRNG() {
2230    setDelegate(new PublicSynchRNG());
2231    setExecutor(exec);
2232  }
2233}
2234
2235
2236class PooledExecutorRNG extends ExecutorRNG {
2237  static final PooledExecutor exec = Threads.pool;
2238
2239  public PooledExecutorRNG() {
2240    setDelegate(new PublicSynchRNG());
2241    setExecutor(exec);
2242  }
2243}
2244
2245
2246class ChanRNG extends DelegatedRNG {
2247
2248  boolean single_;
2249
2250  ChanRNG() {
2251    setDelegate(new PublicSynchRNG());
2252  }
2253
2254  public synchronized void setSingle(boolean s) { single_ = s; }
2255  public synchronized boolean isSingle() { return single_; }
2256
2257  public long producerNext(Channel c) throws InterruptedException JavaDoc {
2258    RNG r = getDelegate();
2259    if (isSingle()) {
2260      c.put(r);
2261      r = (RNG)(c.take());
2262      r.update();
2263    }
2264    else {
2265      if (pcBias < 0) {
2266        r.update();
2267        r.update(); // update consumer side too
2268
}
2269      else if (pcBias == 0) {
2270        r.update();
2271      }
2272      
2273      if (pmode == 0) {
2274        c.put(r);
2275      }
2276      else {
2277        while (!(c.offer(r, waitTime))) {}
2278      }
2279    }
2280    return r.get();
2281  }
2282
2283  public long consumerNext(Channel c) throws InterruptedException JavaDoc {
2284    RNG r = null;
2285    if (cmode == 0) {
2286      r = (RNG)(c.take());
2287    }
2288    else {
2289      while (r == null) r = (RNG)(c.poll(waitTime));
2290    }
2291    
2292    if (pcBias == 0) {
2293      r.update();
2294    }
2295    else if (pcBias > 0) {
2296      r.update();
2297      r.update();
2298    }
2299    return r.get();
2300  }
2301}
2302
2303
Popular Tags