001: /*
002: * All content copyright (c) 2003-2006 Terracotta, Inc., except as may otherwise be noted in a separate copyright notice. All rights reserved.
003: */
004: package com.tctest;
005:
006: import com.tc.object.config.ConfigVisitor;
007: import com.tc.object.config.DSOClientConfigHelper;
008: import com.tc.object.config.TransparencyClassSpec;
009: import com.tc.simulator.app.ApplicationConfig;
010: import com.tc.simulator.listener.ListenerProvider;
011: import com.tc.util.Assert;
012: import com.tctest.runner.AbstractTransparentApp;
013:
014: import java.util.LinkedList;
015: import java.util.concurrent.CyclicBarrier;
016:
017: public class ConcurrentLinkedListTestApp extends AbstractTransparentApp {
018:
019: private final CyclicBarrier barrier;
020: private final LinkedList<Integer> sharedList = new LinkedList<Integer>();
021: private final LinkedList<Integer> resultList = new LinkedList<Integer>();
022:
023: public ConcurrentLinkedListTestApp(String appId,
024: ApplicationConfig cfg, ListenerProvider listenerProvider) {
025: super (appId, cfg, listenerProvider);
026: barrier = new CyclicBarrier(getParticipantCount());
027: }
028:
029: public void run() {
030: try {
031: int index = barrier.await();
032:
033: testProducerConsumer(index);
034:
035: } catch (Throwable t) {
036: notifyError(t);
037: }
038: }
039:
040: /**
041: * Test producer consumer on a shared list
042: */
043: private void testProducerConsumer(int index) throws Exception {
044: int upbound = 1000;
045:
046: // thread 0 as a produce
047: if (index == 0) {
048: int val = 0;
049: synchronized (sharedList) {
050: resultList.clear();
051: sharedList.clear();
052: }
053:
054: while (val <= upbound) {
055: synchronized (sharedList) {
056: sharedList.add(val);
057: // System.out.println("*** Produces item " + val);
058: ++val;
059: sharedList.notifyAll();
060: }
061: Thread.sleep(1 + (int) (Math.random() * 2));
062: }
063: }
064:
065: if (index != 0) {
066: int val = 0;
067: while (val < upbound) {
068: synchronized (sharedList) {
069: while (sharedList.isEmpty()) {
070: sharedList.wait();
071: }
072: val = sharedList.removeFirst();
073: resultList.add(val);
074: // System.out.println("*** Thread " + index + " consumes item " + val);
075: // put the last item back as an end indicator
076: if (val == upbound) {
077: sharedList.add(val);
078: sharedList.notifyAll();
079: }
080: }
081: Thread.sleep(5 + (int) (Math.random() * 5));
082: }
083: }
084:
085: barrier.await();
086:
087: // verify
088: for (int i = 0; i < upbound; ++i) {
089: // it is right to use the same lock
090: synchronized (sharedList) {
091: // System.out.println("*** Verify["+i+"] value="+resultList.get(i));
092: Assert.assertTrue(i == resultList.get(i));
093: }
094: }
095:
096: barrier.await();
097: }
098:
099: public static void visitL1DSOConfig(ConfigVisitor visitor,
100: DSOClientConfigHelper config) {
101: String testClass = ConcurrentLinkedListTestApp.class.getName();
102: TransparencyClassSpec spec = config.getOrCreateSpec(testClass);
103:
104: config.addIncludePattern(testClass + "$*", false, false, true);
105:
106: String methodExpression = "* " + testClass + "*.*(..)";
107: config.addWriteAutolock(methodExpression);
108:
109: spec.addRoot("barrier", "barrier");
110: spec.addRoot("sharedList", "sharedList");
111: spec.addRoot("resultList", "resultList");
112: }
113: }
|