Methods Summary |
---|
public synchronized void | acquire()Wait for all threads except the active thread.
If the active thread just increament the depth.
This should be called before entering a critical section.
this.acquire(false);
|
public synchronized void | acquire(boolean forMerge)Wait for all threads except the active thread.
If the active thread just increament the depth.
This should be called before entering a critical section.
called with true from the merge process, if true then the refresh will not refresh the object
while (!((getActiveThread() == Thread.currentThread()) || ((getActiveThread() == null) && (getNumberOfReaders() == 0)))) {
// This must be in a while as multiple threads may be released, or another thread may rush the acquire after one is released.
try {
setNumberOfWritersWaiting(getNumberOfWritersWaiting() + 1);
wait();
setNumberOfWritersWaiting(getNumberOfWritersWaiting() - 1);
} catch (InterruptedException exception) {
throw ConcurrencyException.waitWasInterrupted(exception.getMessage());
}
}
if (getActiveThread() == null) {
setActiveThread(Thread.currentThread());
}
setIsLockedByMergeManager(forMerge);
setDepth(getDepth() + 1);
|
public void | acquireDeferredLock()Add deferred lock into a hashtable to avoid deadlock
Thread currentThread = Thread.currentThread();
DeferredLockManager lockManager = getDeferredLockManager(currentThread);
if (lockManager == null) {
lockManager = new DeferredLockManager();
putDeferredLock(currentThread, lockManager);
}
lockManager.incrementDepth();
synchronized (this) {
while (!(getNumberOfReaders() == 0)) {
// There are readers of this object, wait until they are done before determining if
//there are any other writers. If not we will wait on the readers for acquire. If another
//thread is also waiting on the acquire then a deadlock could occur. See bug 3049635
//We could release all active locks before relesing defered but the object may not be finished building
//we could make the readers get a hard lock, but then we would just build a defered lock even though
//the object is not being built.
try {
setNumberOfWritersWaiting(getNumberOfWritersWaiting() + 1);
wait();
setNumberOfWritersWaiting(getNumberOfWritersWaiting() - 1);
} catch (InterruptedException exception) {
throw ConcurrencyException.waitWasInterrupted(exception.getMessage());
}
}
if ((getActiveThread() == currentThread) || (!isAcquired())) {
lockManager.addActiveLock(this);
acquire();
} else {
lockManager.addDeferredLock(this);
Object[] params = new Object[2];
params[0] = this.getOwnerCacheKey().getObject();
params[1] = currentThread.getName();
AbstractSessionLog.getLog().log(SessionLog.FINER, "acquiring_deferred_lock", params, true);
}
}
|
public synchronized boolean | acquireNoWait()If the lock is not acquired allready acquire it and return true.
If it has been acquired allready return false
Added for CR 2317
if (!isAcquired() || getActiveThread() == Thread.currentThread()) {
//if I own the lock increment depth
acquire(false);
return true;
} else {
return false;
}
|
public synchronized boolean | acquireNoWait(boolean forMerge)If the lock is not acquired allready acquire it and return true.
If it has been acquired allready return false
Added for CR 2317
called with true from the merge process, if true then the refresh will not refresh the object
if (!isAcquired() || getActiveThread() == Thread.currentThread()) {
//if I own the lock increment depth
acquire(forMerge);
return true;
} else {
return false;
}
|
public synchronized void | acquireReadLock()Wait on any writer.
Allow concurrent reads.
// Cannot check for starving writers as will lead to deadlocks.
while (!((getActiveThread() == Thread.currentThread()) || (getActiveThread() == null))) {
try {
wait();
} catch (InterruptedException exception) {
throw ConcurrencyException.waitWasInterrupted(exception.getMessage());
}
}
setNumberOfReaders(getNumberOfReaders() + 1);
|
public synchronized boolean | acquireReadLockNoWait()If this is acquired return false otherwise acquire readlock and return true
if (!isAcquired()) {
acquireReadLock();
return true;
} else {
return false;
}
|
public void | checkReadLock()Check the lock state, if locked, acquire and release a read lock.
This optimizes out the normal read-lock check if not locked.
// If it is not locked, then just return.
if (getActiveThread() == null) {
return;
}
acquireReadLock();
releaseReadLock();
|
public java.lang.Thread | getActiveThread()Return the active thread.
return activeThread;
|
public static synchronized oracle.toplink.essentials.internal.helper.DeferredLockManager | getDeferredLockManager(java.lang.Thread thread)Return the deferred lock manager from the thread
return (DeferredLockManager)getDeferredLockManagers().get(thread);
|
protected static java.util.Hashtable | getDeferredLockManagers()Return the deferred lock manager hashtable (thread - DeferredLockManager).
if (deferredLockManagers == null) {
deferredLockManagers = new Hashtable(50);
}
return deferredLockManagers;
|
public int | getDepth()Return the current depth of the active thread.
return depth;
|
public int | getNumberOfReaders()Number of writer that want the lock.
This is used to ensure that a writer is not starved.
return numberOfReaders;
|
public int | getNumberOfWritersWaiting()Number of writers that want the lock.
This is used to ensure that a writer is not starved.
return numberOfWritersWaiting;
|
public oracle.toplink.essentials.internal.identitymaps.CacheKey | getOwnerCacheKey()Returns the owner cache key for this concurrency manager
return this.ownerCacheKey;
|
public boolean | isAcquired()Return if a thread has aquire this manager.
return depth > 0;
|
public static synchronized boolean | isBuildObjectOnThreadComplete(java.lang.Thread thread, oracle.toplink.essentials.internal.helper.IdentityHashtable recursiveSet)Check if the deferred locks of a thread are all released
if (recursiveSet.containsKey(thread)) {
return true;
}
recursiveSet.put(thread, thread);
DeferredLockManager lockManager = getDeferredLockManager(thread);
if (lockManager == null) {
return true;
}
Vector deferredLocks = lockManager.getDeferredLocks();
for (Enumeration deferredLocksEnum = deferredLocks.elements();
deferredLocksEnum.hasMoreElements();) {
ConcurrencyManager deferedLock = (ConcurrencyManager)deferredLocksEnum.nextElement();
Thread activeThread = null;
if (deferedLock.isAcquired()) {
activeThread = deferedLock.getActiveThread();
// the active thread may be set to null at anypoint
// if added for CR 2330
if (activeThread != null) {
DeferredLockManager currentLockManager = getDeferredLockManager(activeThread);
if (currentLockManager == null) {
return false;
} else if (currentLockManager.isThreadComplete()) {
activeThread = deferedLock.getActiveThread();
// The lock may suddenly finish and no longer have an active thread.
if (activeThread != null) {
if (!isBuildObjectOnThreadComplete(activeThread, recursiveSet)) {
return false;
}
}
} else {
return false;
}
}
}
}
return true;
|
public boolean | isLockedByMergeManager()INTERNAL:
Used byt the refresh process to determine if this concurrency manager is locked by
the merge process. If it is then the refresh should not refresh the object
return this.lockedByMergeManager;
|
public boolean | isNested()Return if this manager is within a nested aquire.
return depth > 1;
|
public synchronized void | putDeferredLock(java.lang.Thread thread, oracle.toplink.essentials.internal.helper.DeferredLockManager lockManager)
getDeferredLockManagers().put(thread, lockManager);
|
public synchronized void | release()Decrement the depth for the active thread.
Assume the current thread is the active one.
Raise an error if the depth become < 0.
The notify will release the first thread waiting on the object,
if no threads are waiting it will do nothing.
if (getDepth() == 0) {
throw ConcurrencyException.signalAttemptedBeforeWait();
} else {
setDepth(getDepth() - 1);
}
if (getDepth() == 0) {
setActiveThread(null);
setIsLockedByMergeManager(false);
notifyAll();
}
|
public void | releaseDeferredLock()Release the deferred lock.
This uses a deadlock detection and resoultion algorthm to avoid cache deadlocks.
The deferred lock manager keeps track of the lock for a thread, so that other
thread know when a deadlock has occured and can resolve it.
Thread currentThread = Thread.currentThread();
DeferredLockManager lockManager = getDeferredLockManager(currentThread);
if (lockManager == null) {
return;
}
int depth = lockManager.getThreadDepth();
if (depth > 1) {
lockManager.decrementDepth();
return;
}
// If the set is null or empty, means there is no deferred lock for this thread, return.
if (!lockManager.hasDeferredLock()) {
lockManager.releaseActiveLocksOnThread();
removeDeferredLockManager(currentThread);
return;
}
lockManager.setIsThreadComplete(true);
// Thread have three stages, one where they are doing work (i.e. building objects)
// two where they are done their own work but may be waiting on other threads to finish their work,
// and a third when they and all the threads they are waiting on are done.
// This is essentially a busy wait to determine if all the other threads are done.
while (true) {
// 2612538 - the default size of IdentityHashtable (32) is appropriate
IdentityHashtable recursiveSet = new IdentityHashtable();
if (isBuildObjectOnThreadComplete(currentThread, recursiveSet)) {// Thread job done.
lockManager.releaseActiveLocksOnThread();
removeDeferredLockManager(currentThread);
Object[] params = new Object[1];
params[0] = currentThread.getName();
AbstractSessionLog.getLog().log(SessionLog.FINER, "deferred_locks_released", params, true);
return;
} else {// Not done yet, wait and check again.
try {
Thread.sleep(10);
} catch (InterruptedException ignoreAndContinue) {
}
}
}
|
public synchronized void | releaseReadLock()Decrement the number of readers.
Used to allow concurrent reads.
if (getNumberOfReaders() == 0) {
throw ConcurrencyException.signalAttemptedBeforeWait();
} else {
setNumberOfReaders(getNumberOfReaders() - 1);
}
if (getNumberOfReaders() == 0) {
notifyAll();
}
|
public static synchronized oracle.toplink.essentials.internal.helper.DeferredLockManager | removeDeferredLockManager(java.lang.Thread thread)Remove the deferred lock manager for the thread
return (DeferredLockManager)getDeferredLockManagers().remove(thread);
|
public void | setActiveThread(java.lang.Thread activeThread)Set the active thread.
this.activeThread = activeThread;
|
protected void | setDepth(int depth)Set the current depth of the active thread.
this.depth = depth;
|
public void | setIsLockedByMergeManager(boolean state)INTERNAL:
Used by the mergemanager to let the read know not to refresh this object as it is being
loaded by the merge process.
this.lockedByMergeManager = state;
|
protected void | setNumberOfReaders(int numberOfReaders)Track the number of readers.
this.numberOfReaders = numberOfReaders;
|
protected void | setNumberOfWritersWaiting(int numberOfWritersWaiting)Number of writers that want the lock.
This is used to ensure that a writer is not starved.
this.numberOfWritersWaiting = numberOfWritersWaiting;
|
public java.lang.String | toString()Print the nested depth.
Object[] args = { new Integer(getDepth()) };
return Helper.getShortClassName(getClass()) + ToStringLocalization.buildMessage("nest_level", args);
|