Bug 571177 - [performance] Avoid sleep for fixed period during spinning

"Thread.sleep(100)" in average waits 50ms too long.

Instead of just sleeping the thread is now notified via synchronization
(only when the condition is fullfilled).

Bug: 571177
Change-Id: I03b345f5f2537d5b8d00bf46fddb42ed1e5ea4b1
Signed-off-by: jkubitz <jkubitz-eclipse@gmx.de>
Reviewed-on: https://git.eclipse.org/r/c/platform/eclipse.platform.runtime/+/176222
Tested-by: Platform Bot <platform-bot@eclipse.org>
Reviewed-by: Andrey Loskutov <loskutov@gmx.de>
diff --git a/bundles/org.eclipse.core.jobs/src/org/eclipse/core/internal/jobs/JobManager.java b/bundles/org.eclipse.core.jobs/src/org/eclipse/core/internal/jobs/JobManager.java
index 3337413..f495334 100644
--- a/bundles/org.eclipse.core.jobs/src/org/eclipse/core/internal/jobs/JobManager.java
+++ b/bundles/org.eclipse.core.jobs/src/org/eclipse/core/internal/jobs/JobManager.java
@@ -948,16 +948,24 @@
 					@Override
 					public void done(IJobChangeEvent event) {
 						//don't remove from list if job is being rescheduled
-						if (!((JobChangeEvent) event).reschedule)
+						if (!((JobChangeEvent) event).reschedule) {
 							jobs.remove(event.getJob());
+							if (jobs.isEmpty()) { // minimal notification
+								synchronized (jobs) {
+									jobs.notifyAll();
+								}
+							}
+						}
 					}
 
 					//update the list of jobs if new ones are started during the join
 					@Override
 					public void running(IJobChangeEvent event) {
 						Job job = event.getJob();
-						if (family == null || job.belongsTo(family))
+						if (family == null || job.belongsTo(family)) {
 							jobs.add(job);
+							// no notification upon increased size
+						}
 					}
 
 					//update the list of jobs if new ones are scheduled during the join
@@ -970,8 +978,10 @@
 						if (isSuspended())
 							return;
 						Job job = event.getJob();
-						if (family == null || job.belongsTo(family))
+						if (family == null || job.belongsTo(family)) {
 							jobs.add(job);
+							// no notification upon increased size
+						}
 					}
 				};
 				addJobChangeListener(listener);
@@ -1005,7 +1015,11 @@
 					throw new OperationCanceledException();
 				//notify hook to service pending syncExecs before falling asleep
 				lockManager.aboutToWait(null);
-				Thread.sleep(100);
+				synchronized (jobs) {
+					if (!jobs.isEmpty()) { // in case we missed a notify outside the synchronized block
+						jobs.wait(100);// Avoid sleep for fixed period by notify / wait
+					}
+				}
 			}
 		} finally {
 			lockManager.aboutToRelease();