-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #14 from briancorbinxyz/jdk23
Jdk23
- Loading branch information
Showing
15 changed files
with
242 additions
and
36 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,11 @@ | ||
package org.example; | ||
|
||
/// This interface defines a contract for classes that can be serialized to JSON strings. | ||
/// Any class that implements this interface must provide an implementation of the `asJsonString()` | ||
/// method, which returns the JSON representation of the object. | ||
public interface JsonSerializable { | ||
|
||
/// Returns the JSON representation of the object. | ||
/// @return the JSON string representation of the object. | ||
String asJsonString(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,19 +1,21 @@ | ||
package org.example; | ||
|
||
/** | ||
* Tic-tac-toe player interface for all players | ||
* {@snippet : | ||
* // Create a human player | ||
* Player player = new HumanPlayer("X"); // @highlight region="player" substring="player" | ||
* | ||
* // Choose the next valid move on the game board | ||
* int validBoardLocation = player.nextMove(gameBoard); // @end | ||
* } | ||
*/ | ||
/// Tic-tac-toe player interface for all players | ||
/// {@snippet : | ||
/// // Create a human player | ||
/// Player player = new HumanPlayer("X"); // @highlight region="player" substring="player" | ||
/// | ||
/// // Choose the next valid move on the game board | ||
/// int validBoardLocation = player.nextMove(gameBoard); // @end | ||
/// } | ||
public sealed interface Player permits HumanPlayer, BotPlayer, RemoteBotPlayer { | ||
|
||
|
||
/// Returns the marker (e.g. "X" or "O") used by this player. | ||
/// @return the player's marker | ||
String getPlayerMarker(); | ||
|
||
/// Chooses the next valid move on the game board. | ||
/// @param board the current state of the game board | ||
/// @return the index of the next valid move on the board | ||
int nextMove(GameBoard board); | ||
|
||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
package org.example.interop; | ||
|
||
import java.lang.invoke.MethodHandles; | ||
import java.lang.invoke.VarHandle; | ||
|
||
public class PlayerIds { | ||
|
||
private volatile int nextId; | ||
|
||
private static final VarHandle NEXT_ID_VH; | ||
|
||
static { | ||
try { | ||
NEXT_ID_VH = MethodHandles.lookup().findVarHandle(PlayerIds.class, "nextId", int.class); | ||
} catch (NoSuchFieldException | IllegalAccessException e) { | ||
throw new ExceptionInInitializerError(e); | ||
} | ||
} | ||
|
||
public PlayerIds(int initialValue) { | ||
this.nextId = initialValue; | ||
} | ||
|
||
public int getNextId() { | ||
return nextId; | ||
} | ||
|
||
public int getNextIdAndIncrement() { | ||
return (int) NEXT_ID_VH.getAndAdd(this, 1); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
105 changes: 105 additions & 0 deletions
105
app/src/main/java/org/example/interop/benchmark/PlayerIdsBenchmark.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
package org.example.interop.benchmark; | ||
|
||
import java.util.concurrent.TimeUnit; | ||
import java.util.concurrent.atomic.AtomicInteger; | ||
import java.util.concurrent.locks.ReentrantLock; | ||
import org.example.interop.PlayerIds; | ||
import org.openjdk.jmh.annotations.Benchmark; | ||
import org.openjdk.jmh.annotations.BenchmarkMode; | ||
import org.openjdk.jmh.annotations.Mode; | ||
import org.openjdk.jmh.annotations.OutputTimeUnit; | ||
|
||
@SuppressWarnings("unused") | ||
public class PlayerIdsBenchmark { | ||
|
||
@Benchmark | ||
@BenchmarkMode(Mode.AverageTime) | ||
@OutputTimeUnit(TimeUnit.NANOSECONDS) | ||
public void testPlayerIdsGetId() { | ||
PlayerIds ids = new PlayerIds(1); | ||
for (int i = 0; i < 1000; i++) { | ||
var id = ids.getNextId(); | ||
} | ||
} | ||
|
||
@Benchmark | ||
@BenchmarkMode(Mode.AverageTime) | ||
@OutputTimeUnit(TimeUnit.NANOSECONDS) | ||
public void testPlayerIdsGetAndIncrementId() { | ||
PlayerIds ids = new PlayerIds(1); | ||
for (int i = 0; i < 1000; i++) { | ||
var id = ids.getNextIdAndIncrement(); | ||
} | ||
} | ||
|
||
@Benchmark | ||
@BenchmarkMode(Mode.AverageTime) | ||
@OutputTimeUnit(TimeUnit.NANOSECONDS) | ||
public void testAtomicIntegerGetId() { | ||
AtomicInteger ids = new AtomicInteger(1); | ||
for (int i = 0; i < 1000; i++) { | ||
var id = ids.get(); | ||
} | ||
} | ||
|
||
@Benchmark | ||
@BenchmarkMode(Mode.AverageTime) | ||
@OutputTimeUnit(TimeUnit.NANOSECONDS) | ||
public void testAtomicIntegerGetAndIncrement() { | ||
AtomicInteger ids = new AtomicInteger(1); | ||
for (int i = 0; i < 1000; i++) { | ||
var id = ids.getAndIncrement(); | ||
} | ||
} | ||
|
||
@Benchmark | ||
@BenchmarkMode(Mode.AverageTime) | ||
@OutputTimeUnit(TimeUnit.NANOSECONDS) | ||
public void testLockGetId() { | ||
Control ids = new Control(1); | ||
for (int i = 0; i < 1000; i++) { | ||
var id = ids.getId(); | ||
} | ||
} | ||
|
||
@Benchmark | ||
@BenchmarkMode(Mode.AverageTime) | ||
@OutputTimeUnit(TimeUnit.NANOSECONDS) | ||
public void testLockGetAndIncrement() { | ||
Control ids = new Control(1); | ||
for (int i = 0; i < 1000; i++) { | ||
var id = ids.getAndIncrement(); | ||
} | ||
} | ||
|
||
/// Naive implementation of an id generator. | ||
private static class Control { | ||
private final ReentrantLock lock = new ReentrantLock(); | ||
|
||
private int id = 1; | ||
|
||
private Control(int initialValue) { | ||
this.id = initialValue; | ||
} | ||
|
||
private int getId() { | ||
lock.lock(); | ||
try { | ||
return id; | ||
} finally { | ||
lock.unlock(); | ||
} | ||
} | ||
|
||
private int getAndIncrement() { | ||
lock.lock(); | ||
try { | ||
int oldId = id; | ||
id = id + 1; | ||
return oldId; | ||
} finally { | ||
lock.unlock(); | ||
} | ||
} | ||
} | ||
} |
Oops, something went wrong.