|
Lines 41-46
Link Here
|
| 41 |
import org.eclipse.core.runtime.IPath; |
41 |
import org.eclipse.core.runtime.IPath; |
| 42 |
import org.eclipse.core.runtime.IStatus; |
42 |
import org.eclipse.core.runtime.IStatus; |
| 43 |
import org.eclipse.core.runtime.NullProgressMonitor; |
43 |
import org.eclipse.core.runtime.NullProgressMonitor; |
|
|
44 |
import org.eclipse.core.runtime.OperationCanceledException; |
| 44 |
import org.eclipse.core.runtime.Path; |
45 |
import org.eclipse.core.runtime.Path; |
| 45 |
import org.eclipse.core.runtime.Platform; |
46 |
import org.eclipse.core.runtime.Platform; |
| 46 |
import org.eclipse.core.runtime.QualifiedName; |
47 |
import org.eclipse.core.runtime.QualifiedName; |
|
Lines 103-177
Link Here
|
| 103 |
} |
104 |
} |
| 104 |
} |
105 |
} |
| 105 |
|
106 |
|
| 106 |
/** |
107 |
class SharedObject { |
| 107 |
* A Data class to track our shared objects |
|
|
| 108 |
*/ |
| 109 |
static class SharedObject { |
| 110 |
int referenceCountForEdit; |
108 |
int referenceCountForEdit; |
| 111 |
int referenceCountForRead; |
109 |
int referenceCountForRead; |
| 112 |
IStructuredModel theSharedModel; |
110 |
volatile IStructuredModel theSharedModel; |
|
|
111 |
final ILock LOAD_LOCK = Job.getJobManager().newLock(); |
| 113 |
volatile boolean initializing = true; |
112 |
volatile boolean initializing = true; |
| 114 |
volatile boolean doWait = true; |
113 |
volatile boolean doWait = true; |
| 115 |
|
114 |
// The field 'id' is only meant for debug |
| 116 |
SharedObject(IStructuredModel sharedModel) { |
115 |
volatile String id; |
| 117 |
theSharedModel = sharedModel; |
116 |
|
| 118 |
referenceCountForRead = 0; |
117 |
SharedObject(String id) { |
| 119 |
referenceCountForEdit = 0; |
118 |
this.id=id; |
|
|
119 |
// be aware, this lock will leak and cause the deadlock detector to be horrible if we never release it |
| 120 |
LOAD_LOCK.acquire(); |
| 120 |
} |
121 |
} |
| 121 |
|
122 |
|
| 122 |
/** |
123 |
/** |
| 123 |
* Waits until this shared object has been attempted to be loaded. |
124 |
* Waits until this shared object has been attempted to be loaded. The |
| 124 |
* The load is "attempted" because not all loads result in a model. |
125 |
* load is "attempted" because not all loads result in a model. However, |
| 125 |
* However, upon leaving this method, theShareModel variable |
126 |
* upon leaving this method, theShareModel variable is up-to-date. |
| 126 |
* is up-to-date. |
|
|
| 127 |
*/ |
127 |
*/ |
| 128 |
public void waitForLoadAttempt() { |
128 |
public void waitForLoadAttempt() { |
|
|
129 |
Job current = Job.getJobManager().currentJob(); |
| 129 |
boolean interrupted = false; |
130 |
boolean interrupted = false; |
| 130 |
try { |
131 |
try { |
| 131 |
// if we have a rule, then use a polling system with |
132 |
while (initializing) { |
| 132 |
// short-circuit, otherwise use wait/notify |
133 |
if (current!=null) { |
| 133 |
if (Job.getJobManager().currentRule() != null) { |
134 |
current.yieldRule(null); |
| 134 |
while (initializing) { |
|
|
| 135 |
Job.getJobManager().currentJob().yieldRule(null); |
| 136 |
synchronized (this) { |
| 137 |
if (initializing) { |
| 138 |
try { |
| 139 |
wait(WAIT_INTERVAL_MS); |
| 140 |
} |
| 141 |
catch (InterruptedException e) { |
| 142 |
interrupted = true; |
| 143 |
} |
| 144 |
} |
| 145 |
} |
| 146 |
} |
135 |
} |
| 147 |
} |
136 |
try { |
| 148 |
else { |
137 |
loop(); |
| 149 |
synchronized (this) { |
138 |
} catch (InterruptedException e) { |
| 150 |
while (initializing) { |
139 |
interrupted=true; |
| 151 |
try { |
|
|
| 152 |
wait(); |
| 153 |
} |
| 154 |
catch (InterruptedException e) { |
| 155 |
interrupted = true; |
| 156 |
} |
| 157 |
} |
| 158 |
} |
140 |
} |
| 159 |
} |
141 |
} |
| 160 |
} |
142 |
} |
| 161 |
finally { |
143 |
finally { |
| 162 |
if (interrupted) |
144 |
if (interrupted) { |
| 163 |
Thread.currentThread().interrupt(); |
145 |
Thread.currentThread().interrupt(); |
|
|
146 |
} |
| 164 |
} |
147 |
} |
| 165 |
} |
148 |
} |
| 166 |
|
149 |
|
|
|
150 |
private void loop() throws InterruptedException { |
| 151 |
if (initializing) { |
| 152 |
if (LOAD_LOCK.acquire(WAIT_INTERVAL_MS)) { |
| 153 |
// if we got the lock, but initializing is still not true the deadlock detector gave us |
| 154 |
// the lock and caused reentrancy into this critical section. This is invalid and the |
| 155 |
// sign of a cyclical load attempt. In this case, we through an |
| 156 |
// OperationCanceledException in lew of entering a spin-loop. |
| 157 |
if (initializing) { |
| 158 |
LOAD_LOCK.release(); |
| 159 |
throw new OperationCanceledException("Aborted cyclic load attempt for model with id: "+ id); |
| 160 |
} else { |
| 161 |
LOAD_LOCK.release(); |
| 162 |
} |
| 163 |
} |
| 164 |
} |
| 165 |
} |
| 166 |
|
| 167 |
/** |
167 |
/** |
| 168 |
* Flags this model as loaded. All waiting methods on |
168 |
* Flags this model as loaded. All waiting methods on |
| 169 |
* {@link #waitForLoadAttempt()} will proceed after this |
169 |
* {@link #waitForLoadAttempt()} will proceed after this method returns. |
| 170 |
* method returns. |
|
|
| 171 |
*/ |
170 |
*/ |
| 172 |
public synchronized void setLoaded() { |
171 |
public void setLoaded() { |
| 173 |
initializing = false; |
172 |
initializing = false; |
| 174 |
notifyAll(); |
173 |
LOAD_LOCK.release(); |
| 175 |
} |
174 |
} |
| 176 |
} |
175 |
} |
| 177 |
|
176 |
|
|
Lines 239-245
Link Here
|
| 239 |
SharedObject testObject = (SharedObject) fManagedObjects.get(id); |
238 |
SharedObject testObject = (SharedObject) fManagedObjects.get(id); |
| 240 |
if (testObject==null) { |
239 |
if (testObject==null) { |
| 241 |
// null means it's been disposed, we need to do the work to reload it. |
240 |
// null means it's been disposed, we need to do the work to reload it. |
| 242 |
sharedObject = new SharedObject(null); |
241 |
sharedObject = new SharedObject(id); |
| 243 |
fManagedObjects.put(id, sharedObject); |
242 |
fManagedObjects.put(id, sharedObject); |
| 244 |
SYNC.release(); |
243 |
SYNC.release(); |
| 245 |
_doCommonCreateModel(file, id, handler, resolver, rwType, encodingRule, |
244 |
_doCommonCreateModel(file, id, handler, resolver, rwType, encodingRule, |
|
Lines 350-356
Link Here
|
| 350 |
SharedObject testObject = (SharedObject) fManagedObjects.get(id); |
349 |
SharedObject testObject = (SharedObject) fManagedObjects.get(id); |
| 351 |
if (testObject==null) { |
350 |
if (testObject==null) { |
| 352 |
// it was removed ,so lets create it |
351 |
// it was removed ,so lets create it |
| 353 |
sharedObject = new SharedObject(null); |
352 |
sharedObject = new SharedObject(id); |
| 354 |
fManagedObjects.put(id, sharedObject); |
353 |
fManagedObjects.put(id, sharedObject); |
| 355 |
SYNC.release(); |
354 |
SYNC.release(); |
| 356 |
_doCommonCreateModel(inputStream, id, handler, resolver, rwType, |
355 |
_doCommonCreateModel(inputStream, id, handler, resolver, rwType, |
|
Lines 493-499
Link Here
|
| 493 |
SharedObject testObject = (SharedObject) fManagedObjects.get(id); |
492 |
SharedObject testObject = (SharedObject) fManagedObjects.get(id); |
| 494 |
if (testObject==null) { |
493 |
if (testObject==null) { |
| 495 |
// it was removed ,so lets create it |
494 |
// it was removed ,so lets create it |
| 496 |
sharedObject = new SharedObject(null); |
495 |
sharedObject = new SharedObject(id); |
| 497 |
fManagedObjects.put(id, sharedObject); |
496 |
fManagedObjects.put(id, sharedObject); |
| 498 |
|
497 |
|
| 499 |
SYNC.release(); |
498 |
SYNC.release(); |
|
Lines 569-575
Link Here
|
| 569 |
throw new ResourceInUse(); |
568 |
throw new ResourceInUse(); |
| 570 |
} |
569 |
} |
| 571 |
|
570 |
|
| 572 |
sharedObject = new SharedObject(null); |
571 |
sharedObject = new SharedObject(id); |
| 573 |
fManagedObjects.put(id, sharedObject); |
572 |
fManagedObjects.put(id, sharedObject); |
| 574 |
|
573 |
|
| 575 |
} finally { |
574 |
} finally { |
|
Lines 614-620
Link Here
|
| 614 |
SYNC.acquire(); |
613 |
SYNC.acquire(); |
| 615 |
SharedObject testObject = (SharedObject) fManagedObjects.get(id); |
614 |
SharedObject testObject = (SharedObject) fManagedObjects.get(id); |
| 616 |
if (testObject==null) { |
615 |
if (testObject==null) { |
| 617 |
sharedObject = new SharedObject(null); |
616 |
sharedObject = new SharedObject(id); |
| 618 |
fManagedObjects.put(id, sharedObject); |
617 |
fManagedObjects.put(id, sharedObject); |
| 619 |
SYNC.release(); |
618 |
SYNC.release(); |
| 620 |
synchronized(sharedObject) { |
619 |
synchronized(sharedObject) { |
|
Lines 832-838
Link Here
|
| 832 |
if (sharedObject != null) { |
831 |
if (sharedObject != null) { |
| 833 |
throw new ResourceInUse(); |
832 |
throw new ResourceInUse(); |
| 834 |
} |
833 |
} |
| 835 |
sharedObject = new SharedObject(null); |
834 |
sharedObject = new SharedObject(newId); |
| 836 |
fManagedObjects.put(newId,sharedObject); |
835 |
fManagedObjects.put(newId,sharedObject); |
| 837 |
} finally { |
836 |
} finally { |
| 838 |
SYNC.release(); |
837 |
SYNC.release(); |