Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/test/jdk/java/foreign/TestResourceScope.java
41144 views
1
/*
2
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
*
5
* This code is free software; you can redistribute it and/or modify it
6
* under the terms of the GNU General Public License version 2 only, as
7
* published by the Free Software Foundation.
8
*
9
* This code is distributed in the hope that it will be useful, but WITHOUT
10
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12
* version 2 for more details (a copy is included in the LICENSE file that
13
* accompanied this code).
14
*
15
* You should have received a copy of the GNU General Public License version
16
* 2 along with this work; if not, write to the Free Software Foundation,
17
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18
*
19
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20
* or visit www.oracle.com if you need additional information or have any
21
* questions.
22
*/
23
24
/*
25
* @test
26
* @modules java.base/jdk.internal.ref
27
* jdk.incubator.foreign/jdk.incubator.foreign
28
* @run testng/othervm TestResourceScope
29
*/
30
31
import java.lang.ref.Cleaner;
32
33
import jdk.incubator.foreign.ResourceScope;
34
import jdk.internal.ref.CleanerFactory;
35
36
import org.testng.annotations.DataProvider;
37
import org.testng.annotations.Test;
38
import static org.testng.Assert.*;
39
40
import java.util.ArrayList;
41
import java.util.List;
42
import java.util.concurrent.atomic.AtomicInteger;
43
import java.util.concurrent.atomic.AtomicReference;
44
import java.util.function.Supplier;
45
import java.util.stream.IntStream;
46
47
public class TestResourceScope {
48
49
final static int N_THREADS = 10000;
50
51
@Test(dataProvider = "cleaners")
52
public void testConfined(Supplier<Cleaner> cleanerSupplier) {
53
AtomicInteger acc = new AtomicInteger();
54
Cleaner cleaner = cleanerSupplier.get();
55
ResourceScope scope = cleaner != null ?
56
ResourceScope.newConfinedScope(cleaner) :
57
ResourceScope.newConfinedScope();
58
for (int i = 0 ; i < N_THREADS ; i++) {
59
int delta = i;
60
scope.addCloseAction(() -> acc.addAndGet(delta));
61
}
62
assertEquals(acc.get(), 0);
63
64
if (cleaner == null) {
65
scope.close();
66
assertEquals(acc.get(), IntStream.range(0, N_THREADS).sum());
67
} else {
68
scope = null;
69
int expected = IntStream.range(0, N_THREADS).sum();
70
while (acc.get() != expected) {
71
kickGC();
72
}
73
}
74
}
75
76
@Test(dataProvider = "cleaners")
77
public void testSharedSingleThread(Supplier<Cleaner> cleanerSupplier) {
78
AtomicInteger acc = new AtomicInteger();
79
Cleaner cleaner = cleanerSupplier.get();
80
ResourceScope scope = cleaner != null ?
81
ResourceScope.newSharedScope(cleaner) :
82
ResourceScope.newSharedScope();
83
for (int i = 0 ; i < N_THREADS ; i++) {
84
int delta = i;
85
scope.addCloseAction(() -> acc.addAndGet(delta));
86
}
87
assertEquals(acc.get(), 0);
88
89
if (cleaner == null) {
90
scope.close();
91
assertEquals(acc.get(), IntStream.range(0, N_THREADS).sum());
92
} else {
93
scope = null;
94
int expected = IntStream.range(0, N_THREADS).sum();
95
while (acc.get() != expected) {
96
kickGC();
97
}
98
}
99
}
100
101
@Test(dataProvider = "cleaners")
102
public void testSharedMultiThread(Supplier<Cleaner> cleanerSupplier) {
103
AtomicInteger acc = new AtomicInteger();
104
Cleaner cleaner = cleanerSupplier.get();
105
List<Thread> threads = new ArrayList<>();
106
ResourceScope scope = cleaner != null ?
107
ResourceScope.newSharedScope(cleaner) :
108
ResourceScope.newSharedScope();
109
AtomicReference<ResourceScope> scopeRef = new AtomicReference<>(scope);
110
for (int i = 0 ; i < N_THREADS ; i++) {
111
int delta = i;
112
Thread thread = new Thread(() -> {
113
try {
114
scopeRef.get().addCloseAction(() -> {
115
acc.addAndGet(delta);
116
});
117
} catch (IllegalStateException ex) {
118
// already closed - we need to call cleanup manually
119
acc.addAndGet(delta);
120
}
121
});
122
threads.add(thread);
123
}
124
assertEquals(acc.get(), 0);
125
threads.forEach(Thread::start);
126
127
// if no cleaner, close - not all segments might have been added to the scope!
128
// if cleaner, don't unset the scope - after all, the scope is kept alive by threads
129
if (cleaner == null) {
130
while (true) {
131
try {
132
scope.close();
133
break;
134
} catch (IllegalStateException ise) {
135
// scope is acquired (by add) - wait some more
136
}
137
}
138
}
139
140
threads.forEach(t -> {
141
try {
142
t.join();
143
} catch (InterruptedException ex) {
144
fail();
145
}
146
});
147
148
if (cleaner == null) {
149
assertEquals(acc.get(), IntStream.range(0, N_THREADS).sum());
150
} else {
151
scope = null;
152
scopeRef.set(null);
153
int expected = IntStream.range(0, N_THREADS).sum();
154
while (acc.get() != expected) {
155
kickGC();
156
}
157
}
158
}
159
160
@Test(dataProvider = "cleaners")
161
public void testLockSingleThread(Supplier<Cleaner> cleanerSupplier) {
162
Cleaner cleaner = cleanerSupplier.get();
163
ResourceScope scope = cleaner != null ?
164
ResourceScope.newConfinedScope(cleaner) :
165
ResourceScope.newConfinedScope();
166
List<ResourceScope.Handle> handles = new ArrayList<>();
167
for (int i = 0 ; i < N_THREADS ; i++) {
168
handles.add(scope.acquire());
169
}
170
171
while (true) {
172
try {
173
scope.close();
174
assertEquals(handles.size(), 0);
175
break;
176
} catch (IllegalStateException ex) {
177
assertTrue(handles.size() > 0);
178
ResourceScope.Handle handle = handles.remove(0);
179
scope.release(handle);
180
scope.release(handle); // make sure it's idempotent
181
scope.release(handle); // make sure it's idempotent
182
}
183
}
184
}
185
186
@Test(dataProvider = "cleaners")
187
public void testLockSharedMultiThread(Supplier<Cleaner> cleanerSupplier) {
188
Cleaner cleaner = cleanerSupplier.get();
189
ResourceScope scope = cleaner != null ?
190
ResourceScope.newSharedScope(cleaner) :
191
ResourceScope.newSharedScope();
192
AtomicInteger lockCount = new AtomicInteger();
193
for (int i = 0 ; i < N_THREADS ; i++) {
194
new Thread(() -> {
195
lockCount.incrementAndGet();
196
try {
197
ResourceScope.Handle handle = scope.acquire();
198
waitSomeTime();
199
scope.release(handle);
200
scope.release(handle); // make sure it's idempotent
201
scope.release(handle); // make sure it's idempotent
202
} catch (IllegalStateException ex) {
203
// might be already closed - do nothing
204
} finally {
205
lockCount.decrementAndGet();
206
}
207
}).start();
208
}
209
210
while (lockCount.get() > 0) {
211
try {
212
scope.close();
213
assertEquals(lockCount.get(), 0);
214
break;
215
} catch (IllegalStateException ex) {
216
waitSomeTime();
217
}
218
}
219
}
220
221
@Test
222
public void testCloseEmptyConfinedScope() {
223
ResourceScope.newConfinedScope().close();
224
}
225
226
@Test
227
public void testCloseEmptySharedScope() {
228
ResourceScope.newSharedScope().close();
229
}
230
231
@Test
232
public void testCloseConfinedLock() {
233
ResourceScope scope = ResourceScope.newConfinedScope();
234
ResourceScope.Handle handle = scope.acquire();
235
AtomicReference<Throwable> failure = new AtomicReference<>();
236
Thread t = new Thread(() -> {
237
try {
238
scope.release(handle);
239
scope.release(handle); // make sure it's idempotent
240
scope.release(handle); // make sure it's idempotent
241
} catch (Throwable ex) {
242
failure.set(ex);
243
}
244
});
245
t.start();
246
try {
247
t.join();
248
assertNotNull(failure.get());
249
assertEquals(failure.get().getClass(), IllegalStateException.class);
250
} catch (Throwable ex) {
251
throw new AssertionError(ex);
252
}
253
}
254
255
@Test(dataProvider = "scopes")
256
public void testScopeHandles(Supplier<ResourceScope> scopeFactory) {
257
ResourceScope scope = scopeFactory.get();
258
acquireRecursive(scope, 5);
259
if (!scope.isImplicit()) {
260
scope.close();
261
}
262
}
263
264
private void acquireRecursive(ResourceScope scope, int acquireCount) {
265
ResourceScope.Handle handle = scope.acquire();
266
assertEquals(handle.scope(), scope);
267
if (acquireCount > 0) {
268
// recursive acquire
269
acquireRecursive(scope, acquireCount - 1);
270
}
271
if (!scope.isImplicit()) {
272
assertThrows(IllegalStateException.class, scope::close);
273
}
274
scope.release(handle);
275
scope.release(handle); // make sure it's idempotent
276
scope.release(handle); // make sure it's idempotent
277
}
278
279
private void waitSomeTime() {
280
try {
281
Thread.sleep(10);
282
} catch (InterruptedException ex) {
283
// ignore
284
}
285
}
286
287
private void kickGC() {
288
for (int i = 0 ; i < 100 ; i++) {
289
byte[] b = new byte[100];
290
System.gc();
291
Thread.onSpinWait();
292
}
293
}
294
295
@DataProvider
296
static Object[][] cleaners() {
297
return new Object[][] {
298
{ (Supplier<Cleaner>)() -> null },
299
{ (Supplier<Cleaner>)Cleaner::create },
300
{ (Supplier<Cleaner>)CleanerFactory::cleaner }
301
};
302
}
303
304
@DataProvider
305
static Object[][] scopes() {
306
return new Object[][] {
307
{ (Supplier<ResourceScope>)ResourceScope::newConfinedScope },
308
{ (Supplier<ResourceScope>)ResourceScope::newSharedScope },
309
{ (Supplier<ResourceScope>)ResourceScope::newImplicitScope },
310
{ (Supplier<ResourceScope>)ResourceScope::globalScope }
311
};
312
}
313
}
314
315