FazBrowse GitHub Viewer
|
Trending
|
URL:
|
Home
Tools:
[Download Repo ZIP]
[View Raw Code]
[Original HTTPS Page]
elimination-backoff-stack.java/Exchanger.java at master · moocf/elimination-backoff-stack.java · GitHub
Uh oh!
There was an error while loading.
Please reload this page
.
moocf
/
elimination-backoff-stack.java
Public
Notifications
You must be signed in to change notification settings
Fork
1
Star
2
Code
Issues
0
Pull requests
0
Actions
Projects
Security and quality
0
Insights
Additional navigation options
Code
Issues
Pull requests
Actions
Projects
Security and quality
Insights
Expand file tree
Breadcrumbs
elimination-backoff-stack.java
/
Exchanger.java
Copy path
More file actions
More file actions
Latest commit
History
History
History
80 lines (73 loc) · 2.41 KB
Breadcrumbs
elimination-backoff-stack.java
/
Exchanger.java
Copy path
File metadata and controls
80 lines (73 loc) · 2.41 KB
Raw
Copy raw file
Download raw file
Open symbols panel
Edit and raw actions
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
import
java
.
util
.
concurrent
.*;
import
java
.
util
.
concurrent
.
atomic
.*;
// Exchanger is a lock-free object that permits two threads
// to exchange values, within a time limit.
class
Exchanger
<
T
> {
AtomicStampedReference
<
T
>
slot
;
static
final
int
EMPTY
=
0
;
static
final
int
WAITING
=
1
;
static
final
int
BUSY
=
2
;
// slot: stores value and stamp
// EMPTY: slot has no value.
// WAITING: slot has 1st value, waiting for 2nd.
// BUSY: slot has 2nd value, waiting to be empty.
public
Exchanger
() {
slot
=
new
AtomicStampedReference
<>(
null
,
0
);
}
// 1. Calculate last wait time.
// 2. If wait time exceeded, then throw expection.
// 3. Get slot value and stamp.
// 4a. If slot is EMPTY (no value):
// 4b. Try adding 1st value to slot, else retry 2.
// 4c. Try getting 2nd value from slot, within time limit.
// 5a. If slot is WAITING (has 1st value):
// 5b. Try adding 2nd value to slot, else retry 2.
// 5c. Return 1st value.
// 6a. If slot is BUSY (has 2nd value):
// 6b. Retry 2.
public
T
exchange
(
T
y
,
long
timeout
,
TimeUnit
unit
)
throws
TimeoutException
{
long
w
=
unit
.
toNanos
(
timeout
);
// 1
long
W
=
System
.
nanoTime
() +
w
;
// 1
int
[]
stamp
= {
EMPTY
};
while
(
System
.
nanoTime
() <
W
) {
// 2
T
x
=
slot
.
get
(
stamp
);
// 3
switch
(
stamp
[
0
]) {
// 3
case
EMPTY
:
// 4
if
(
addA
(
y
)) {
// 4
while
(
System
.
nanoTime
() <
W
)
// 4
if
((
x
=
removeB
()) !=
null
)
return
x
;
// 4
throw
new
TimeoutException
();
// 5
}
break
;
case
WAITING
:
// 7
if
(
addB
(
x
,
y
))
// 7
return
x
;
// 7
break
;
case
BUSY
:
// 8
break
;
// 8
default
:
}
}
throw
new
TimeoutException
();
// 2
}
// 1. Add 1st value to slot.
// 2. Set its stamp as WAITING (for 2nd).
private
boolean
addA
(
T
y
) {
// 1, 2
return
slot
.
compareAndSet
(
null
,
y
,
EMPTY
,
WAITING
);
}
// 1. Add 2nd value to slot.
// 2. Set its stamp as BUSY (for 1st to remove).
private
boolean
addB
(
T
x
,
T
y
) {
// 1, 2
return
slot
.
compareAndSet
(
x
,
y
,
WAITING
,
BUSY
);
}
// 1. If stamp is not BUSY (no 2nd value in slot), exit.
// 2. Set slot as EMPTY, and get 2nd value from slot.
private
T
removeB
() {
int
[]
stamp
= {
EMPTY
};
T
x
=
slot
.
get
(
stamp
);
// 1
if
(
stamp
[
0
] !=
BUSY
)
return
null
;
// 1
slot
.
set
(
null
,
EMPTY
);
// 2
return
x
;
// 2
}
}
Back
|
FazBrowse Home
|
New Git URL