1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17 package org.apache.commons.transaction.util;
18
19 /**
20 * Simple barrier that blocks until all parties have either called or have arrived at the meeting point.
21 * Very useful for testing or other purposes that require to make concurrent settings deterministic.
22 *
23 * @version $Id: RendezvousBarrier.java 493628 2007-01-07 01:42:48Z joerg $
24 */
25 public class RendezvousBarrier {
26
27 public static final int DEFAULT_TIMEOUT = 20000;
28
29 protected final int parties;
30 protected final String name;
31 protected int count = 0;
32 protected long timeout;
33 protected LoggerFacade logger;
34
35 public RendezvousBarrier(String name, LoggerFacade logger) {
36 this(name, DEFAULT_TIMEOUT, logger);
37 }
38
39 public RendezvousBarrier(String name, long timeout, LoggerFacade logger) {
40 this(name, 2, timeout, logger);
41 }
42
43 public RendezvousBarrier(String name, int parties, long timeout, LoggerFacade logger) {
44 this.parties = parties;
45 this.name = name;
46 this.timeout = timeout;
47 this.logger = logger;
48 }
49
50 /**
51 * Notify the barrier that you (the current thread) will not come to the meeting point.
52 * Same thing as {@link #meet()}, but does not not let you wait.
53 */
54 public synchronized void call() {
55 count++;
56 if (count >= parties) {
57 if (logger.isFineEnabled())
58 logger.logFine("Thread " + Thread.currentThread().getName() + " by CALL COMPLETING barrier " + name);
59 notifyAll();
60 }
61 }
62
63 /**
64 * Meet at this barrier. The current thread will either block when there are missing parties for this barrier
65 * or it is the last one to complete this meeting and the barrier will release its block.
66 * In this case all other waiting threads will be notified.
67 *
68 * @throws InterruptedException if the current thread is interrupted while waiting
69 */
70 public synchronized void meet() throws InterruptedException {
71 count++;
72 if (count >= parties) {
73 if (logger.isFineEnabled())
74 logger.logFine("Thread " + Thread.currentThread().getName() + " by MEET COMPLETING barrier " + name);
75 notifyAll();
76 } else {
77 if (logger.isFineEnabled()) {
78 logger.logFine(
79 "At barrier "
80 + name
81 + " thread "
82 + Thread.currentThread().getName()
83 + " WAITING for "
84 + (parties - count)
85 + " of "
86 + parties
87 + " parties");
88 }
89 wait(timeout);
90 if (count == 0) {
91 // means the barrier has been reset
92 } else if (count >= parties) {
93 if (logger.isFineEnabled())
94 logger.logFine("Thread " + Thread.currentThread().getName() + " CONTINUING at barrier " + name);
95 } else {
96 if (logger.isFineEnabled())
97 logger.logFine("Thread " + Thread.currentThread().getName() + " FAILING at barrier " + name);
98 notifyAll();
99 }
100 }
101 }
102
103 /**
104 * Releases all waiting threads and resets the number of parties already arrived.
105 */
106 public synchronized void reset() {
107 if (logger.isFineEnabled()) logger.logFine("Resetting barrier " + name);
108 count = 0;
109 notifyAll();
110 }
111
112 }