1 11 package org.eclipse.core.internal.jobs; 12 13 import org.eclipse.core.internal.runtime.RuntimeLog; 14 import org.eclipse.core.runtime.*; 15 import org.eclipse.core.runtime.jobs.ISchedulingRule; 16 import org.eclipse.core.runtime.jobs.Job; 17 18 21 class ThreadJob extends Job { 22 26 static final Object notifier = new Object (); 27 28 private final JobManager manager; 29 34 protected boolean acquireRule = false; 35 36 41 boolean isBlocked = false; 42 43 46 protected boolean isRunning = false; 47 48 53 private RuntimeException lastPush = null; 54 59 protected Job realJob; 60 63 private ISchedulingRule[] ruleStack; 64 67 private int top; 68 69 ThreadJob(JobManager manager, ISchedulingRule rule) { 70 super("Implicit Job"); this.manager = manager; 72 setSystem(true); 73 setPriority(Job.INTERACTIVE); 74 ruleStack = new ISchedulingRule[2]; 75 top = -1; 76 setRule(rule); 77 } 78 79 84 private void illegalPop(ISchedulingRule rule) { 85 StringBuffer buf = new StringBuffer ("Attempted to endRule: "); buf.append(rule); 87 if (top >= 0 && top < ruleStack.length) { 88 buf.append(", does not match most recent begin: "); buf.append(ruleStack[top]); 90 } else { 91 if (top < 0) 92 buf.append(", but there was no matching beginRule"); else 94 buf.append(", but the rule stack was out of bounds: " + top); } 96 buf.append(". See log for trace information if rule tracing is enabled."); String msg = buf.toString(); 98 if (JobManager.DEBUG || JobManager.DEBUG_BEGIN_END) { 99 System.out.println(msg); 100 Throwable t = lastPush == null ? new IllegalArgumentException () : lastPush; 101 IStatus error = new Status(IStatus.ERROR, JobManager.PI_JOBS, 1, msg, t); 102 RuntimeLog.log(error); 103 } 104 Assert.isLegal(false, msg); 105 } 106 107 111 private void illegalPush(ISchedulingRule pushRule, ISchedulingRule baseRule) { 112 StringBuffer buf = new StringBuffer ("Attempted to beginRule: "); buf.append(pushRule); 114 buf.append(", does not match outer scope rule: "); buf.append(baseRule); 116 String msg = buf.toString(); 117 if (JobManager.DEBUG) { 118 System.out.println(msg); 119 IStatus error = new Status(IStatus.ERROR, JobManager.PI_JOBS, 1, msg, new IllegalArgumentException ()); 120 RuntimeLog.log(error); 121 } 122 Assert.isLegal(false, msg); 123 124 } 125 126 130 private boolean isCanceled(IProgressMonitor monitor) { 131 try { 132 return monitor.isCanceled(); 133 } catch (RuntimeException e) { 134 IStatus status = new Status(IStatus.ERROR, JobManager.PI_JOBS, JobManager.PLUGIN_ERROR, "ThreadJob.isCanceled", e); RuntimeLog.log(status); 137 } 138 return false; 139 } 140 141 144 synchronized boolean isRunning() { 145 return isRunning; 146 } 147 148 152 ThreadJob joinRun(IProgressMonitor monitor) { 153 if (isCanceled(monitor)) 154 throw new OperationCanceledException(); 155 InternalJob blockingJob = manager.findBlockingJob(this); 157 Thread blocker = blockingJob == null ? null : blockingJob.getThread(); 158 ThreadJob result = this; 159 try { 160 if (manager.getLockManager().aboutToWait(blocker)) 162 return this; 163 try { 164 waitStart(monitor, blockingJob); 165 final Thread currentThread = Thread.currentThread(); 166 while (true) { 167 if (isCanceled(monitor)) 168 throw new OperationCanceledException(); 169 if (manager.runNow(this)) 171 return this; 172 blockingJob = manager.findBlockingJob(this); 174 blocker = blockingJob == null ? null : blockingJob.getThread(); 176 if (blocker == currentThread && blockingJob instanceof ThreadJob) { 177 result = (ThreadJob)blockingJob; 179 result.push(getRule()); 180 result.isBlocked = this.isBlocked; 181 return result; 182 } 183 if (manager.getLockManager().aboutToWait(blocker)) 185 return this; 186 synchronized (notifier) { 188 try { 189 notifier.wait(250); 190 } catch (InterruptedException e) { 191 } 193 } 194 } 195 } finally { 196 if (this == result) 197 waitEnd(monitor); 198 } 199 } finally { 200 manager.getLockManager().aboutToRelease(); 201 } 202 } 203 204 208 boolean pop(ISchedulingRule rule) { 209 if (top < 0 || ruleStack[top] != rule) 210 illegalPop(rule); 211 ruleStack[top--] = null; 212 return top < 0; 213 } 214 215 220 void push(final ISchedulingRule rule) { 221 final ISchedulingRule baseRule = getRule(); 222 if (++top >= ruleStack.length) { 223 ISchedulingRule[] newStack = new ISchedulingRule[ruleStack.length * 2]; 224 System.arraycopy(ruleStack, 0, newStack, 0, ruleStack.length); 225 ruleStack = newStack; 226 } 227 ruleStack[top] = rule; 228 if (JobManager.DEBUG_BEGIN_END) 229 lastPush = (RuntimeException ) new RuntimeException ().fillInStackTrace(); 230 if (baseRule != null && rule != null && !baseRule.contains(rule)) 232 illegalPush(rule, baseRule); 233 } 234 235 239 boolean recycle() { 240 if (getState() != Job.NONE) 242 return false; 243 acquireRule = isRunning = isBlocked = false; 245 realJob = null; 246 setRule(null); 247 setThread(null); 248 if (ruleStack.length != 2) 249 ruleStack = new ISchedulingRule[2]; 250 else 251 ruleStack[0] = ruleStack[1] = null; 252 top = -1; 253 return true; 254 } 255 256 259 public IStatus run(IProgressMonitor monitor) { 260 synchronized (this) { 261 isRunning = true; 262 } 263 return ASYNC_FINISH; 264 } 265 266 270 void setRealJob(Job realJob) { 271 this.realJob = realJob; 272 } 273 274 278 boolean shouldInterrupt() { 279 return realJob == null ? true : !realJob.isSystem(); 280 } 281 282 285 public String toString() { 286 StringBuffer buf = new StringBuffer ("ThreadJob"); buf.append('(').append(realJob).append(',').append('['); 288 for (int i = 0; i <= top && i < ruleStack.length; i++) 289 buf.append(ruleStack[i]).append(','); 290 buf.append(']').append(')'); 291 return buf.toString(); 292 } 293 294 299 private void waitEnd(IProgressMonitor monitor) { 300 final LockManager lockManager = manager.getLockManager(); 301 final Thread currentThread = Thread.currentThread(); 302 if (isRunning()) { 303 lockManager.addLockThread(currentThread, getRule()); 304 lockManager.resumeSuspendedLocks(currentThread); 306 } else { 307 lockManager.removeLockWaitThread(currentThread, getRule()); 309 } 310 } 311 312 318 private void waitStart(IProgressMonitor monitor, InternalJob blockingJob) { 319 manager.getLockManager().addLockWaitThread(Thread.currentThread(), getRule()); 320 isBlocked = true; 321 manager.reportBlocked(monitor, blockingJob); 322 } 323 } | Popular Tags |