mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-07-08 17:45:24 +02:00
Make Mutex thread-safe by doing IProgressMonitor queries outside synchronized
This commit is contained in:
parent
e892da770b
commit
d40a6c11ff
1 changed files with 79 additions and 59 deletions
|
@ -55,58 +55,72 @@ public class Mutex {
|
||||||
* @param timeout Maximum wait time given in milliseconds.
|
* @param timeout Maximum wait time given in milliseconds.
|
||||||
* @return <code>true</code> if the lock was obtained successfully.
|
* @return <code>true</code> if the lock was obtained successfully.
|
||||||
*/
|
*/
|
||||||
public synchronized boolean waitForLock(IProgressMonitor monitor, long timeout) {
|
public boolean waitForLock(IProgressMonitor monitor, long timeout) {
|
||||||
if (Thread.interrupted()) {
|
if (Thread.interrupted()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (fLocked) {
|
final Thread myself = Thread.currentThread();
|
||||||
//need to wait for the lock.
|
synchronized(fWaitQueue) {
|
||||||
boolean canceled = false;
|
if (!fLocked) {
|
||||||
final Thread myself = Thread.currentThread();
|
//acquire the lock immediately.
|
||||||
try {
|
fLocked = true;
|
||||||
fWaitQueue.add(myself);
|
return true;
|
||||||
|
} else {
|
||||||
|
fWaitQueue.add(myself);
|
||||||
Activator.trace("Mutex: added "+myself+", size="+fWaitQueue.size()); //$NON-NLS-1$ //$NON-NLS-2$
|
Activator.trace("Mutex: added "+myself+", size="+fWaitQueue.size()); //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
long start = System.currentTimeMillis();
|
|
||||||
long timeLeft = timeout;
|
|
||||||
long pollTime = (monitor!=null) ? 1000 : timeLeft;
|
|
||||||
long nextProgressUpdate = start+500;
|
|
||||||
while (timeLeft>0 && !canceled) {
|
|
||||||
try {
|
|
||||||
wait(timeLeft > pollTime ? pollTime : timeLeft);
|
|
||||||
Activator.trace("Mutex: wakeup "+myself+" ?"); //$NON-NLS-1$ //$NON-NLS-2$
|
|
||||||
//I'm still in the list, nobody is allowed to take me out!
|
|
||||||
//assert !fWaitQueue.isEmpty();
|
|
||||||
if (!fLocked && fWaitQueue.get(0) == myself) {
|
|
||||||
break; //gee it's my turn!
|
|
||||||
}
|
|
||||||
long curTime = System.currentTimeMillis();
|
|
||||||
timeLeft = start + timeout - curTime;
|
|
||||||
if (monitor!=null) {
|
|
||||||
//TODO put the calls to the progress monitor out
|
|
||||||
//of the synchronized{}
|
|
||||||
canceled = monitor.isCanceled();
|
|
||||||
if (!canceled && (curTime>nextProgressUpdate)) {
|
|
||||||
monitor.worked(1);
|
|
||||||
nextProgressUpdate+=1000;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch(InterruptedException e) {
|
|
||||||
canceled = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
fWaitQueue.remove(myself);
|
|
||||||
Activator.trace("Mutex: removed "+myself+", size="+fWaitQueue.size()); //$NON-NLS-1$ //$NON-NLS-2$
|
|
||||||
}
|
|
||||||
if (fLocked || canceled) {
|
|
||||||
//we were not able to acquire the lock due to an exception,
|
|
||||||
//or because the wait was canceled.
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//acquire the lock myself now.
|
//need to wait for the lock.
|
||||||
fLocked = true;
|
boolean lockAcquired = false;
|
||||||
return true;
|
try {
|
||||||
|
long start = System.currentTimeMillis();
|
||||||
|
long timeLeft = timeout;
|
||||||
|
long pollTime = (monitor!=null) ? 1000 : timeLeft;
|
||||||
|
long nextProgressUpdate = start+500;
|
||||||
|
boolean canceled = false;
|
||||||
|
while (timeLeft>0 && !canceled && !lockAcquired) {
|
||||||
|
//is it my turn yet? Check wait queue and wait
|
||||||
|
synchronized(fWaitQueue) {
|
||||||
|
if (!fLocked && fWaitQueue.get(0) == myself) {
|
||||||
|
fWaitQueue.remove(0);
|
||||||
|
Activator.trace("Mutex: SUCCESS, removed "+myself+", size="+fWaitQueue.size()); //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
|
fLocked = true;
|
||||||
|
lockAcquired = true;
|
||||||
|
} else {
|
||||||
|
fWaitQueue.wait(timeLeft > pollTime ? pollTime : timeLeft);
|
||||||
|
if (!fLocked && fWaitQueue.get(0) == myself) {
|
||||||
|
fWaitQueue.remove(0);
|
||||||
|
Activator.trace("Mutex: SUCCESS, removed "+myself+", size="+fWaitQueue.size()); //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
|
fLocked = true;
|
||||||
|
lockAcquired = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!lockAcquired) {
|
||||||
|
//Need to continue waiting
|
||||||
|
Activator.trace("Mutex: wakeup "+myself+" ?"); //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
|
long curTime = System.currentTimeMillis();
|
||||||
|
timeLeft = start + timeout - curTime;
|
||||||
|
if (monitor!=null) {
|
||||||
|
canceled = monitor.isCanceled();
|
||||||
|
if (!canceled && (curTime>nextProgressUpdate)) {
|
||||||
|
monitor.worked(1);
|
||||||
|
nextProgressUpdate+=1000;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch(InterruptedException e) {
|
||||||
|
//canceled waiting -> no lock aquired
|
||||||
|
} finally {
|
||||||
|
if (!lockAcquired) {
|
||||||
|
synchronized(fWaitQueue) {
|
||||||
|
fWaitQueue.remove(myself);
|
||||||
|
Activator.trace("Mutex: FAIL, removed "+myself+", size="+fWaitQueue.size()); //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return lockAcquired;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -115,12 +129,14 @@ public class Mutex {
|
||||||
* May only be called by the same thread that originally acquired
|
* May only be called by the same thread that originally acquired
|
||||||
* the Mutex.
|
* the Mutex.
|
||||||
*/
|
*/
|
||||||
public synchronized void release() {
|
public void release() {
|
||||||
fLocked=false;
|
synchronized(fWaitQueue) {
|
||||||
if (!fWaitQueue.isEmpty()) {
|
fLocked=false;
|
||||||
Object nextOneInQueue = fWaitQueue.get(0);
|
if (!fWaitQueue.isEmpty()) {
|
||||||
Activator.trace("Mutex: releasing "+nextOneInQueue); //$NON-NLS-1$
|
Object nextOneInQueue = fWaitQueue.get(0);
|
||||||
notifyAll();
|
Activator.trace("Mutex: releasing "+nextOneInQueue); //$NON-NLS-1$
|
||||||
|
fWaitQueue.notifyAll();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -128,8 +144,10 @@ public class Mutex {
|
||||||
* Return this Mutex's lock status.
|
* Return this Mutex's lock status.
|
||||||
* @return <code>true</code> if this mutex is currently acquired by a thread.
|
* @return <code>true</code> if this mutex is currently acquired by a thread.
|
||||||
*/
|
*/
|
||||||
public synchronized boolean isLocked() {
|
public boolean isLocked() {
|
||||||
return fLocked;
|
synchronized(fWaitQueue) {
|
||||||
|
return fLocked;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -139,11 +157,13 @@ public class Mutex {
|
||||||
* This should be called if the resource that the Threads are
|
* This should be called if the resource that the Threads are
|
||||||
* contending for, becomes unavailable for some other reason.
|
* contending for, becomes unavailable for some other reason.
|
||||||
*/
|
*/
|
||||||
public synchronized void interruptAll() {
|
public void interruptAll() {
|
||||||
Iterator it = fWaitQueue.iterator();
|
synchronized(fWaitQueue) {
|
||||||
while (it.hasNext()) {
|
Iterator it = fWaitQueue.iterator();
|
||||||
Thread aThread = (Thread)it.next();
|
while (it.hasNext()) {
|
||||||
aThread.interrupt();
|
Thread aThread = (Thread)it.next();
|
||||||
|
aThread.interrupt();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue