annotate Source/Mappings/MappingScheduler.h @ 56:b4a2d2ae43cf tip

merge
author Andrew McPherson <andrewm@eecs.qmul.ac.uk>
date Fri, 23 Nov 2018 15:48:14 +0000
parents c6f30c1e2bda
children
rev   line source
andrewm@0 1 /*
andrewm@0 2 TouchKeys: multi-touch musical keyboard control software
andrewm@0 3 Copyright (c) 2013 Andrew McPherson
andrewm@0 4
andrewm@0 5 This program is free software: you can redistribute it and/or modify
andrewm@0 6 it under the terms of the GNU General Public License as published by
andrewm@0 7 the Free Software Foundation, either version 3 of the License, or
andrewm@0 8 (at your option) any later version.
andrewm@0 9
andrewm@0 10 This program is distributed in the hope that it will be useful,
andrewm@0 11 but WITHOUT ANY WARRANTY; without even the implied warranty of
andrewm@0 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
andrewm@0 13 GNU General Public License for more details.
andrewm@0 14
andrewm@0 15 You should have received a copy of the GNU General Public License
andrewm@0 16 along with this program. If not, see <http://www.gnu.org/licenses/>.
andrewm@0 17
andrewm@0 18 =====================================================================
andrewm@0 19
andrewm@0 20 MappingScheduler.h: implements a thread in which mapping actions are
andrewm@0 21 performed. Each Mapping object implements a triggerReceived() method
andrewm@0 22 which is called by the hardware I/O thread. This method should do a
andrewm@0 23 minimal amount of work but pass the real work off to the performMapping()
andrewm@0 24 method which is called by the MappingScheduler thread. The scheduler
andrewm@0 25 also allows mapping calls to be performed in the absence of received data,
andrewm@0 26 for example to cause a parameter to ramp down over time if no touch data
andrewm@0 27 is received.
andrewm@0 28 */
andrewm@0 29
andrewm@0 30 #ifndef __TouchKeys__MappingScheduler__
andrewm@0 31 #define __TouchKeys__MappingScheduler__
andrewm@0 32
andrewm@11 33 #undef DEBUG_MAPPING_SCHEDULER_STATISTICS
andrewm@11 34
andrewm@0 35 #include <iostream>
andrewm@0 36 #include <map>
andrewm@0 37 #include <list>
andrewm@0 38 #include "../JuceLibraryCode/JuceHeader.h"
andrewm@0 39 #include "Mapping.h"
andrewm@0 40
andrewm@0 41 /*
andrewm@0 42 * LockFreeQueue
andrewm@0 43 *
andrewm@0 44 * Placeholder implementation for a ring buffer. Will have issues with
andrewm@0 45 * instruction reordering, but should serve the purpose for testing for now.
andrewm@0 46 */
andrewm@0 47
andrewm@0 48 template <typename T>
andrewm@0 49 struct LockFreeQueue
andrewm@0 50 {
andrewm@0 51 LockFreeQueue()
andrewm@0 52 {
andrewm@0 53 list.push_back(T());
andrewm@0 54 iHead = list.begin();
andrewm@0 55 iTail = list.end();
andrewm@0 56 }
andrewm@0 57
andrewm@0 58 void Produce(const T& t)
andrewm@0 59 {
andrewm@0 60 list.push_back(t);
andrewm@0 61 iTail = list.end();
andrewm@0 62 list.erase(list.begin(), iHead);
andrewm@0 63 }
andrewm@0 64
andrewm@0 65 bool Consume(T& t)
andrewm@0 66 {
andrewm@0 67 typename TList::iterator iNext = iHead;
andrewm@0 68 ++iNext;
andrewm@0 69 if (iNext != iTail)
andrewm@0 70 {
andrewm@0 71 iHead = iNext;
andrewm@0 72 t = *iHead;
andrewm@0 73 return true;
andrewm@0 74 }
andrewm@0 75 return false;
andrewm@0 76 }
andrewm@0 77
andrewm@0 78 T Consume()
andrewm@0 79 {
andrewm@0 80 T tmp;
andrewm@0 81 while (!Consume(tmp))
andrewm@0 82 {
andrewm@0 83 ;
andrewm@0 84 }
andrewm@0 85 return tmp;
andrewm@0 86 }
andrewm@0 87
andrewm@11 88 #ifdef DEBUG_MAPPING_SCHEDULER_STATISTICS
andrewm@11 89 unsigned long size()
andrewm@11 90 {
andrewm@11 91 return list.size();
andrewm@11 92 }
andrewm@11 93 #endif
andrewm@11 94
andrewm@0 95 private:
andrewm@0 96 typedef std::list<T> TList;
andrewm@0 97 TList list;
andrewm@0 98 typename std::list<T>::iterator iHead, iTail;
andrewm@0 99 };
andrewm@0 100
andrewm@0 101 /*
andrewm@0 102 * MappingScheduler
andrewm@0 103 *
andrewm@0 104 * This class manages the timing and execution of Mapping objects. It performs a function
andrewm@0 105 * similar to Scheduler but optimized specifically for running the performMapping() method
andrewm@0 106 * of objects inheriting from Mapping. It maintains facilities to run mappings either now
andrewm@0 107 * or in the future, including the ability to preempt future mapping calls with more immediate
andrewm@0 108 * ones.
andrewm@0 109 */
andrewm@0 110
andrewm@0 111 class MappingScheduler : public Thread {
andrewm@0 112 private:
andrewm@0 113 static const timestamp_diff_type kAllowableAdvanceExecutionTime;
andrewm@0 114
andrewm@0 115 enum {
andrewm@0 116 kActionUnknown = 0,
andrewm@0 117 kActionRegister,
andrewm@0 118 kActionPerformMapping,
andrewm@0 119 kActionUnschedule,
andrewm@0 120 kActionUnregister,
andrewm@0 121 kActionUnregisterAndDelete
andrewm@0 122 };
andrewm@0 123
andrewm@0 124 struct MappingAction {
andrewm@0 125 public:
andrewm@0 126 MappingAction() : who(0), counter(0), action(kActionUnknown) {}
andrewm@0 127 MappingAction(Mapping *x, unsigned long y, int z) :
andrewm@0 128 who(x), counter(y), action(z) {}
andrewm@0 129
andrewm@0 130 Mapping *who;
andrewm@0 131 unsigned long counter;
andrewm@0 132 int action;
andrewm@0 133 };
andrewm@0 134
andrewm@0 135 public:
andrewm@0 136 // ***** Constructor *****
andrewm@0 137 //
andrewm@0 138 // Note: This class is not copy-constructable.
andrewm@0 139
andrewm@11 140 MappingScheduler(PianoKeyboard& keyboard, String threadName = "MappingScheduler");
andrewm@0 141 // ***** Destructor *****
andrewm@0 142
andrewm@0 143 ~MappingScheduler();
andrewm@0 144
andrewm@0 145 // ***** Thread Methods *****
andrewm@0 146 //
andrewm@0 147 // These start and stop the thread that handles the scheduling of events.
andrewm@0 148
andrewm@0 149 void start();
andrewm@0 150 void stop();
andrewm@0 151
andrewm@0 152 bool isRunning() { return isRunning_; }
andrewm@0 153
andrewm@0 154 // The main Juce::Thread run loop
andrewm@0 155 void run();
andrewm@0 156
andrewm@0 157 // ***** Event Management Methods *****
andrewm@0 158 //
andrewm@0 159 // This interface provides the ability to schedule and unschedule events for
andrewm@0 160 // current or future times.
andrewm@0 161
andrewm@0 162 void registerMapping(Mapping *who);
andrewm@0 163
andrewm@0 164 void scheduleNow(Mapping *who);
andrewm@0 165 void scheduleLater(Mapping *who, timestamp_type timestamp);
andrewm@0 166
andrewm@0 167 void unschedule(Mapping *who);
andrewm@0 168
andrewm@0 169 void unregisterMapping(Mapping *who);
andrewm@0 170 void unregisterAndDelete(Mapping *who);
andrewm@0 171
andrewm@0 172 private:
andrewm@0 173 // ***** Private Methods *****
andrewm@0 174 void performAction(MappingAction const& mappingAction);
andrewm@0 175
andrewm@0 176 // Reference to the main PianoKeyboard object which holds the master timestamp
andrewm@0 177 PianoKeyboard& keyboard_;
andrewm@0 178
andrewm@0 179 // These variables keep track of the status of the separate thread running the events
andrewm@0 180 CriticalSection actionsInsertionMutex_;
andrewm@0 181 CriticalSection actionsLaterMutex_;
andrewm@0 182
andrewm@0 183 WaitableEvent waitableEvent_;
andrewm@0 184 bool isRunning_;
andrewm@0 185
andrewm@0 186 // This counter keeps track of the sequence of insertions and executions
andrewm@0 187 // of mappings. It is incremented whenever the scheduler finishes the "now"
andrewm@0 188 // set of actions, and can be used to figure out whether an event has been
andrewm@0 189 // duplicated or preempted.
andrewm@0 190 unsigned long counter_;
andrewm@0 191 std::map<Mapping*, unsigned long> countersForMappings_;
andrewm@0 192
andrewm@0 193 // These variables hold a ring buffer of actions to happen as soon as possible and a
andrewm@0 194 // lock-synchronized collection of events that happen at later timestamps
andrewm@0 195 LockFreeQueue<MappingAction> actionsNow_;
andrewm@0 196 std::multimap<timestamp_type, MappingAction> actionsLater_;
andrewm@11 197
andrewm@11 198 #ifdef DEBUG_MAPPING_SCHEDULER_STATISTICS
andrewm@11 199 timestamp_type lastDebugStatisticsTimestamp_;
andrewm@11 200
andrewm@11 201 // Debugging method to indicate what is in the queue
andrewm@11 202 void printDebugStatistics();
andrewm@11 203 #endif
andrewm@0 204 };
andrewm@0 205
andrewm@0 206
andrewm@0 207 #endif /* defined(__TouchKeys__MappingScheduler__) */