Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Simplify event publication in TargetPlatformService #1466

Merged
merged 1 commit into from
Nov 9, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading