-
-
Notifications
You must be signed in to change notification settings - Fork 48
/
Latch.ts
151 lines (142 loc) · 5.06 KB
/
Latch.ts
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
//================================================================
/**
* @packageDocumentation
* @module std
*/
//================================================================
import { ConditionVariable } from "./ConditionVariable";
/**
* Latch for critical sections.
*
* The `Latch` class blocks critical sections until the downward counter to be zero. Howver,
* unlike {@link Barrier} who can reusable that downward counter be reset whenever reach to the
* zero, downward of the `Latch` is not reusable but diposable.
*
* @author Jeongho Nam - https://github.com/samchon
*/
export class Latch
{
private cv_: ConditionVariable;
private count_: number;
/* ---------------------------------------------------------
CONSTRUCTORS
--------------------------------------------------------- */
/**
* Initializer Constructor.
*
* @param size Size of the downward counter.
*/
public constructor(size: number)
{
this.cv_ = new ConditionVariable();
this.count_ = size;
}
/* ---------------------------------------------------------
WAIT FUNCTIONS
--------------------------------------------------------- */
/**
* Waits until the counter to be zero.
*
* Blocks the function calling until internal counter to be reached to the zero.
*
* If the {@link Latch} already has been reached to the zero, it would be returned
* immediately.
*/
public async wait(): Promise<void>
{
if (this._Try_wait() === false)
await this.cv_.wait();
}
/**
* Test whether the counter has been reached to the zero.
*
* The {@link try_wait} function tests whether the internal counter has been reached to the
* zero.
*
* @return Whether reached to zero or not.
*/
public async try_wait(): Promise<boolean>
{
return this._Try_wait();
}
/**
* Tries to wait until the counter to be zero in timeout.
*
* Attempts to block the function calling until internal counter to be reached to the zero
* in timeout. If succeeded to waiting the counter to be reached to the zero, it returns
* `true`. Otherwise, the {@link Latch} fails to reach to the zero in the given time, the
* function gives up the waiting and returns `false`.
*
* If the {@link Latch} already has been reached to the zero, it would return `true` directly.
*
* @param ms The maximum miliseconds for waiting.
* @return Whether succeeded to waiting in the given time.
*/
public async wait_for(ms: number): Promise<boolean>
{
if (this._Try_wait() === true)
return true;
else
return await this.cv_.wait_for(ms);
}
/**
* Tries to wait until the counter to be zero in time expiration.
*
* Attempts to block the function calling until internal counter to be reached to the zero
* in time expiration. If succeeded to waiting the counter to be reached to the zero, it
* returns `true`. Otherwise, the {@link Latch} fails to reach to the zero in the given time,
* the function gives up the waiting and returns `false`.
*
* If the {@link Latch} already has been reached to the zero, it would return `true` directly.
*
* @param at The maximum time point to wait.
* @return Whether succeeded to waiting in the given time.
*/
public async wait_until(at: Date): Promise<boolean>
{
if (this._Try_wait() === true)
return true;
else
return await this.cv_.wait_until(at);
}
private _Try_wait(): boolean
{
return this.count_ <= 0;
}
/* -----------------------------------------------------------
ARRIVAL FUNCTIONS
----------------------------------------------------------- */
/**
* Derecements the counter.
*
* Decrements the counter by *n* without blocking.
*
* If the parametric value *n* is equal to or greater than internal counter, so that the
* internal counter be equal to or less than zero, everyone who are {@link wait waiting} for
* the {@link Latch} would continue their execution.
*
* @param n Value of the decrement. Default is 1.
*/
public async count_down(n: number = 1): Promise<void>
{
this.count_ -= n;
if (this._Try_wait() === true)
await this.cv_.notify_all();
}
/**
* Decrements the counter and waits until the counter to be zero.
*
* Decrements the counter by *n* and blocks the section until internal counter to be zero.
*
* If the parametric value *n* is equal to or greater than internal counter, so that the
* internal counter be equal to or less than zero, everyone who are {@link wait waiting} for
* the {@link Latch} would continue their execution including this one.
*
* @param n Value of the decrement. Default is 1.
*/
public async arrive_and_wait(n: number = 1): Promise<void>
{
await this.count_down(n);
await this.wait();
}
}