EMF Thread Safety

In my past customer project we designed an RCP application that was supposed to monitorartificial-horizon-attitude-indicator and manage a distributed flight simulation. The simulation consists of dozens of independent simulation nodes that interchange messages and signals over a local network.

Basically the RCP application manages a huge and dynamic model graph that reflects all relevant information of the underlying flight simulation. All that information is displayed simultaneously in multiple views and editors.

The domain model is based on EMF and comprises about 100 classes with hundreds of thousands of runtime instances. The application continuously receives network messages on multiple background jobs and updates parts of the domain model accordingly.

Since a flight simulation is a highly dynamic system with dozens of model updates per second, we stumbled upon two major problems:

  • An unresponsive user interface
  • Concurrent domain model modifications

To avoid unresponsive user interfaces you should:

  • Use the SWT.VIRTUAL style for all your viewers
  • Omit EMF touch events
  • Never block the UI Thread
  • Read the post about EMF.Edit performance

EMF models are not thread-safe by default and writing multithreaded applications is not that simple. The more complex our application became, the more often we got concurrent modification exceptions and had problems with filtering and sorting operations.

As you can see in the table below, the only thread-safe operation on EMF instances is reading a single-valued attribute.

Single-Valued Attribute Multi-Valued Attribute
+ Read – Iterate
– Write – Add/Remove

It’s not obvious that writing a single-valued attribute from multiple threads is forbidden. However attaching an EAdapter in one thread while propagating a set event in another thread fires concurrent modification exceptions as well.

There are two established solutions to avoid multithreading problems in EMF.

EMF Transaction

EMF transaction uses transactional editing domains to synchronize read and write operations on different threads. All write operations are triggered by commands that are executed on the domain’s transactional commandstack.


final TransactionalEditingDomain domain = TransactionalEditingDomain.Registry.INSTANCE.getEditingDomain("instanceName");

domain.getCommandStack().execute(AddCommand.create(...));
domain.getCommandStack().execute(RemoveCommand.create(...));

All Read operations have to run in an exclusive context and the result is passed back as follows:

try {

Double r =(Double)editingDomain.runExclusive(new RunnableWithResult.Impl<Double>() {

  @Override
  public void run() {
    setResult(model.getSignals().stream().mapToDouble(s->s.getValue()).sum());
  }

 label.setText("Sum = " +r);

} catch (InterruptedException e) {}

In addition the framework contains several classes for EMF.edit programming.


//EMF.edit support
viever.setContentProvider(new TransactionalAdapterFactoryContentProvider(domain,af);
viever.setLabelProvider(new TransactionalAdapterFactoryLabelProvider(domain,af);

I gave up figuring out how EMF transaction actually is working behind the scenes. It’s really complex and using the framework requires a consequent usage throughout the entire application. While synchronizing write operations using commands is doable, encapsulating all read operations on a shared editing domain ends up in writing many lines of additional boilerplate code. Especially UI related code becomes quite more complex and it’s very likely that team members simply fade out synchronization when just bringing up a simple info dialog that shows parts of your domain model.

That’s why we decided to use a simpler solution.

Model synchronization on the UI Thread

According to the EMF FAQ, EMF itself does not ensure thread-safety in application model implementations. Data structures are unsynchronized, the expectation is that a complete instance of the model (including resources and resource set, if present) should only be accessed by one thread at a time.

By one thread at one time can also be realized by using always the same single thread. An excellent candidate for such a thread is the UI/Display thread.

The advantage of using this thread is that all model operations triggered from inside the UI thread ( e.g. initializing views, databinding, event handlers ) run faultless without any further synchronization. Since more than 80% of all our application code is running in the UI thread we didn’t have to think about concurrency too much.

However all applications require some long running – mostly IO intensive – background operations that affect the application’s domain model. Fortunately a solution for that is really straightforward.

Write operations in background jobs

Below is an example how to modify the domain model in a background job. By the way never use Java threads directly. Prefer higher a level abstraction like the Eclipse jobs API or executor services.

new Job("Model Update") {

   protected IStatus run(IProgressMonitor monitor) {

       //create model in long running operation
	Signal signal = fetchFromWebserviceOrWhatEver();

       //merge instance in UI thread afterwards
	Display.getDefault().syncExec(()->;model.getSignals().add(signal));

	...

After the long running operation has finished, the new model instance has to be merged immediately. Model updates are pretty short running operations and it’s no problem to run them in the UI thread. Actually this thread is idling and waiting for user input most of its time. However using the display object directly is not recommended because not all OSGI bundles should necessarily have dependencies to SWT.

That’s why we used a simple EMFTRansactionHelper utility class that provides methods to modify EMF models thread-safe. In our RCP application the class is initialized on startup as shown below. For headless unit tests running on the server, this class is initialized with another synchronizer.

public Object start(IApplicationContext context) throws Exception {

 Display display = PlatformUI.createDisplay();
 EMFTransactionHelper.setSynchronizer((runnable) ->display.syncExec(runnable));

The previous example can then be written as:

new Job("Model Append") {

@Override
protected IStatus run(IProgressMonitor monitor) {

 Signal signal = ModelFactory.eINSTANCE.createSignal();
 signal.setName(UUID.randomUUID().toString());
 signal.setValue((int) Math.random());

 EMFTransactionHelper.addElementExclusive(model,ModelPackage.Literals.MODEL__SIGNALS, signal);

Read operations in background jobs

Many long running operations only need read access to the domain model. For instance generating reports or PDF documents. Unlike reading single-valued attributes from multiple threads iterating over multi-valued collections in background jobs is really problematic.

One option is cloning (EcoreUtil.copy()) parts of the application model in the UI thread and use the cloned model for background processing.

If cloning is not possible, the collection must be copied synchronized in the job itself. Here is an example:

new Job("Read Only") {

@Override
protected IStatus run(IProgressMonitor monitor) {

  //clone list thread-safe
  List<Signal> cL = EMFTransactionHelper.cloneCollectionExclusive(model.getSignals);		

  //iterate over clone
  cL.forEach(s-> ...)

Demo Application

The video below shows a very simple application that demonstrates both synchronization techniques. Each viewer contains 10.000 model instances that are modified continuously. The sourcecode is available here.

As you can see, the user interface still reacts very smooth. Both solutions have their pros and cons. For our use case the second solution was the better option. For other uses cases EMF transaction might be the better choice.


Virtual containers in tree viewers using EMF.Edit

Maybe you already stumbled upon the problem to display model instances with hundreds or even thousands of child elements in a tree based viewer. Displaying all that children as direct successors of their parent (shown in the figure on the left) is confusing and slows down the UI.

An alternative approach is to hook in virtual folders, that contain a subset of the parent’s child elements instead. This approach is shown in the figure on the right and might be familiar to you since it’s also used in the Eclipse ‘Variables’ view.

If you use EMF.Edit based item providers to display your domain objects read on!

The technique shown here is a slightly modified version of the technique explained in chapter 19.2.3 Adding Non-Model Intermediary View Objects of the standard Eclipse Modeling Framework book.

The source code below is used to display the right tree viewer in the illustration above. It’s usual EMF.Edit programming. The only difference is the usage of a PartitionedContentProvider instead of an AdapterFactoryContentProvider.

You find the implementation of PartitionedContentProvider here. It’s packaged into a plugin but feel free to copy that single class into your own project. Overwrite the method getVirtualFolderSize() to limit the maximum number of container’s direct children. If the number exceeds this limit, virtual folders are hooked in instead. If the virtual folder size is -1 virtual folders are not created.


final AdapterFactory adapterFactory = new ComposedAdapterFactory(ComposedAdapterFactory.Descriptor.Registry.INSTANCE);
domain = new AdapterFactoryEditingDomain(adapterFactory, new BasicCommandStack());

viewer = new TreeViewer(parent, SWT.FLAT | SWT.MULTI);

viewer.addDragSupport(DND.DROP_MOVE, new Transfer[] { LocalTransfer.getInstance() }, new ViewerDragAdapter(viewer));
viewer.addDropSupport(DND.DROP_MOVE, new Transfer[] { LocalTransfer.getInstance() }, new EditingDomainViewerDropAdapter(domain, viewer));
viewer.setLabelProvider(new AdapterFactoryLabelProvider(adapterFactory));

// we limit the maximal child elements for containers to 100
viewer.setContentProvider(new PartitionedContentProvider(adapterFactory) {

       @Override
       protected int getVirtualFolderSize(Object folder) {
          return folder instanceof Container ? 100 : DEFAULT_FOLDER_SIZE;
       }
});


EMF.Edit Performance

Whenever you are using EMF generated models in rich client applications don’t forget to generate appropriate EMF.Edit item providers for all your domain objects. Even if you are using other UI frameworks than SWT, this will definitely save a lot of time. Especially if your user interface has to react on complex model changes. Complex changes are bulked collection modifications that might trigger refresh operations in table or tree based viewers.

If you are not familiar with the basic concepts of EMF and EMF.Edit the What every Eclipse developer should know about EMF blog post is a good starting point.

As you can see in the illustration below, the AdapterFactoryContentProvider reacts on model changes (actually notified by the wrapped AdapterFactory and a specific ModelItemProvider) and refreshes its associated viewer instance.

 

This works pretty fine in most cases. However if your underlying domain model is very ‘nervous’ with dozens of model updates per second (e.g. stock prices, simulation models, sensor data) frequent refresh operations slow down the user interface. In this case you should try to use a delayed content provider illustrated here:

 

 

Instead of performing dozens of smaller viewer updates it could be better to await a couple of model notifications and perform a full refresh operations afterwards.

The snippet shows an exemplary implementation that I currently use in a customers monitoring application for high frequent simulation models. The provider implementation itself is time based. If the first notification arrives, a full viewer refresh is performed after a short delay (Display.timerExec(..)). Notifications arriving in the meantime can be ignored due to the subsequent full viewer refresh. Delays around 500ms feel a little lazy but the UI reacts still as smooth as expected.

 


import java.util.concurrent.atomic.AtomicBoolean;

import org.eclipse.emf.common.notify.AdapterFactory;
import org.eclipse.emf.common.notify.Notification;
import org.eclipse.emf.edit.ui.provider.AdapterFactoryContentProvider;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.swt.widgets.Display;

/**
 * * Use this {@link AdapterFactoryContentProvider} if the viewer's underlying
 * domain model frequently changes and would produce many notification events.
 * In this case it's much more efficient to trigger a full refresh after a short
 * delay.
 */
public class DelayedAdapterFactoryContentProvider extends
		AdapterFactoryContentProvider {

	private static final int DELAY_IN_MS = 500;
	private final AtomicBoolean refresh = new AtomicBoolean(false);
	private Viewer viewer;

	public DelayedAdapterFactoryContentProvider(AdapterFactory adapterFactory) {
		super(adapterFactory);
	}

	@Override
	public void notifyChanged(Notification notification) {

		if (!notification.isTouch() && !refresh.getAndSet(true)) {

			Display.getDefault().asyncExec(new Runnable() {
				@Override
				public void run() {

					Display.getDefault().timerExec(DELAY_IN_MS, new Runnable() {
						@Override
						public void run() {
							refresh.set(false);

							if (viewer.getControl() != null
									&amp;amp;&amp;amp; !viewer.getControl().isDisposed()) {
								viewer.refresh();
							}
						}
					});
				}
			});

		}
	}

	@Override
	public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
		this.viewer = viewer;
		super.inputChanged(viewer, oldInput, newInput);
	}
}