Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor default random function #99

Merged
merged 2 commits into from
Dec 22, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@

import java.security.SecureRandom;
import java.util.Random;
import java.util.concurrent.locks.ReentrantLock;

import com.github.f4b6a3.uuid.factory.function.RandomFunction;
import com.github.f4b6a3.uuid.util.internal.RandomUtil;
Expand All @@ -35,8 +36,11 @@
* <p>
* The current implementation uses a pool {@link SecureRandom}.
* <p>
* The pool size is equal to the number of processors available, up to a maximum
* of 32.
* The pool size depends on the number of processors available, up to a maximum
* of 32. The minimum is 4.
* <p>
* The pool items are deleted very often to avoid holding them for too long.
* They are also deleted to avoid holding more instances than threads running.
* <p>
* The PRNG algorithm can be specified by system property or environment
* variable. See {@link RandomUtil#newSecureRandom()}.
Expand All @@ -48,11 +52,20 @@ public final class DefaultRandomFunction implements RandomFunction {

private static final int POOL_SIZE = processors();
private static final Random[] POOL = new Random[POOL_SIZE];
private static final ReentrantLock lock = new ReentrantLock();

@Override
public byte[] apply(final int length) {

final byte[] bytes = new byte[length];
current().nextBytes(bytes);

// every now and then
if (bytes.length > 0 && bytes[0x00] == 0) {
// delete a random item from the pool
delete((new Random()).nextInt(POOL_SIZE));
}

return bytes;
}

Expand All @@ -61,12 +74,25 @@ private static Random current() {
// calculate the pool index given the current thread ID
final int index = (int) Thread.currentThread().getId() % POOL_SIZE;

// lazy loading instance
if (POOL[index] == null) {
POOL[index] = RandomUtil.newSecureRandom();
lock.lock();
try {
// lazy loading instance
if (POOL[index] == null) {
POOL[index] = RandomUtil.newSecureRandom();
}
return POOL[index];
} finally {
lock.unlock();
}
}

return POOL[index];
private static void delete(int index) {
lock.lock();
try {
POOL[index] = null;
} finally {
lock.unlock();
}
}

private static int processors() {
Expand Down