blob: fff7d2069b3b283de6ff8bf0df4c8f3a68ecbf8a [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 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 2.0 which
* accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*******************************************************************************/
package org.eclipse.tracecompass.tmf.core.statesystem;
import java.util.ArrayDeque;
import java.util.PriorityQueue;
import java.util.Queue;
import java.util.Set;
import java.util.TreeSet;
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.tracecompass.statesystem.core.ITmfStateSystemBuilder;
/**
* This class allows to recycle state system attributes. Instead of creating a
* lot of short-lived attributes, it is sometimes useful to re-use an attribute
* (and its whole sub-tree) that was previously used and is no longer required.
* This class keeps a list of children attributes of a base quark and grows that
* list as needed.
*
* @author Geneviève Bastien
* @since 2.0
*/
public class TmfAttributePool {
private final ITmfStateSystemBuilder fSs;
private final Integer fBaseQuark;
private final Queue<@Nullable Integer> fAvailableQuarks;
private final Set<Integer> fQuarksInUse = new TreeSet<>();
private int fCount = 0;
/**
* The type of queue
*/
public enum QueueType {
/**
* First In First Out, available attributes are stored and returned in
* the order in which they are recycled
*/
FIFO,
/**
* Available attributes are returned by their number, so attributes with
* lower numbers will be used more often
*/
PRIORITY
}
/**
* Constructor
*
* @param ss
* The state system
* @param baseQuark
* The base quark under which to add the recyclable attributes
*/
public TmfAttributePool(ITmfStateSystemBuilder ss, Integer baseQuark) {
this(ss, baseQuark, QueueType.FIFO);
}
/**
* Constructor
*
* @param ss
* The state system
* @param baseQuark
* The base quark under which to add the recyclable attributes
* @param type
* The type of queue to use for the attribute pool
*/
public TmfAttributePool(ITmfStateSystemBuilder ss, Integer baseQuark, QueueType type) {
fSs = ss;
try {
/* Make sure the base quark is in range */
ss.getParentAttributeQuark(baseQuark);
fBaseQuark = baseQuark;
} catch (IndexOutOfBoundsException e) {
throw new IllegalArgumentException("The quark used as base for the attribute pool does not exist"); //$NON-NLS-1$
}
switch (type) {
case FIFO:
fAvailableQuarks = new ArrayDeque<>();
break;
case PRIORITY:
fAvailableQuarks = new PriorityQueue<>();
break;
default:
throw new IllegalArgumentException("Wrong queue type"); //$NON-NLS-1$
}
}
/**
* Get an available attribute quark. If there is one available, it will be
* reused, otherwise a new quark will be created under the base quark. The
* name of the attributes is a sequential integer. So the first quark to be
* added will be named '0', the next one '1', etc.
*
* @return An available quark
*/
public synchronized int getAvailable() {
Integer quark = fAvailableQuarks.poll();
if (quark == null) {
quark = fSs.getQuarkRelativeAndAdd(fBaseQuark, String.valueOf(fCount));
fCount++;
}
fQuarksInUse.add(quark);
return quark;
}
/**
* Recycle a quark so that it can be reused by calling the
* {@link #getAvailable()} method. The quark has to have been obtained from
* a previous call to {@link #getAvailable()}. It will set the quark's value
* in the state system to a null value.
*
* It is assumed that it will be reused in the same context each time, so
* all children are kept and set to null in this method. The quarks are
* still available for the caller, nothing prevents from re-using them
* without referring to this class. That means if any attribute's value need
* to be non-null after recycling the quark, the caller can do it after
* calling this method.
*
* @param quark
* The quark to recycle.
* @param ts
* The timestamp at which to close this attribute.
*/
public synchronized void recycle(int quark, long ts) {
if (!fQuarksInUse.remove(quark)) {
throw new IllegalArgumentException("Quark " + quark + " is not in use at time " + ts); //$NON-NLS-1$ //$NON-NLS-2$
}
fSs.removeAttribute(ts, quark);
fAvailableQuarks.add(quark);
}
}