001: /*
002: * All content copyright (c) 2003-2006 Terracotta, Inc., except as may otherwise be noted in a separate copyright
003: * notice. All rights reserved.
004: */
005: package com.tctest;
006:
007: import com.tc.object.config.ConfigVisitor;
008: import com.tc.object.config.DSOClientConfigHelper;
009: import com.tc.object.config.TransparencyClassSpec;
010: import com.tc.simulator.app.ApplicationConfig;
011: import com.tc.simulator.listener.ListenerProvider;
012: import com.tc.util.Assert;
013: import com.tctest.runner.AbstractTransparentApp;
014:
015: import java.util.concurrent.BrokenBarrierException;
016: import java.util.concurrent.CyclicBarrier;
017: import java.util.concurrent.TimeUnit;
018: import java.util.concurrent.TimeoutException;
019:
020: public class CyclicBarrierTestApp extends AbstractTransparentApp {
021: private static final int FINISHED_BARRIER_ACTION_FLAG = 100;
022:
023: private final DataRoot dataRoot = new DataRoot();
024: private final CyclicBarrier barrier;
025: private final CyclicBarrier testBarrier;
026:
027: public CyclicBarrierTestApp(String appId, ApplicationConfig cfg,
028: ListenerProvider listenerProvider) {
029: super (appId, cfg, listenerProvider);
030: barrier = new CyclicBarrier(getParticipantCount());
031: testBarrier = new CyclicBarrier(getParticipantCount(),
032: new BarrierAction(dataRoot));
033: }
034:
035: public void run() {
036: try {
037: basicBarrierActionTest();
038: basicBarrierAPITest();
039: interruptedBarrierTest();
040: } catch (Throwable t) {
041: notifyError(t);
042: }
043: }
044:
045: private void clear() throws Exception {
046: synchronized (dataRoot) {
047: dataRoot.clear();
048: }
049:
050: barrier.await();
051: }
052:
053: private void basicBarrierActionTest() throws Exception {
054: testBarrier.await();
055:
056: Assert.assertEquals(FINISHED_BARRIER_ACTION_FLAG, dataRoot
057: .getData());
058:
059: barrier.await();
060: }
061:
062: private void basicBarrierAPITest() throws Exception {
063: Assert.assertEquals(getParticipantCount(), testBarrier
064: .getParties());
065:
066: clear();
067:
068: int index = -1;
069: synchronized (dataRoot) {
070: index = dataRoot.getIndex();
071: dataRoot.setIndex(index + 1);
072: }
073:
074: barrier.await();
075:
076: if (index == 0) {
077: try {
078: Assert.assertEquals(0, testBarrier.getNumberWaiting());
079: testBarrier.await(10, TimeUnit.MILLISECONDS);
080: } catch (TimeoutException e) {
081: Assert.assertTrue(testBarrier.isBroken());
082: }
083: }
084:
085: barrier.await();
086:
087: if (index != 0) {
088: Assert.assertTrue(testBarrier.isBroken());
089: }
090:
091: barrier.await();
092:
093: if (index == 0) {
094: testBarrier.reset();
095: }
096:
097: barrier.await();
098:
099: Assert.assertFalse(testBarrier.isBroken());
100:
101: testBarrier.await();
102: }
103:
104: private void interruptedBarrierTest() throws Exception {
105: clear();
106:
107: int index = -1;
108: synchronized (dataRoot) {
109: index = dataRoot.getIndex();
110: dataRoot.setIndex(index + 1);
111: }
112:
113: barrier.await();
114:
115: Thread thread = null;
116:
117: if (index == 0) {
118: thread = new Thread(new BarrierRunnable(testBarrier));
119: thread.start();
120: }
121:
122: if (index == 1) {
123: while (testBarrier.getNumberWaiting() == 0) {
124: // do nothing
125: }
126: }
127:
128: barrier.await();
129:
130: if (index == 0) {
131: thread.interrupt();
132: }
133:
134: barrier.await();
135:
136: if (index == 0) {
137: thread.join();
138: }
139:
140: barrier.await();
141: }
142:
143: public static void visitL1DSOConfig(ConfigVisitor visitor,
144: DSOClientConfigHelper config) {
145: String testClass = CyclicBarrierTestApp.class.getName();
146: TransparencyClassSpec spec = config.getOrCreateSpec(testClass);
147:
148: config.addIncludePattern(testClass + "$*", false, false, true);
149:
150: String methodExpression = "* " + testClass + "*.*(..)";
151: config.addWriteAutolock(methodExpression);
152:
153: spec.addRoot("barrier", "barrier");
154: spec.addRoot("testBarrier", "testBarrier");
155: spec.addRoot("dataRoot", "dataRoot");
156: }
157:
158: private static class BarrierAction implements Runnable {
159: private final DataRoot dataRoot;
160:
161: public BarrierAction(DataRoot dataRoot) {
162: this .dataRoot = dataRoot;
163: }
164:
165: public void run() {
166: dataRoot.setData(FINISHED_BARRIER_ACTION_FLAG);
167: }
168: }
169:
170: private class BarrierRunnable implements Runnable {
171: private CyclicBarrier b;
172:
173: public BarrierRunnable(CyclicBarrier b) {
174: this .b = b;
175: }
176:
177: public void run() {
178: try {
179: run0();
180: } catch (Throwable t) {
181: notifyError(t);
182: }
183: }
184:
185: private void run0() {
186: try {
187: b.await();
188: } catch (InterruptedException e) {
189: Assert.assertTrue(b.isBroken());
190: } catch (BrokenBarrierException e) {
191: Assert.assertTrue(b.isBroken());
192: }
193: }
194: }
195:
196: private static class DataRoot {
197: private int index;
198: private volatile int data;
199:
200: public DataRoot() {
201: this .index = 0;
202: }
203:
204: public int getIndex() {
205: return index;
206: }
207:
208: public void setIndex(int index) {
209: this .index = index;
210: }
211:
212: public int getData() {
213: return data;
214: }
215:
216: public void setData(int data) {
217: this .data = data;
218: }
219:
220: public void clear() {
221: this .index = 0;
222: this .data = 0;
223: }
224: }
225: }
|