Skip to content

Commit

Permalink
Avoid circularity through class loading in circularity lock locking m…
Browse files Browse the repository at this point in the history
…echanism.
  • Loading branch information
raphw committed Jul 11, 2024
1 parent 4cbd7f7 commit 15af295
Showing 1 changed file with 35 additions and 20 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2585,20 +2585,31 @@ class Default implements CircularityLock {
private final ConcurrentMap<Thread, Boolean> threads = new ConcurrentHashMap<Thread, Boolean>();

/**
* Creates a default circularity lock. The constructor invokes all methods that are used by
* the lock to avoid that using this lock triggers class loading under use.
* An additional global lock that avoids circularity errors cause by class loading
* by the locking mechanism.
*/
private final AtomicBoolean open = new AtomicBoolean();

/**
* Creates a default circularity lock.
*/
public Default() {
Thread thread = Thread.currentThread();
threads.putIfAbsent(thread, true);
threads.remove(thread);
open.compareAndSet(false, true); // trigger expected class loading
}

/**
* {@inheritDoc}
*/
public boolean acquire() {
return threads.putIfAbsent(Thread.currentThread(), true) == null;
if (open.compareAndSet(true, false)) {
try {
return threads.putIfAbsent(Thread.currentThread(), true) == null;
} finally {
open.set(true);
}
} else {
return false;
}
}

/**
Expand Down Expand Up @@ -2639,6 +2650,12 @@ class Global implements CircularityLock {
*/
private final TimeUnit timeUnit;

/**
* An additional global lock that avoids circularity errors cause by class loading
* by the locking mechanism.
*/
private final AtomicBoolean open = new AtomicBoolean();

/**
* Creates a new global circularity lock that does not wait for a release.
*/
Expand All @@ -2656,26 +2673,24 @@ public Global(long time, TimeUnit timeUnit) {
lock = new ReentrantLock();
this.time = time;
this.timeUnit = timeUnit;
try {
if (!(time == 0 ? lock.tryLock() : lock.tryLock(time, timeUnit))) {
throw new IllegalStateException();
}
} catch (InterruptedException ignored) {
Thread.currentThread().interrupt();
return;
}
lock.unlock();
open.compareAndSet(false, true); // trigger expected class loading
}

/**
* {@inheritDoc}
*/
public boolean acquire() {
try {
return time == 0
? lock.tryLock()
: lock.tryLock(time, timeUnit);
} catch (InterruptedException ignored) {
if (open.compareAndSet(true, false)) {
try {
return time == 0
? lock.tryLock()
: lock.tryLock(time, timeUnit);
} catch (InterruptedException ignored) {
return false;
} finally {
open.set(true);
}
} else {
return false;
}
}
Expand Down

0 comments on commit 15af295

Please sign in to comment.