Classes in this File | Line Coverage | Branch Coverage | Complexity | ||||
TurnBarrier |
|
| 1.8333333333333333;1.833 |
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 turn based barrier to make a sequence of calls from different threads deterministic. | |
21 | * This is very useful for testing where you want to have a continuous flow throughout | |
22 | * different threads. The idea is to have an ordered sequence of steps where step n can not be | |
23 | * executed before n-1. | |
24 | * | |
25 | * @version $Id: TurnBarrier.java 493628 2007-01-07 01:42:48Z joerg $ | |
26 | */ | |
27 | public class TurnBarrier { | |
28 | ||
29 | public static final long DEFAULT_TIMEOUT = Long.MAX_VALUE; | |
30 | ||
31 | protected final String name; | |
32 | ||
33 | protected int currentNumber; | |
34 | ||
35 | protected final int startNumber; | |
36 | ||
37 | protected final long timeout; | |
38 | ||
39 | protected LoggerFacade logger; | |
40 | ||
41 | /** | |
42 | * Creates a new turn barrier starting with turn 0 with an unlimited timeout. | |
43 | * | |
44 | * @param name the name of the barrier | |
45 | * @param logger logger for debug output | |
46 | */ | |
47 | public TurnBarrier(String name, LoggerFacade logger) { | |
48 | 0 | this(name, DEFAULT_TIMEOUT, logger); |
49 | 0 | } |
50 | ||
51 | /** | |
52 | * Creates a new turn barrier starting with turn 0. | |
53 | * | |
54 | * @param name the name of the barrier | |
55 | * @param timeout timeout for threads to wait for their turn | |
56 | * @param logger logger for debug output | |
57 | */ | |
58 | public TurnBarrier(String name, long timeout, LoggerFacade logger) { | |
59 | 0 | this(name, timeout, logger, 0); |
60 | 0 | } |
61 | ||
62 | /** | |
63 | * Creates a new turn barrier. | |
64 | * | |
65 | * @param name the name of the barrier | |
66 | * @param timeout timeout for threads to wait for their turn | |
67 | * @param logger logger for debug output | |
68 | * @param startTurn the turn to start with | |
69 | */ | |
70 | 4 | public TurnBarrier(String name, long timeout, LoggerFacade logger, int startTurn) { |
71 | 4 | this.name = name; |
72 | 4 | this.timeout = timeout; |
73 | 4 | this.logger = logger; |
74 | 4 | this.startNumber = startTurn; |
75 | 4 | this.currentNumber = startTurn; |
76 | 4 | } |
77 | ||
78 | /** | |
79 | * Blockingly waits for the given turn. If a timeout occurs a runtime exception will be thrown. | |
80 | * | |
81 | * @param turnNumber the turn number to wait for | |
82 | * @throws InterruptedException thrown if the thread is interrupted while waiting | |
83 | * @throws RuntimeException thrown when timed out | |
84 | */ | |
85 | public synchronized void waitForTurn(int turnNumber) throws InterruptedException, | |
86 | RuntimeException { | |
87 | 450 | if (turnNumber > currentNumber) { |
88 | 264 | long started = System.currentTimeMillis(); |
89 | 667 | for (long remaining = timeout; remaining > 0 && turnNumber > currentNumber; remaining = timeout |
90 | - (System.currentTimeMillis() - started)) { | |
91 | 403 | wait(remaining); |
92 | } | |
93 | } | |
94 | 450 | if (turnNumber > currentNumber) { |
95 | 0 | throw new RuntimeException("Timed out while waiting for our turn"); |
96 | } | |
97 | 450 | } |
98 | ||
99 | /** | |
100 | * Signals the next turn. Any thread waiting for the turn will be allowed to continue. | |
101 | * | |
102 | * @param turnNumber the next turn number | |
103 | */ | |
104 | public synchronized void signalTurn(int turnNumber) { | |
105 | 450 | currentNumber = turnNumber; |
106 | 450 | notifyAll(); |
107 | 450 | } |
108 | ||
109 | /** | |
110 | * Starts the barrier over again. The next turn will be the one the barrier was started with. | |
111 | * | |
112 | */ | |
113 | public synchronized void reset() { | |
114 | 100 | signalTurn(startNumber); |
115 | 100 | } |
116 | } |