9537fb403ab5879197e8f55448a2770846b580a3
[deliverable/tracecompass.git] / analysis / org.eclipse.tracecompass.analysis.timing.core / src / org / eclipse / tracecompass / internal / analysis / timing / core / store / ArrayListStore.java
1 /*******************************************************************************
2 * Copyright (c) 2016 Ericsson
3 *
4 * All rights reserved. This program and the accompanying materials
5 * are made available under the terms of the Eclipse Public License v1.0
6 * which accompanies this distribution, and is available at
7 * http://www.eclipse.org/legal/epl-v10.html
8 *******************************************************************************/
9
10 package org.eclipse.tracecompass.internal.analysis.timing.core.store;
11
12 import static org.eclipse.tracecompass.common.core.NonNullUtils.checkNotNull;
13
14 import java.util.ArrayList;
15 import java.util.Collection;
16 import java.util.Collections;
17 import java.util.Comparator;
18 import java.util.Iterator;
19 import java.util.List;
20 import java.util.concurrent.locks.ReadWriteLock;
21 import java.util.concurrent.locks.ReentrantReadWriteLock;
22 import java.util.stream.Collectors;
23
24 import org.eclipse.jdt.annotation.NonNull;
25 import org.eclipse.jdt.annotation.Nullable;
26 import org.eclipse.tracecompass.segmentstore.core.ISegment;
27 import org.eclipse.tracecompass.segmentstore.core.ISegmentStore;
28
29 import com.google.common.collect.ImmutableList;
30
31 /**
32 * Implementation of an {@link ISegmentStore} using one in-memory
33 * {@link ArrayList}. This relatively simple implementation holds everything in
34 * memory, and as such cannot contain too much data.
35 *
36 * The ArrayListStore itself is {@link Iterable}, and its iteration order will
37 * be by ascending order of start times. For segments with identical start
38 * times, the secondary comparator will be the end time. If even those are
39 * equal, it will defer to the segments' natural ordering (
40 * {@link ISegment#compareTo}).
41 *
42 * The store's tree maps will not accept duplicate key-value pairs, which means
43 * that if you want several segments with the same start and end times, make
44 * sure their compareTo() differentiates them.
45 *
46 * Removal operations are not supported.
47 *
48 * @param <E>
49 * The type of segment held in this store
50 *
51 * @author Matthew Khouzam
52 */
53 public class ArrayListStore<@NonNull E extends ISegment> implements ISegmentStore<E> {
54
55 private final Comparator<E> COMPARATOR = (o1, o2) -> {
56 int ret = Long.compare(o1.getStart(), o2.getStart());
57 if (ret == 0) {
58 return Long.compare(o1.getEnd(), o2.getEnd());
59 }
60 return ret;
61 };
62
63 private final ReadWriteLock fLock = new ReentrantReadWriteLock(false);
64
65 private final List<E> fStore;
66
67 private @Nullable transient Iterable<E> fLastSnapshot = null;
68
69 /**
70 * Constructor
71 */
72 public ArrayListStore() {
73 fStore = new ArrayList<>();
74 }
75
76 /**
77 * Constructor
78 *
79 * @param array
80 * an array of elements to wrap in the segment store
81 *
82 */
83 public ArrayListStore(Object[] array) {
84 fStore = new ArrayList<>();
85 for (int i = 0; i < array.length; i++) {
86 if (array[i] instanceof ISegment) {
87 fStore.add((E) array[i]);
88 }
89 }
90 fStore.sort(COMPARATOR);
91 }
92 // ------------------------------------------------------------------------
93 // Methods from Collection
94 // ------------------------------------------------------------------------
95
96 @Override
97 public Iterator<E> iterator() {
98 fLock.readLock().lock();
99 try {
100 Iterable<E> lastSnapshot = fLastSnapshot;
101 if (lastSnapshot == null) {
102 lastSnapshot = ImmutableList.copyOf(fStore);
103 fLastSnapshot = lastSnapshot;
104 }
105 return checkNotNull(lastSnapshot.iterator());
106 } finally {
107 fLock.readLock().unlock();
108 }
109 }
110
111 @Override
112 public boolean add(@Nullable E val) {
113 if (val == null) {
114 throw new IllegalArgumentException("Cannot add null value"); //$NON-NLS-1$
115 }
116
117 fLock.writeLock().lock();
118 try {
119 fStore.add(val);
120 // Go backwards to "sift up" like a priority queue
121 for (int i = size() - 1; i > 0 && COMPARATOR.compare(val, fStore.get(i - 1)) < 0; i--) {
122 Collections.swap(fStore, i, i - 1);
123 }
124 fLastSnapshot = null;
125 return true;
126 } finally {
127 fLock.writeLock().unlock();
128 }
129 }
130
131 @Override
132 public int size() {
133 return fStore.size();
134 }
135
136 @Override
137 public boolean isEmpty() {
138 fLock.readLock().lock();
139 try {
140 return fStore.isEmpty();
141 } finally {
142 fLock.readLock().unlock();
143 }
144 }
145
146 @Override
147 public boolean contains(@Nullable Object o) {
148 fLock.readLock().lock();
149 try {
150 return fStore.contains(o);
151 } finally {
152 fLock.readLock().unlock();
153 }
154 }
155
156 @Override
157 public boolean containsAll(@Nullable Collection<?> c) {
158 fLock.readLock().lock();
159 try {
160 return fStore.containsAll(c);
161 } finally {
162 fLock.readLock().unlock();
163 }
164 }
165
166 @Override
167 public Object[] toArray() {
168 fLock.readLock().lock();
169 try {
170 return fStore.toArray();
171 } finally {
172 fLock.readLock().unlock();
173 }
174 }
175
176 @Override
177 public <T> T[] toArray(T[] a) {
178 fLock.readLock().lock();
179 try {
180 return fStore.toArray(a);
181 } finally {
182 fLock.readLock().unlock();
183 }
184 }
185
186 @Override
187 public boolean remove(@Nullable Object o) {
188 throw new UnsupportedOperationException();
189 }
190
191 @Override
192 public boolean addAll(@Nullable Collection<? extends E> c) {
193 if (c == null) {
194 throw new IllegalArgumentException();
195 }
196
197 fLock.writeLock().lock();
198 try {
199 boolean changed = false;
200 for (E elem : c) {
201 if (this.add(elem)) {
202 changed = true;
203 }
204 }
205 return changed;
206 } finally {
207 fLock.writeLock().unlock();
208 }
209 }
210
211 @Override
212 public boolean removeAll(@Nullable Collection<?> c) {
213 throw new UnsupportedOperationException();
214 }
215
216 @Override
217 public boolean retainAll(@Nullable Collection<?> c) {
218 throw new UnsupportedOperationException();
219 }
220
221 @Override
222 public void clear() {
223 fLock.writeLock().lock();
224 try {
225 fStore.clear();
226 } finally {
227 fLock.writeLock().unlock();
228 }
229 }
230
231 // ------------------------------------------------------------------------
232 // Methods added by ISegmentStore
233 // ------------------------------------------------------------------------
234
235 @Override
236 public Iterable<E> getIntersectingElements(long position) {
237 /*
238 * The intervals intersecting 't' are those whose 1) start time is
239 * *lower* than 't' AND 2) end time is *higher* than 't'.
240 */
241 fLock.readLock().lock();
242 try {
243 return fStore.stream().filter(element -> position >= element.getStart() && position <= element.getEnd()).collect(Collectors.toList());
244 } finally {
245 fLock.readLock().unlock();
246 }
247 }
248
249 @Override
250 public Iterable<E> getIntersectingElements(long start, long end) {
251 fLock.readLock().lock();
252 try {
253 return fStore.stream().filter(element -> !(start > element.getEnd() || end < element.getStart())).collect(Collectors.toList());
254 } finally {
255 fLock.readLock().unlock();
256 }
257 }
258
259 @Override
260 public void dispose() {
261 fLock.writeLock().lock();
262 try {
263 fStore.clear();
264 } finally {
265 fLock.writeLock().unlock();
266 }
267 }
268 }
This page took 0.036802 seconds and 4 git commands to generate.