1
+
// Protocol Buffers - Google's data interchange format
2
+
// Copyright 2025 Google Inc. All rights reserved.
3
+
//
4
+
// Use of this source code is governed by a BSD-style
5
+
// license that can be found in the LICENSE file or at
6
+
// https://developers.google.com/open-source/licenses/bsd
7
+
8
+
package com.google.protobuf;
9
+
10
+
import proto2_unittest.UnittestProto;
11
+
import proto2_unittest.UnittestProto.TestAllTypes;
12
+
import java.util.ArrayList;
13
+
import java.util.List;
14
+
import java.util.concurrent.CountDownLatch;
15
+
import java.util.concurrent.ExecutionException;
16
+
import java.util.concurrent.ExecutorService;
17
+
import java.util.concurrent.Executors;
18
+
import java.util.concurrent.Future;
19
+
import org.junit.Assert;
20
+
import org.junit.Test;
21
+
import org.junit.runner.RunWith;
22
+
import org.junit.runners.JUnit4;
23
+
24
+
@RunWith(JUnit4.class)
25
+
public final class ConcurrentDescriptorsTest {
26
+
public static final int N = 1000;
27
+
28
+
static class Worker implements Runnable {
29
+
private final CountDownLatch startSignal;
30
+
private final CountDownLatch doneSignal;
31
+
private final Runnable trigger;
32
+
33
+
Worker(CountDownLatch startSignal, CountDownLatch doneSignal, Runnable trigger) {
34
+
this.startSignal = startSignal;
35
+
this.doneSignal = doneSignal;
36
+
this.trigger = trigger;
37
+
}
38
+
39
+
@Override
40
+
public void run() {
41
+
try {
42
+
startSignal.await();
43
+
trigger.run();
44
+
} catch (InterruptedException | RuntimeException e) {
45
+
doneSignal.countDown();
46
+
throw new RuntimeException(e); // Rethrow for main thread to handle
47
+
}
48
+
doneSignal.countDown();
49
+
}
50
+
}
51
+
52
+
@Test
53
+
public void testSimultaneousStaticInit() throws InterruptedException {
54
+
ExecutorService executor = Executors.newFixedThreadPool(N);
55
+
CountDownLatch startSignal = new CountDownLatch(1);
56
+
CountDownLatch doneSignal = new CountDownLatch(N);
57
+
List<Future<?>> futures = new ArrayList<>(N);
58
+
for (int i = 0; i < N; i++) {
59
+
Future<?> future =
60
+
executor.submit(
61
+
new Worker(
62
+
startSignal,
63
+
doneSignal,
64
+
// Static method invocation triggers static initialization.
65
+
() -> Assert.assertNotNull(UnittestProto.getDescriptor())));
66
+
futures.add(future);
67
+
}
68
+
startSignal.countDown();
69
+
doneSignal.await();
70
+
System.out.println("Done with all threads...");
71
+
for (int i = 0; i < futures.size(); i++) {
72
+
try {
73
+
futures.get(i).get();
74
+
} catch (ExecutionException e) {
75
+
Assert.fail("Thread " + i + " failed with:" + e.getMessage());
76
+
}
77
+
}
78
+
executor.shutdown();
79
+
}
80
+
81
+
@Test
82
+
public void testSimultaneousFeatureAccess() throws InterruptedException {
83
+
ExecutorService executor = Executors.newFixedThreadPool(N);
84
+
CountDownLatch startSignal = new CountDownLatch(1);
85
+
CountDownLatch doneSignal = new CountDownLatch(N);
86
+
List<Future<?>> futures = new ArrayList<>(N);
87
+
for (int i = 0; i < N; i++) {
88
+
Future<?> future =
89
+
executor.submit(
90
+
new Worker(
91
+
startSignal,
92
+
doneSignal,
93
+
// hasPresence() uses the [field_presence] feature.
94
+
() ->
95
+
Assert.assertTrue(
96
+
TestAllTypes.getDescriptor()
97
+
.findFieldByName("optional_int32")
98
+
.hasPresence())));
99
+
futures.add(future);
100
+
}
101
+
startSignal.countDown();
102
+
doneSignal.await();
103
+
System.out.println("Done with all threads...");
104
+
for (int i = 0; i < futures.size(); i++) {
105
+
try {
106
+
futures.get(i).get();
107
+
} catch (ExecutionException e) {
108
+
Assert.fail("Thread " + i + " failed with:" + e.getMessage());
109
+
}
110
+
}
111
+
executor.shutdown();
112
+
}
113
+
}
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4