diff options
author | Eugene Ostroukhov | 2012-05-11 22:40:47 +0000 |
---|---|---|
committer | Pawel Piech | 2012-05-14 21:29:06 +0000 |
commit | 03d1253f689c45fcc963eff82837595a1e12ce73 (patch) | |
tree | 23a063f34cf675012f7a50f889bb39355ec89aef | |
parent | d5cb9f4f8ff821d26f813d438f9d9df56607927e (diff) | |
download | org.eclipse.cdt-03d1253f689c45fcc963eff82837595a1e12ce73.tar.gz org.eclipse.cdt-03d1253f689c45fcc963eff82837595a1e12ce73.tar.xz org.eclipse.cdt-03d1253f689c45fcc963eff82837595a1e12ce73.zip |
Bug 379317 - This change coalesces runnables into one.
This improves perceived performance as repaints are not interleaved with
updates.
Change-Id: If9674e45adf1aa5b4d8530e22dfcd494d228f329
Reviewed-on: https://git.eclipse.org/r/5956
Reviewed-by: Pawel Piech <pawel.piech@windriver.com>
IP-Clean: Pawel Piech <pawel.piech@windriver.com>
Tested-by: Pawel Piech <pawel.piech@windriver.com>
-rw-r--r-- | dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/ui/concurrent/SimpleDisplayExecutor.java | 80 |
1 files changed, 61 insertions, 19 deletions
diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/ui/concurrent/SimpleDisplayExecutor.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/ui/concurrent/SimpleDisplayExecutor.java index a6fe2ec256d..e4a12bdf48c 100644 --- a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/ui/concurrent/SimpleDisplayExecutor.java +++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/ui/concurrent/SimpleDisplayExecutor.java @@ -4,15 +4,18 @@ * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html - * + * * Contributors: * Wind River Systems - initial API and implementation + * NVIDIA - coalesce runnable in the single event loop iteration *******************************************************************************/ package org.eclipse.cdt.dsf.ui.concurrent; import java.util.Collections; import java.util.HashMap; +import java.util.LinkedList; import java.util.Map; +import java.util.Queue; import java.util.concurrent.Executor; import java.util.concurrent.RejectedExecutionException; @@ -22,13 +25,13 @@ import org.eclipse.swt.SWTException; import org.eclipse.swt.widgets.Display; /** - * A simple executor which uses the display thread to run the submitted + * A simple executor which uses the display thread to run the submitted * runnables. It only implements the {@link Executor}, and NOT the more - * sophisticated {@link DsfExecutor} (which extends - * {@link java.util.concurrent.ScheduledExecutorService}). However, this + * sophisticated {@link DsfExecutor} (which extends + * {@link java.util.concurrent.ScheduledExecutorService}). However, this * implementation is much more efficient than DisplayDsfExecutor as it does * not use a separate thread or maintain its own queue. - * + * * @since 1.0 */ public class SimpleDisplayExecutor implements Executor{ @@ -36,13 +39,13 @@ public class SimpleDisplayExecutor implements Executor{ * Internal mapping of display objects to executors. */ private static Map<Display, SimpleDisplayExecutor> fExecutors = Collections.synchronizedMap( new HashMap<Display, SimpleDisplayExecutor>() ); - + /** * Factory method for display executors. * @param display Display to create an executor for. * @return The new (or re-used) executor. */ - public static SimpleDisplayExecutor getSimpleDisplayExecutor(Display display) { + public static SimpleDisplayExecutor getSimpleDisplayExecutor(final Display display) { synchronized (fExecutors) { SimpleDisplayExecutor executor = fExecutors.get(display); if (executor == null) { @@ -52,26 +55,65 @@ public class SimpleDisplayExecutor implements Executor{ return executor; } } - + /** - * The display class used by this executor to execute the submitted runnables. + * The display class used by this executor to execute the submitted runnables. */ private final Display fDisplay; - - private SimpleDisplayExecutor(Display display) { + /** + * Runnables waiting for the UI loop iteration + */ + private Queue<Runnable> runnables; + + private SimpleDisplayExecutor(final Display display) { fDisplay = display; } @Override - public void execute(Runnable command) { - try { - fDisplay.asyncExec(command); - } catch (SWTException e) { - if (e.code == SWT.ERROR_DEVICE_DISPOSED) { - throw new RejectedExecutionException("Display " + fDisplay + " is disposed", e); //$NON-NLS-1$ //$NON-NLS-2$ - } else { - throw e; + public void execute(final Runnable command) { + final boolean needsPosting = enqueue(command); + if (needsPosting) { + try { + fDisplay.asyncExec(new Runnable() { + @Override + public void run() { + runInSwtThread(); + } + }); + } catch (final SWTException e) { + if (e.code == SWT.ERROR_DEVICE_DISPOSED) { + throw new RejectedExecutionException("Display " + fDisplay + " is disposed", e); //$NON-NLS-1$ //$NON-NLS-2$ + } else { + throw e; + } } } } + + private synchronized boolean enqueue(final Runnable runnable) { + boolean needsPosting = false; + if (runnables == null) { + runnables = new LinkedList<Runnable>(); + needsPosting = true; + } + runnables.offer(runnable); + return needsPosting; + } + + private synchronized Runnable getNextRunnable() { + final Runnable runnable = runnables.poll(); + if (runnable == null) { + runnables = null; + return null; + } else { + return runnable; + } + } + + protected void runInSwtThread() { + Runnable runnable; + while ((runnable = getNextRunnable()) != null) { + runnable.run(); + } + } } |