/*******************************************************************************
- * Copyright (c) 2013, 2015 École Polytechnique de Montréal
+ * Copyright (c) 2013, 2016 École Polytechnique de Montréal
*
* 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:
- * Geneviève Bastien - Initial API and implementation
*******************************************************************************/
package org.eclipse.tracecompass.tmf.tests.stubs.analysis;
import static org.eclipse.tracecompass.common.core.NonNullUtils.checkNotNull;
+import java.util.concurrent.locks.Condition;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
+
import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.tracecompass.statesystem.core.ITmfStateSystemBuilder;
import org.eclipse.tracecompass.statesystem.core.exceptions.AttributeNotFoundException;
import org.eclipse.tracecompass.statesystem.core.exceptions.StateValueTypeException;
*/
public class TestStateSystemProvider extends AbstractTmfStateProvider {
+ /**
+ * This interface allows unit tests to provide only the event handling part
+ * of the state provider, without having to extend the analysis and the
+ * classes
+ */
+ @FunctionalInterface
+ public static interface TestStateProviderHandler {
+ /**
+ * Handles the event
+ *
+ * @param ss
+ * The state system builder
+ * @param event
+ * The event to handler
+ * @return <code>true</code> if everything went fine, or <code>false</code> to cancel
+ */
+ boolean eventHandle(@NonNull ITmfStateSystemBuilder ss, ITmfEvent event);
+ }
+
private static final int VERSION = 1;
- private final String fString = "[]";
- private int fCount = 0;
+ private static final String fString = "[]";
+ private static int fCount = 0;
+ private static final @NonNull TestStateProviderHandler DEFAULT_HANDLER = (ss, event) -> {
+ /* Just need something to fill the state system */
+ if (fString.equals(event.getContent().getValue())) {
+ try {
+ int quarkId = ss.getQuarkAbsoluteAndAdd("String");
+ int quark = ss.getQuarkRelativeAndAdd(quarkId, fString);
+ ss.modifyAttribute(event.getTimestamp().getValue(), TmfStateValue.newValueInt(fCount++), quark);
+ } catch (TimeRangeException | AttributeNotFoundException | StateValueTypeException e) {
+
+ }
+ }
+ return true;
+ };
+ private static @NonNull TestStateProviderHandler sfHandler = DEFAULT_HANDLER;
+
+ /**
+ * Set the event handler for the state provider
+ *
+ * @param handler
+ * The class containing the event handler for this state provider
+ */
+ public static void setEventHandler(TestStateProviderHandler handler) {
+ if (handler == null) {
+ sfHandler = DEFAULT_HANDLER;
+ return;
+ }
+ sfHandler = handler;
+ }
+
+ private final Lock fLock = new ReentrantLock();
+ private @Nullable Condition fNextEventSignal = null;
/**
* Constructor
@Override
protected void eventHandle(ITmfEvent event) {
ITmfStateSystemBuilder ss = checkNotNull(getStateSystemBuilder());
+ sfHandler.eventHandle(ss, event);
+ }
- /* Just need something to fill the state system */
- if (fString.equals(event.getContent().getValue())) {
- try {
- int quarkId = ss.getQuarkAbsoluteAndAdd("String");
- int quark = ss.getQuarkRelativeAndAdd(quarkId, fString);
- ss.modifyAttribute(event.getTimestamp().getValue(), TmfStateValue.newValueInt(fCount++), quark);
- } catch (TimeRangeException e) {
- } catch (AttributeNotFoundException e) {
- } catch (StateValueTypeException e) {
+ @Override
+ public void processEvent(@NonNull ITmfEvent event) {
+ fLock.lock();
+ try {
+ Condition cond = fNextEventSignal;
+ if (cond != null) {
+ cond.await();
+ }
+ } catch (InterruptedException e) {
+
+ } finally {
+ super.processEvent(event);
+ fLock.unlock();
+ }
+ }
+
+ /**
+ * Set the processing of event to be one event at a time instead of the
+ * default behavior. It will block until the next call to
+ * {@link #signalNextEvent()} method call.
+ *
+ * @param throttleEvent
+ * Whether to wait for a signal to process the next event
+ */
+ public void setThrottling(boolean throttleEvent) {
+ fLock.lock();
+ try {
+ if (throttleEvent) {
+ Condition cond = fNextEventSignal;
+ // If called for the first time, create a condition
+ if (cond == null) {
+ cond = fLock.newCondition();
+ fNextEventSignal = cond;
+ }
+
+ } else {
+ Condition cond = fNextEventSignal;
+ if (cond != null) {
+ fNextEventSignal = null;
+ cond.signalAll();
+ }
+ }
+ } finally {
+ fLock.unlock();
+ }
+
+ }
+ /**
+ * Signal for the next event to be processed. Calling this method makes
+ * sense only if {@link #setThrottling(boolean)} has been set to true
+ */
+ public void signalNextEvent() {
+ fLock.lock();
+ try {
+ Condition cond = fNextEventSignal;
+ if (cond != null) {
+ cond.signalAll();
}
+ } finally {
+ fLock.unlock();
}
}