Skip to content

Commit

Permalink
Simplify event publication in TargetPlatformService
Browse files Browse the repository at this point in the history
Instead of implementing an asynchronous event dispatching mechanism in
TargetPlatformService, simply use IEventBroker.post().
  • Loading branch information
HannesWell committed Nov 9, 2024
1 parent ee1f4a3 commit b817a85
Showing 1 changed file with 21 additions and 104 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -33,18 +33,14 @@
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceProxy;
import org.eclipse.core.resources.IResourceProxyVisitor;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IPath;
Expand Down Expand Up @@ -100,44 +96,14 @@ public class TargetPlatformService implements ITargetPlatformService {
* The target definition currently being used as the target platform for
* the workspace.
*/
private final AtomicReference<ITargetDefinition> fWorkspaceTarget;
private final AtomicReference<ITargetDefinition> fWorkspaceTarget = new AtomicReference<>();

/**
* vm arguments for default target
*/
private StringBuilder fVMArguments;

private final EventDispatcher eventSendingJob;

/**
* Collects target files in the workspace
*/
static class ResourceProxyVisitor implements IResourceProxyVisitor {

private final List<IResource> fList;

protected ResourceProxyVisitor(List<IResource> list) {
fList = list;
}

/**
* @see org.eclipse.core.resources.IResourceProxyVisitor#visit(org.eclipse.core.resources.IResourceProxy)
*/
@Override
public boolean visit(IResourceProxy proxy) {
if (proxy.getType() == IResource.FILE) {
if (ICoreConstants.TARGET_FILE_EXTENSION.equalsIgnoreCase(IPath.fromOSString(proxy.getName()).getFileExtension())) {
fList.add(proxy.requestResource());
}
return false;
}
return true;
}
}

private TargetPlatformService() {
fWorkspaceTarget = new AtomicReference<>();
eventSendingJob = new EventDispatcher("Sending 'workspace target changed' event", TargetPlatformService.class); //$NON-NLS-1$
}

/**
Expand Down Expand Up @@ -271,21 +237,23 @@ private List<ITargetHandle> findLocalTargetDefinitions() {
* @return all target definition handles in the workspace
*/
private List<WorkspaceFileTargetHandle> findWorkspaceTargetDefinitions() {
List<IResource> files = new ArrayList<>(10);
ResourceProxyVisitor visitor = new ResourceProxyVisitor(files);
List<IFile> files = new ArrayList<>(10);
try {
ResourcesPlugin.getWorkspace().getRoot().accept(visitor, IResource.NONE);
ResourcesPlugin.getWorkspace().getRoot().accept(proxy -> {
if (proxy.getType() == IResource.FILE) {
if (ICoreConstants.TARGET_FILE_EXTENSION
.equalsIgnoreCase(IPath.fromOSString(proxy.getName()).getFileExtension())) {
files.add((IFile) proxy.requestResource());
}
return false;
}
return true;
}, IResource.NONE);
} catch (CoreException e) {
PDECore.log(e);
return new ArrayList<>(0);
}
Iterator<IResource> iter = files.iterator();
List<WorkspaceFileTargetHandle> handles = new ArrayList<>(files.size());
while (iter.hasNext()) {
IFile file = (IFile) iter.next();
handles.add(new WorkspaceFileTargetHandle(file));
return List.of();
}
return handles;
return files.stream().map(WorkspaceFileTargetHandle::new).toList();
}

@Override
Expand Down Expand Up @@ -361,71 +329,20 @@ public synchronized ITargetDefinition getWorkspaceTargetDefinition() throws Core
*/
public void setWorkspaceTargetDefinition(ITargetDefinition target, boolean asyncEvents) {
ITargetDefinition oldTarget = fWorkspaceTarget.getAndSet(target);
boolean changed = !Objects.equals(oldTarget, target);
if (changed) {
if (asyncEvents) {
eventSendingJob.schedule(target);
} else {
notifyTargetChanged(target);
}
if (!Objects.equals(oldTarget, target)) {
notifyEvent(TargetEvents.TOPIC_WORKSPACE_TARGET_CHANGED, target, asyncEvents);
}
}

static void notifyTargetChanged(ITargetDefinition target) {
private static void notifyEvent(String topic, Object data, boolean asyncEvents) {
IEclipseContext context = EclipseContextFactory.getServiceContext(PDECore.getDefault().getBundleContext());
IEventBroker broker = context.get(IEventBroker.class);
if (broker != null) {
broker.send(TargetEvents.TOPIC_WORKSPACE_TARGET_CHANGED, target);
}
}

static class EventDispatcher extends Job {

private final ConcurrentLinkedQueue<ITargetDefinition> queue;
private final Object myFamily;

/**
* @param jobName
* descriptive job name
* @param family
* non null object to control this job execution
**/
public EventDispatcher(String jobName, Object family) {
super(jobName);
Assert.isNotNull(family);
this.myFamily = family;
this.queue = new ConcurrentLinkedQueue<>();
setSystem(true);
}

@Override
public boolean belongsTo(Object family) {
return myFamily == family;
}

@Override
protected IStatus run(IProgressMonitor monitor) {
ITargetDefinition target;
while ((target = queue.poll()) != null && !monitor.isCanceled()) {
notifyTargetChanged(target);
}
if (!queue.isEmpty() && !monitor.isCanceled()) {
// in case actions got faster scheduled then processed
schedule();
}
if (monitor.isCanceled()) {
queue.clear();
return Status.CANCEL_STATUS;
if (asyncEvents) {
broker.post(topic, data);
} else {
broker.send(topic, data);
}
return Status.OK_STATUS;
}

/**
* Enqueue a task asynchronously.
**/
public void schedule(ITargetDefinition target) {
queue.offer(target);
schedule(); // will reschedule if already running
}
}

Expand Down

0 comments on commit b817a85

Please sign in to comment.