File: Wicket.java

package info (click to toggle)
openjdk-11 11.0.16%2B8-1~deb10u1
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 784,576 kB
  • sloc: java: 5,128,021; xml: 1,192,224; cpp: 1,124,021; ansic: 422,433; javascript: 155,577; sh: 17,084; objc: 13,327; python: 4,522; asm: 3,570; makefile: 2,858; awk: 351; sed: 172; perl: 114; jsp: 24; csh: 3
file content (229 lines) | stat: -rw-r--r-- 7,477 bytes parent folder | download | duplicates (10)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
/*
 * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package nsk.share;

import java.io.PrintStream;

/**
 * Wicket provides a means for one or more threads to suspend execution
 * (to wait) until notified by one or more other threads that some set
 * of locks is now open.
 *
 * <p>Wicket instances are intended to be used generally in the following
 * scenarios:
 *
 *   <ul><li>One thread starts one or more child threads and waits until the
 *   child threads to be started.
 *
 *   <li>One thread starts one or more child threads and waits until at least
 *   one of the child threads to be started.
 *
 *   <li>One or more child threads wait until a main thread lets them
 *   to finish.
 *
 *   <li>Disable the current thread for thread scheduling purposes, for up to
 *   the specified waiting time.</ul>
 */

public class Wicket {

    /** Number of closed locks, can be greater or equal to zero */
    private int count;

    /** Number of waiters **/
    private int waiters = 0;

    /** Enable debug output */
    private PrintStream debugOutput = null;

    /** Wicket's string identifier */
    private String name = "";

    /**
     * Construct a Wicket with only one closed lock.
     */
    public Wicket() {
        this(1);
    }

    /**
     * Construct a Wicket with the given number of closed locks.
     *
     * @param _name Wicket's identifier
     * @param _count the initial number of closed locks
     * @param _debugOutput whether to print debug info or not
     * @throws IllegalArgumentException if count is less than 1
     */
    public Wicket(String _name, int _count, PrintStream _debugOutput) {
        this(_count);
        name = _name;
        debugOutput = _debugOutput;
    }

    /**
     * Construct a Wicket with the given number of closed locks.
     *
     * @param count the initial number of closed locks
     * @throws IllegalArgumentException if count is less than 1
     */
    public Wicket(int count) {
        if (count < 1)
            throw new IllegalArgumentException(
                "count is less than one: " + count);
        this.count = count;
    }

    /**
     * Wait for all locks of this Wicket to be open.
     *
     * <p>If all locks are already open then returns immediately.
     *
     * <p>If at least one lock is still closed then the current thread becomes
     * disabled for thread scheduling purposes and lies dormant until all
     * the locks will be open by some other threads. One lock can be open
     * by invoking the unlock method for this Wicket.
     *
     * <p>Please note, that the method would ignore Thread.interrupt() requests.
     */
    public synchronized void waitFor() {
        ++waiters;
        if (debugOutput != null) {
            debugOutput.printf("Wicket %s: waitFor()\n", name);
        }

        while (count > 0) {
            try {
                wait();
            } catch (InterruptedException e) {}
        }
        --waiters;
    }

    /**
     * Wait for all locks of this Wicket to be open within the given
     * period of time.
     *
     * <p>If all locks are already open then returns immediately with zero.
     *
     * <p>If the time is equal to zero, the method will not
     * wait and returns a number of closed locks,
     * if all locks are open, the return value is zero.
     *
     * <p>If at least one lock is still closed then the current thread becomes
     * disabled for thread scheduling purposes and lies dormant until
     * of the two things happens:
     *
     *   <ul><li>Some other threads invoke the unlock method for this Wicket
     *   to open all the closed locks; or
     *
     *   <li>The specified waiting time elapses.</ul>
     *
     * <p>If all locks are open then the return value is 0.
     *
     * <p>If the specified waiting time elapses and some locks are still closed
     * then the return value is equal to number of closed locks.
     *
     * <p>Please note, that the method would ignore Thread.interrupt() requests.
     *
     * @param timeout the maximum time to wait in milliseconds
     * @return the number of closed locks
     * @throws IllegalArgumentException if timeout is less than 0
     */
    public synchronized int waitFor(long timeout) {
        if (debugOutput != null) {
            debugOutput.printf("Wicket %s: waitFor(%d)\n", name, timeout);
        }

        if (timeout < 0)
            throw new IllegalArgumentException(
                "timeout value is negative: " + timeout);
        ++waiters;
        long waitTime = timeout;
        long startTime = System.currentTimeMillis();
        while (count > 0 && waitTime > 0) {
            try {
                wait(waitTime);
            } catch (InterruptedException e) {}
            waitTime = timeout - (System.currentTimeMillis() - startTime);
        }
        --waiters;
        return (count);
    }

    /**
     * Unlock one closed lock.
     *
     * <p>Open a lock, reducing the number of closed locks by one.
     *
     * <p>If last closed lock is opened then all of the threads waiting
     * by invoking the waitFor method for this Wicket will be released
     * and re-enabled for thread scheduling purposes.
     *
     * @throws IllegalStateException if there is no one closed lock
     */
    public synchronized void unlock() {
        if (debugOutput != null) {
            debugOutput.printf("Wicket %s: unlock()\n", name);
        }

        if (count == 0)
            throw new IllegalStateException("locks are already open");

        --count;
        if (count == 0) {
            notifyAll();
        }
    }

    /**
     * Unlock all closed locks.
     *
     * <p>Open all closed locks, setting the number of closed locks to zero.
     *
     * <p>If any threads are waiting by invoking the waitFor method for
     * this Wicket then they will be released and re-enabled for thread
     * scheduling purposes.
     */
    public synchronized void unlockAll() {
        if (debugOutput != null) {
            debugOutput.printf("Wicket %s: unlockAll()\n", name);
        }

        count = 0;
        notifyAll();
    }

    /**
     * Return current number of waiters - threads that are currently
     * waiting using one of waitFor methods.
     *
     * @return number of waiters
     */
    public synchronized int getWaiters() {
        if (debugOutput != null) {
            debugOutput.printf("Wicket %s: getWaiters()\n", name);
        }
        return waiters;
    }
}