use of jetbrains.exodus.core.execution.locks.CriticalSection in project xodus by JetBrains.
the class ReentrantTransactionDispatcher method releaseTransaction.
/**
* Release transaction that was acquired in a thread with specified permits.
*/
void releaseTransaction(@NotNull final Thread thread, final int permits) {
try (CriticalSection ignored = criticalSection.enter()) {
int currentThreadPermits = getThreadPermits(thread);
if (permits > currentThreadPermits) {
throw new ExodusException("Can't release more permits than it was acquired");
}
acquiredPermits -= permits;
currentThreadPermits -= permits;
if (currentThreadPermits == 0) {
threadPermits.remove(thread);
} else {
threadPermits.put(thread, currentThreadPermits);
}
notifyNextWaiters();
}
}
use of jetbrains.exodus.core.execution.locks.CriticalSection in project xodus by JetBrains.
the class ReentrantTransactionDispatcher method acquireTransaction.
/**
* Acquire transaction with a single permit in a thread. Transactions are acquired reentrantly, i.e.
* with respect to transactions already acquired in the thread.
*
* @return the number of acquired permits, identically equal to 1.
*/
int acquireTransaction(@NotNull final Thread thread) {
try (CriticalSection ignored = criticalSection.enter()) {
final int currentThreadPermits = getThreadPermitsToAcquire(thread);
waitForPermits(thread, currentThreadPermits > 0 ? nestedQueue : regularQueue, 1, currentThreadPermits);
}
return 1;
}
use of jetbrains.exodus.core.execution.locks.CriticalSection in project xodus by JetBrains.
the class ReentrantTransactionDispatcher method downgradeTransaction.
/**
* Downgrade transaction (making it holding only 1 permit) that was acquired in a thread with specified permits.
*/
void downgradeTransaction(@NotNull final Thread thread, final int permits) {
if (permits > 1) {
try (CriticalSection ignored = criticalSection.enter()) {
int currentThreadPermits = getThreadPermits(thread);
if (permits > currentThreadPermits) {
throw new ExodusException("Can't release more permits than it was acquired");
}
acquiredPermits -= (permits - 1);
currentThreadPermits -= (permits - 1);
threadPermits.put(thread, currentThreadPermits);
notifyNextWaiters();
}
}
}
use of jetbrains.exodus.core.execution.locks.CriticalSection in project xodus by JetBrains.
the class ReentrantTransactionDispatcher method acquireExclusiveTransaction.
/**
* Acquire exclusive transaction in a thread. Transactions are acquired reentrantly, i.e. with respect
* to transactions already acquired in the thread.
* NB! Nested transaction is never acquired as exclusive.
*
* @return the number of acquired permits.
*/
int acquireExclusiveTransaction(@NotNull final Thread thread) {
try (CriticalSection ignored = criticalSection.enter()) {
final int currentThreadPermits = getThreadPermitsToAcquire(thread);
// if there are no permits acquired in the thread then we can acquire exclusive txn, i.e. all available permits
if (currentThreadPermits == 0) {
waitForPermits(thread, regularQueue, availablePermits, 0);
return availablePermits;
}
waitForPermits(thread, nestedQueue, 1, currentThreadPermits);
}
return 1;
}
use of jetbrains.exodus.core.execution.locks.CriticalSection in project xodus by JetBrains.
the class ReentrantTransactionDispatcher method tryAcquireExclusiveTransaction.
/**
* Wait for exclusive permit during a timeout in milliseconds.
*
* @return number of acquired permits if > 0
*/
private int tryAcquireExclusiveTransaction(@NotNull final Thread thread, final int timeout) {
long nanos = TimeUnit.MILLISECONDS.toNanos(timeout);
try (CriticalSection ignored = criticalSection.enter()) {
if (getThreadPermits(thread) > 0) {
throw new ExodusException("Exclusive transaction can't be nested");
}
final Condition condition = criticalSection.newCondition();
final long currentOrder = acquireOrder++;
regularQueue.put(currentOrder, condition);
while (acquiredPermits > 0 || regularQueue.firstKey() != currentOrder) {
try {
nanos = condition.awaitNanos(nanos);
if (nanos < 0) {
break;
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
break;
}
}
if (acquiredPermits == 0 && regularQueue.firstKey() == currentOrder) {
regularQueue.pollFirstEntry();
acquiredPermits = availablePermits;
threadPermits.put(thread, availablePermits);
return availablePermits;
}
regularQueue.remove(currentOrder);
notifyNextWaiters();
}
return 0;
}
Aggregations