1d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood/* 2d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood * Copyright (C) 2014 The Android Open Source Project 3d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood * 4d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood * Licensed under the Apache License, Version 2.0 (the "License"); 5d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood * you may not use this file except in compliance with the License. 6d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood * You may obtain a copy of the License at 7d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood * 8d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood * http://www.apache.org/licenses/LICENSE-2.0 9d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood * 10d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood * Unless required by applicable law or agreed to in writing, software 11d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood * distributed under the License is distributed on an "AS IS" BASIS, 12d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood * See the License for the specific language governing permissions and 14d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood * limitations under the License. 15d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood */ 16d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood 17d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwoodpackage com.android.internal.midi; 18d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood 19b6f50d357bd3d4d296be6bb047f5ce93a79cbca1Mike Lockwoodimport java.util.Iterator; 20d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwoodimport java.util.SortedMap; 21d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwoodimport java.util.TreeMap; 22d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood 23d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood/** 24d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood * Store arbitrary timestamped events using a Long timestamp. 25d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood * Only one Thread can write into the buffer. 26d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood * And only one Thread can read from the buffer. 27d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood */ 28d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwoodpublic class EventScheduler { 29d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood private static final long NANOS_PER_MILLI = 1000000; 30d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood 312776133be7ac60dc8d6aea5b12e35449ca331836Mike Lockwood private final Object mLock = new Object(); 32b6f50d357bd3d4d296be6bb047f5ce93a79cbca1Mike Lockwood volatile private SortedMap<Long, FastEventQueue> mEventBuffer; 33d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood private FastEventQueue mEventPool = null; 34d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood private int mMaxPoolSize = 200; 352776133be7ac60dc8d6aea5b12e35449ca331836Mike Lockwood private boolean mClosed; 36d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood 37d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood public EventScheduler() { 38d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood mEventBuffer = new TreeMap<Long, FastEventQueue>(); 39d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood } 40d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood 41d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood // If we keep at least one node in the list then it can be atomic 42d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood // and non-blocking. 43d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood private class FastEventQueue { 44d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood // One thread takes from the beginning of the list. 45d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood volatile SchedulableEvent mFirst; 46d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood // A second thread returns events to the end of the list. 47d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood volatile SchedulableEvent mLast; 48d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood volatile long mEventsAdded; 49d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood volatile long mEventsRemoved; 50d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood 51d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood FastEventQueue(SchedulableEvent event) { 52d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood mFirst = event; 53d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood mLast = mFirst; 54d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood mEventsAdded = 1; 55d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood mEventsRemoved = 0; 56d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood } 57d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood 58d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood int size() { 59d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood return (int)(mEventsAdded - mEventsRemoved); 60d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood } 61d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood 62d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood /** 63d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood * Do not call this unless there is more than one event 64d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood * in the list. 65d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood * @return first event in the list 66d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood */ 67d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood public SchedulableEvent remove() { 68d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood // Take first event. 69d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood mEventsRemoved++; 70d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood SchedulableEvent event = mFirst; 71d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood mFirst = event.mNext; 72b6f50d357bd3d4d296be6bb047f5ce93a79cbca1Mike Lockwood event.mNext = null; 73d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood return event; 74d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood } 75d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood 76d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood /** 77d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood * @param event 78d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood */ 79d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood public void add(SchedulableEvent event) { 80d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood event.mNext = null; 81d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood mLast.mNext = event; 82d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood mLast = event; 83d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood mEventsAdded++; 84d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood } 85d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood } 86d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood 87d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood /** 88d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood * Base class for events that can be stored in the EventScheduler. 89d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood */ 90d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood public static class SchedulableEvent { 91d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood private long mTimestamp; 92b6f50d357bd3d4d296be6bb047f5ce93a79cbca1Mike Lockwood volatile private SchedulableEvent mNext = null; 93d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood 94d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood /** 95d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood * @param timestamp 96d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood */ 97d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood public SchedulableEvent(long timestamp) { 98d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood mTimestamp = timestamp; 99d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood } 100d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood 101d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood /** 102d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood * @return timestamp 103d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood */ 104d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood public long getTimestamp() { 105d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood return mTimestamp; 106d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood } 107d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood 108d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood /** 109d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood * The timestamp should not be modified when the event is in the 110d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood * scheduling buffer. 111d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood */ 112d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood public void setTimestamp(long timestamp) { 113d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood mTimestamp = timestamp; 114d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood } 115d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood } 116d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood 117d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood /** 118d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood * Get an event from the pool. 119d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood * Always leave at least one event in the pool. 120d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood * @return event or null 121d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood */ 122d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood public SchedulableEvent removeEventfromPool() { 123d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood SchedulableEvent event = null; 124d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood if (mEventPool != null && (mEventPool.size() > 1)) { 125d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood event = mEventPool.remove(); 126d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood } 127d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood return event; 128d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood } 129d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood 130d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood /** 131d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood * Return events to a pool so they can be reused. 132d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood * 133d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood * @param event 134d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood */ 135d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood public void addEventToPool(SchedulableEvent event) { 136d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood if (mEventPool == null) { 137d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood mEventPool = new FastEventQueue(event); 138d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood // If we already have enough items in the pool then just 139d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood // drop the event. This prevents unbounded memory leaks. 140d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood } else if (mEventPool.size() < mMaxPoolSize) { 141d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood mEventPool.add(event); 142d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood } 143d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood } 144d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood 145d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood /** 146d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood * Add an event to the scheduler. Events with the same time will be 147d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood * processed in order. 148d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood * 149d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood * @param event 150d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood */ 151d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood public void add(SchedulableEvent event) { 1522776133be7ac60dc8d6aea5b12e35449ca331836Mike Lockwood synchronized (mLock) { 153d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood FastEventQueue list = mEventBuffer.get(event.getTimestamp()); 154d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood if (list == null) { 155d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood long lowestTime = mEventBuffer.isEmpty() ? Long.MAX_VALUE 156d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood : mEventBuffer.firstKey(); 157d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood list = new FastEventQueue(event); 158d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood mEventBuffer.put(event.getTimestamp(), list); 159d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood // If the event we added is earlier than the previous earliest 160d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood // event then notify any threads waiting for the next event. 161d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood if (event.getTimestamp() < lowestTime) { 1622776133be7ac60dc8d6aea5b12e35449ca331836Mike Lockwood mLock.notify(); 163d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood } 164d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood } else { 165d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood list.add(event); 166d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood } 167d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood } 168d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood } 169d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood 170d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood private SchedulableEvent removeNextEventLocked(long lowestTime) { 171d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood SchedulableEvent event; 172d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood FastEventQueue list = mEventBuffer.get(lowestTime); 173d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood // Remove list from tree if this is the last node. 174d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood if ((list.size() == 1)) { 175d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood mEventBuffer.remove(lowestTime); 176d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood } 177d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood event = list.remove(); 178d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood return event; 179d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood } 180d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood 181d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood /** 182d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood * Check to see if any scheduled events are ready to be processed. 183d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood * 184d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood * @param timestamp 185d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood * @return next event or null if none ready 186d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood */ 187d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood public SchedulableEvent getNextEvent(long time) { 188d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood SchedulableEvent event = null; 1892776133be7ac60dc8d6aea5b12e35449ca331836Mike Lockwood synchronized (mLock) { 190d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood if (!mEventBuffer.isEmpty()) { 191d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood long lowestTime = mEventBuffer.firstKey(); 192d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood // Is it time for this list to be processed? 193d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood if (lowestTime <= time) { 194d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood event = removeNextEventLocked(lowestTime); 195d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood } 196d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood } 197d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood } 198d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood // Log.i(TAG, "getNextEvent: event = " + event); 199d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood return event; 200d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood } 201d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood 202d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood /** 203d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood * Return the next available event or wait until there is an event ready to 204d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood * be processed. This method assumes that the timestamps are in nanoseconds 205d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood * and that the current time is System.nanoTime(). 206d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood * 207d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood * @return event 208d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood * @throws InterruptedException 209d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood */ 210d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood public SchedulableEvent waitNextEvent() throws InterruptedException { 211d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood SchedulableEvent event = null; 2122776133be7ac60dc8d6aea5b12e35449ca331836Mike Lockwood synchronized (mLock) { 2132776133be7ac60dc8d6aea5b12e35449ca331836Mike Lockwood while (!mClosed) { 2142776133be7ac60dc8d6aea5b12e35449ca331836Mike Lockwood long millisToWait = Integer.MAX_VALUE; 215d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood if (!mEventBuffer.isEmpty()) { 216d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood long now = System.nanoTime(); 217d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood long lowestTime = mEventBuffer.firstKey(); 218d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood // Is it time for the earliest list to be processed? 219d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood if (lowestTime <= now) { 220d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood event = removeNextEventLocked(lowestTime); 221d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood break; 222d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood } else { 223d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood // Figure out how long to sleep until next event. 224d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood long nanosToWait = lowestTime - now; 225d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood // Add 1 millisecond so we don't wake up before it is 226d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood // ready. 227d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood millisToWait = 1 + (nanosToWait / NANOS_PER_MILLI); 228d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood // Clip 64-bit value to 32-bit max. 229d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood if (millisToWait > Integer.MAX_VALUE) { 230d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood millisToWait = Integer.MAX_VALUE; 231d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood } 232d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood } 233d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood } 2342776133be7ac60dc8d6aea5b12e35449ca331836Mike Lockwood mLock.wait((int) millisToWait); 235d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood } 236d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood } 237d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood return event; 238d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood } 2392776133be7ac60dc8d6aea5b12e35449ca331836Mike Lockwood 240b6f50d357bd3d4d296be6bb047f5ce93a79cbca1Mike Lockwood protected void flush() { 241b6f50d357bd3d4d296be6bb047f5ce93a79cbca1Mike Lockwood // Replace our event buffer with a fresh empty one 242b6f50d357bd3d4d296be6bb047f5ce93a79cbca1Mike Lockwood mEventBuffer = new TreeMap<Long, FastEventQueue>(); 243b6f50d357bd3d4d296be6bb047f5ce93a79cbca1Mike Lockwood } 244b6f50d357bd3d4d296be6bb047f5ce93a79cbca1Mike Lockwood 2452776133be7ac60dc8d6aea5b12e35449ca331836Mike Lockwood public void close() { 2462776133be7ac60dc8d6aea5b12e35449ca331836Mike Lockwood synchronized (mLock) { 2472776133be7ac60dc8d6aea5b12e35449ca331836Mike Lockwood mClosed = true; 2482776133be7ac60dc8d6aea5b12e35449ca331836Mike Lockwood mLock.notify(); 2492776133be7ac60dc8d6aea5b12e35449ca331836Mike Lockwood } 2502776133be7ac60dc8d6aea5b12e35449ca331836Mike Lockwood } 251d1b16fe2fb7527eee214898263ec4d6dabbfb0b4Mike Lockwood} 252