blob: 5f39eab4b2c569640ab4dfa590a0a59b8d78289e [file] [log] [blame]
Felix Meschbergerefb2d082008-08-19 13:18:47 +00001/*
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*/
17package org.apache.felix.shell.remote;
18
19
20/**
21 * A latch is a boolean condition that is set at most once, ever.
22 * Once a single release is issued, all acquires will pass.
23 * <p/>
24 * <b>Sample usage.</b> Here are a set of classes that use
25 * a latch as a start signal for a group of worker threads that
26 * are created and started beforehand, and then later enabled.
27 * <pre>
28 * class Worker implements Runnable {
29 * private final Latch startSignal;
30 * Worker(Latch l) { startSignal = l; }
31 * public void run() {
32 * startSignal.acquire();
33 * doWork();
34 * }
35 * void doWork() { ... }
36 * }
37 * <p/>
38 * class Driver { // ...
39 * void main() {
40 * Latch go = new Latch();
41 * for (int i = 0; i < N; ++i) // make threads
42 * new Thread(new Worker(go)).start();
43 * doSomethingElse(); // don't let run yet
44 * go.release(); // let all threads proceed
45 * }
46 * }
47 * </pre>
Felix Meschbergerefb2d082008-08-19 13:18:47 +000048 */
49class Latch
50{
51
52 protected boolean latched_ = false;
53
54
55 /*
56 This could use double-check, but doesn't.
57 If the latch is being used as an indicator of
58 the presence or state of an object, the user would
59 not necessarily get the memory barrier that comes with synch
60 that would be needed to correctly use that object. This
61 would lead to errors that users would be very hard to track down. So, to
62 be conservative, we always use synch.
63 */
64
65 public void acquire() throws InterruptedException
66 {
67 if ( Thread.interrupted() )
68 throw new InterruptedException();
69 synchronized ( this )
70 {
71 while ( !latched_ )
72 wait();
73 }
74 }//acquire
75
76
77 public boolean attempt( long msecs ) throws InterruptedException
78 {
79 if ( Thread.interrupted() )
80 throw new InterruptedException();
81 synchronized ( this )
82 {
83 if ( latched_ )
84 return true;
85 else if ( msecs <= 0 )
86 return false;
87 else
88 {
89 long waitTime = msecs;
90 long start = System.currentTimeMillis();
91 for ( ;; )
92 {
93 wait( waitTime );
94 if ( latched_ )
95 return true;
96 else
97 {
98 waitTime = msecs - ( System.currentTimeMillis() - start );
99 if ( waitTime <= 0 )
100 return false;
101 }
102 }
103 }
104 }
105 }//attempt
106
107
108 /**
109 * Enable all current and future acquires to pass *
110 */
111 public synchronized void release()
112 {
113 latched_ = true;
114 notifyAll();
115 }//release
116
117}//class Latch
118