/*******************************************************************************
* Copyright (c) 2005-2008 SAS Institute Inc., ILOG S.A.
* All rights reserved. This program and the accompanying materials
* 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:
* SAS Institute Inc. - initial API and implementation
* ILOG S.A. - initial API and implementation
*******************************************************************************/
package org.eclipse.albireo.core;
import org.eclipse.swt.SWT;
import org.eclipse.swt.SWTException;
import org.eclipse.swt.widgets.Display;
/**
* This class deals with threading between SWT and AWT.
* <p>
* It is customizable through the "replaceable singleton" design pattern.
* <p>
* Note: This class does <em>not</em> combine the two event threads.
*/
public class ThreadingHandler
{
// ========================================================================
// Accessors
private boolean reportingAsyncExecExceptions = true;
/**
* Returns true if exceptions and throwables occurring during asynchronous
* execution should be logged on <code>System.err</code>.
*/
public boolean isReportingAsyncExecExceptions ()
{
return this.reportingAsyncExecExceptions;
}
/**
* Specifies whether exceptions and throwables occurring during asynchronous
* execution should be logged on <code>System.err</code>.
* If <code>true</code>, the exception will be shown on the console.
* If <code>false</code>, the only way to see the exception is
* <ol>
* <li>to be in an application that provides the "Error Log" view,</li>
* <li>to open the "Error Log" view,</li>
* <li>to look at the event details of all "unhandled event loop
* exceptions".</li>
* </ol>
* The default is <code>true</code>.
*/
public void setReportingAsyncExecExceptions ( final boolean doReporting )
{
this.reportingAsyncExecExceptions = doReporting;
}
// ========================================================================
// Overridable API
/**
* Executes the given <code><var>task</var></code> in the given display's
* thread.
* <p>Note: <code>Throwable</code>s thrown by <code><var>task</var></code>
* will not be displayed. If you want them to be displayed, use a try/catch
* block with <code>printStackTrace()</code> inside
* <code><var>task</var></code> yourself.
*
* @throws SWTException <ul>
* <li>ERROR_DEVICE_DISPOSED - if the display has been disposed</li>
* </ul>
*/
public void asyncExec ( final Display display, final Runnable task )
{
final Runnable final_task;
if ( isReportingAsyncExecExceptions () )
{
final_task = new Runnable () {
public void run ()
{
try
{
task.run ();
}
catch ( final RuntimeException e )
{
e.printStackTrace ();
throw e;
}
catch ( final Error e )
{
e.printStackTrace ();
throw e;
}
}
};
}
else
{
final_task = task;
}
try
{
display.asyncExec ( final_task );
}
catch ( final NullPointerException e )
{
// Workaround for wrong order of actions inside Display.dispose().
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=216346
// http://dev.eclipse.org/newslists/news.eclipse.platform.swt/msg30856.html
final StackTraceElement[] stack = e.getStackTrace ();
if ( stack.length > 0 && "org.eclipse.swt.widgets.Display".equals ( stack[0].getClassName () ) && "asyncExec".equals ( stack[0].getMethodName () ) )
{
final SWTException swte = new SWTException ( SWT.ERROR_DEVICE_DISPOSED );
swte.throwable = e;
throw swte;
}
else
{
throw e;
}
}
}
// ========================================================================
// Singleton design pattern
private static ThreadingHandler theHandler = new ThreadingHandler ();
/**
* Returns the currently active singleton of this class.
*/
public static ThreadingHandler getInstance ()
{
return theHandler;
}
/**
* Replaces the singleton of this class.
* @param instance An instance of this class or of a customized subclass.
*/
public static void setInstance ( final ThreadingHandler instance )
{
theHandler = instance;
}
}