Skip to content

Commit 5d0a2d8

Browse files
committed
Enhancement Request 36456812 - [36430839->24.09] Add support for defining virtual-thread-per-task executors in JDK 21 (merge main -> ce/main @ 108026)
[git-p4: depot-paths = "//dev/coherence-ce/main/": change = 108030]
1 parent 17e9e5c commit 5d0a2d8

File tree

13 files changed

+319
-12
lines changed

13 files changed

+319
-12
lines changed

prj/coherence-concurrent/README.adoc

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
///////////////////////////////////////////////////////////////////////////////
2-
Copyright (c) 2021, Oracle and/or its affiliates.
2+
Copyright (c) 2021, 2024, Oracle and/or its affiliates.
33

44
Licensed under the Universal Permissive License v 1.0 as shown at
5-
http://oss.oracle.com/licenses/upl.
5+
https://oss.oracle.com/licenses/upl.
66
///////////////////////////////////////////////////////////////////////////////
77
= Distributed Concurrency
88
@@ -131,6 +131,9 @@ Several executor types are available for configuration.
131131
132132
|Work stealing
133133
|Creates a work-stealing thread pool using the number of available processors as its target parallelism level.
134+
135+
|VirtualThread
136+
|Creates a VirtualThread-per-task ExecutorService. Requires JDK 21 or newer.
134137
|===
135138
136139
===== Configuration Elements
@@ -158,6 +161,11 @@ Several executor types are available for configuration.
158161
|N/A
159162
|Defines a work-stealing-pool executor
160163
164+
|virtual-per-task
165+
|no
166+
|N/A
167+
|Defines a VirtualThread-per-task executor
168+
161169
|name
162170
|yes
163171
|java.lang.String

prj/coherence-concurrent/pom.xml

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<?xml version="1.0" encoding="UTF-8"?>
22
<!--
3-
~ Copyright (c) 2000, 2023, Oracle and/or its affiliates.
3+
~ Copyright (c) 2000, 2024, Oracle and/or its affiliates.
44
~
55
~ Licensed under the Universal Permissive License v 1.0 as shown at
66
~ https://oss.oracle.com/licenses/upl.
@@ -85,6 +85,11 @@
8585
<plugin>
8686
<groupId>org.apache.felix</groupId>
8787
<artifactId>maven-bundle-plugin</artifactId>
88+
<configuration>
89+
<instructions>
90+
<Multi-Release>true</Multi-Release>
91+
</instructions>
92+
</configuration>
8893
</plugin>
8994

9095
<!-- maven-jar-plugin with configuration to package generated MANIFEST.MF to project jar -->
@@ -130,6 +135,26 @@
130135
</executions>
131136
</plugin>
132137

138+
<plugin>
139+
<artifactId>maven-compiler-plugin</artifactId>
140+
<executions>
141+
<execution>
142+
<id>compile-java21</id>
143+
<phase>compile</phase>
144+
<goals>
145+
<goal>compile</goal>
146+
</goals>
147+
<configuration>
148+
<release>21</release>
149+
<compileSourceRoots>
150+
<compileSourceRoot>${project.basedir}/src/main/java21</compileSourceRoot>
151+
</compileSourceRoots>
152+
<multiReleaseOutput>true</multiReleaseOutput>
153+
</configuration>
154+
</execution>
155+
</executions>
156+
</plugin>
157+
133158
<!-- this is necessary as this concurrent.xsd includes coherence-config-base.xsd. -->
134159
<plugin>
135160
<artifactId>maven-resources-plugin</artifactId>

prj/coherence-concurrent/src/main/java/com/oracle/coherence/concurrent/config/builders/AbstractExecutorBuilder.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
/*
2-
* Copyright (c) 2021 Oracle and/or its affiliates.
2+
* Copyright (c) 2021, 2024, Oracle and/or its affiliates.
33
*
44
* Licensed under the Universal Permissive License v 1.0 as shown at
5-
* http://oss.oracle.com/licenses/upl.
5+
* https://oss.oracle.com/licenses/upl.
66
*/
77
package com.oracle.coherence.concurrent.config.builders;
88

@@ -16,7 +16,6 @@
1616
import com.tangosol.config.annotation.Injectable;
1717
import com.tangosol.config.expression.Expression;
1818

19-
2019
/**
2120
* Base {@link ParameterizedBuilder} fpr named executors.
2221
*

prj/coherence-concurrent/src/main/java/com/oracle/coherence/concurrent/config/builders/AbstractExecutorWithFactoryBuilder.java

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,16 @@
77
package com.oracle.coherence.concurrent.config.builders;
88

99
import com.oracle.coherence.concurrent.executor.util.NamedThreadFactory;
10+
1011
import com.tangosol.coherence.config.ParameterList;
12+
1113
import com.tangosol.coherence.config.builder.ParameterizedBuilder;
1214

1315
import com.tangosol.config.annotation.Injectable;
1416

1517
import com.tangosol.config.expression.Parameter;
1618
import com.tangosol.config.expression.ParameterResolver;
19+
1720
import java.util.concurrent.ThreadFactory;
1821

1922
/**
@@ -66,11 +69,24 @@ protected ThreadFactory instantiateThreadFactory(String sName,
6669
ParameterResolver resolver, ClassLoader loader, ParameterList listParameters)
6770
{
6871
return m_bldr == null
69-
? new NamedThreadFactory(sName)
72+
? instantiateNamedThreadFactory(sName)
7073
: m_bldr.realize(resolver, loader, listParameters);
7174

7275
}
7376

77+
/**
78+
* Creates a new {@link NamedThreadFactory}
79+
*
80+
* @param sName the name to use if no user-defined ThreadFactory
81+
* is defined
82+
*
83+
* @return the {@link NamedThreadFactory}
84+
*/
85+
protected ThreadFactory instantiateNamedThreadFactory(String sName)
86+
{
87+
return new NamedThreadFactory(sName);
88+
}
89+
7490
// ----- data members ---------------------------------------------------
7591

7692
/**

prj/coherence-concurrent/src/main/java/com/oracle/coherence/concurrent/config/builders/CachedBuilder.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import com.oracle.coherence.concurrent.config.NamedExecutorService;
1010

1111
import com.oracle.coherence.concurrent.executor.util.NamedThreadFactory;
12+
1213
import com.tangosol.coherence.config.ParameterList;
1314

1415
import com.tangosol.coherence.config.builder.ParameterizedBuilder;

prj/coherence-concurrent/src/main/java/com/oracle/coherence/concurrent/config/builders/FixedBuilder.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import com.oracle.coherence.concurrent.config.NamedExecutorService;
1010

1111
import com.oracle.coherence.concurrent.executor.util.NamedThreadFactory;
12+
1213
import com.tangosol.coherence.config.ParameterList;
1314

1415
import com.tangosol.coherence.config.builder.ParameterizedBuilder;

prj/coherence-concurrent/src/main/java/com/oracle/coherence/concurrent/config/builders/SingleBuilder.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import com.oracle.coherence.concurrent.config.NamedExecutorService;
1010

1111
import com.oracle.coherence.concurrent.executor.util.NamedThreadFactory;
12+
1213
import com.tangosol.coherence.config.ParameterList;
1314

1415
import com.tangosol.coherence.config.builder.ParameterizedBuilder;

prj/coherence-concurrent/src/main/java/com/oracle/coherence/concurrent/executor/util/NamedThreadFactory.java

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@
77
package com.oracle.coherence.concurrent.executor.util;
88

99
import java.util.concurrent.ThreadFactory;
10-
import java.util.concurrent.atomic.AtomicInteger;
1110

11+
import java.util.concurrent.atomic.AtomicInteger;
1212

1313
/**
1414
* A {@link ThreadFactory} implementation for used with {@code named}
@@ -45,12 +45,33 @@ public NamedThreadFactory(String f_sName)
4545
@Override
4646
public Thread newThread(Runnable r)
4747
{
48-
return new Thread(r, "CES:" + f_sName + '-' + f_counter.incrementAndGet());
48+
return newThread(r, "CES:" + f_sName + '-' + f_counter.incrementAndGet());
49+
}
50+
51+
// ----- helper methods -------------------------------------------------
52+
53+
/**
54+
* Creates a new thread for the given runnable and using the given name.
55+
*
56+
* @param r the {@link Runnable}
57+
* @param sName the name of the thread
58+
*
59+
* @return a new thread for the given runnable and using the given name
60+
*/
61+
public Thread newThread(Runnable r, String sName)
62+
{
63+
return new Thread(r, sName);
4964
}
5065

5166
// ----- data members ---------------------------------------------------
5267

68+
/**
69+
* The thread counter.
70+
*/
5371
protected final AtomicInteger f_counter = new AtomicInteger();
5472

73+
/**
74+
* The thread name.
75+
*/
5576
protected final String f_sName;
5677
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
/*
2+
* Copyright (c) 2024, Oracle and/or its affiliates.
3+
*
4+
* Licensed under the Universal Permissive License v 1.0 as shown at
5+
* https://oss.oracle.com/licenses/upl.
6+
*/
7+
package com.oracle.coherence.concurrent.config;
8+
9+
import com.oracle.coherence.concurrent.config.processors.CachedProcessor;
10+
import com.oracle.coherence.concurrent.config.processors.FixedProcessor;
11+
import com.oracle.coherence.concurrent.config.processors.SingleProcessor;
12+
import com.oracle.coherence.concurrent.config.processors.ThreadFactoryProcessor;
13+
import com.oracle.coherence.concurrent.config.processors.WorkStealingProcessor;
14+
import com.oracle.coherence.concurrent.config.processors.VirtualPerTaskProcessor;
15+
16+
import com.tangosol.config.xml.AbstractNamespaceHandler;
17+
18+
/**
19+
* {@link com.tangosol.config.xml.NamespaceHandler} for processing
20+
* {@code coherence-concurrent}-related artifacts defined in a Coherence
21+
* configuration file.
22+
*
23+
* @author rl 11.20.21
24+
* @since 21.12
25+
*/
26+
public class NamespaceHandler
27+
extends AbstractNamespaceHandler
28+
{
29+
// ----- constructors ---------------------------------------------------
30+
31+
/**
32+
* Construct {@code NamespaceHandler} instance.
33+
*/
34+
public NamespaceHandler()
35+
{
36+
registerProcessor(CachedProcessor.class);
37+
registerProcessor(FixedProcessor.class);
38+
registerProcessor(SingleProcessor.class);
39+
registerProcessor(ThreadFactoryProcessor.class);
40+
registerProcessor(WorkStealingProcessor.class);
41+
registerProcessor(VirtualPerTaskProcessor.class);
42+
}
43+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
/*
2+
* Copyright (c) 2024, Oracle and/or its affiliates.
3+
*
4+
* Licensed under the Universal Permissive License v 1.0 as shown at
5+
* https://oss.oracle.com/licenses/upl.
6+
*/
7+
package com.oracle.coherence.concurrent.config.builders;
8+
9+
import com.oracle.coherence.concurrent.config.NamedExecutorService;
10+
11+
import com.oracle.coherence.concurrent.executor.util.NamedThreadFactory;
12+
13+
import com.tangosol.coherence.config.ParameterList;
14+
15+
import com.tangosol.coherence.config.builder.ParameterizedBuilder;
16+
17+
import com.tangosol.config.expression.ParameterResolver;
18+
19+
import java.util.concurrent.ExecutorService;
20+
import java.util.concurrent.Executors;
21+
import java.util.concurrent.ThreadFactory;
22+
23+
import java.util.function.Supplier;
24+
25+
/**
26+
* A {@link ParameterizedBuilder} for constructing a {@link NamedExecutorService}
27+
* wrapper that will construct a virtual-thread-per-task executor.
28+
*
29+
* @author rl 3.26.2024
30+
* @since 15.1.1.0
31+
*/
32+
public class VirtualPerTaskBuilder
33+
extends AbstractExecutorWithFactoryBuilder<NamedExecutorService>
34+
{
35+
// ----- ParameterizedBuilder interface ---------------------------------
36+
37+
@Override
38+
public NamedExecutorService realize(ParameterResolver resolver, ClassLoader loader, ParameterList listParameters)
39+
{
40+
String sName = m_name.evaluate(resolver);
41+
ThreadFactory factory = instantiateThreadFactory(sName, resolver,
42+
loader, listParameters);
43+
Supplier<ExecutorService> supplier = factory == null
44+
? Executors::newVirtualThreadPerTaskExecutor
45+
: () -> Executors.newThreadPerTaskExecutor(factory);
46+
NamedExecutorService service = new NamedExecutorService(sName, description(factory), supplier);
47+
48+
register(service);
49+
50+
return service;
51+
}
52+
53+
// ----- helper methods -------------------------------------------------
54+
55+
@Override
56+
protected ThreadFactory instantiateNamedThreadFactory(String sName)
57+
{
58+
return new VirtualNamedThreadFactory(sName);
59+
}
60+
61+
// ----- inner class: VirtualNamedThreadFactory -------------------------
62+
63+
/**
64+
* A {@link ThreadFactory} for virtual threads.
65+
*/
66+
protected static class VirtualNamedThreadFactory
67+
extends NamedThreadFactory
68+
{
69+
// ----- constructors -----------------------------------------------
70+
71+
/**
72+
* Constructs a new {@code VirtualNamedThreadFactory}.
73+
*
74+
* @param f_sName the base name that will be used when naming
75+
* threads
76+
*/
77+
public VirtualNamedThreadFactory(String f_sName)
78+
{
79+
super(f_sName);
80+
}
81+
82+
// ----- NamedThreadFactory methods ---------------------------------
83+
84+
@Override
85+
public Thread newThread(Runnable r, String sName)
86+
{
87+
Thread.Builder.OfVirtual builder = Thread.ofVirtual();
88+
if (sName != null)
89+
{
90+
builder.name(sName);
91+
}
92+
return builder.unstarted(r);
93+
}
94+
}
95+
96+
// ----- helper methods -------------------------------------------------
97+
98+
/**
99+
* Creates the description for this executor.
100+
*
101+
* @param factory the {@link ThreadFactory}, if any
102+
*
103+
* @return the description for this executor
104+
*/
105+
protected String description(ThreadFactory factory)
106+
{
107+
String sFactory = factory == null || VirtualNamedThreadFactory.class.equals(factory.getClass())
108+
? "default"
109+
: factory.getClass().getName();
110+
111+
return String.format("VirtualThreadPerTask(ThreadFactory=%s)", sFactory);
112+
}
113+
}

0 commit comments

Comments
 (0)