annotate Source/Utility/Trigger.cpp @ 56:b4a2d2ae43cf tip

merge
author Andrew McPherson <andrewm@eecs.qmul.ac.uk>
date Fri, 23 Nov 2018 15:48:14 +0000
parents 3580ffe87dc8
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 Trigger.cpp: interface for objects to notify one another that new data
andrewm@0 21 has arrived. TriggerSource can send triggers to any object inheriting
andrewm@0 22 from TriggerDestination. Methods of keeping sources and destinations
andrewm@0 23 in sync are included in each class.
andrewm@0 24 */
andrewm@0 25
andrewm@0 26 #include "Trigger.h"
andrewm@0 27
andrewm@0 28 #undef DEBUG_TRIGGERS
andrewm@0 29
andrewm@0 30 void TriggerSource::sendTrigger(timestamp_type timestamp) {
andrewm@0 31 #ifdef DEBUG_TRIGGERS
andrewm@0 32 std::cerr << "sendTrigger (" << this << ")\n";
andrewm@0 33 #endif
andrewm@0 34
andrewm@0 35 if(triggerDestinationsModified_) {
andrewm@0 36 ScopedLock sl(triggerSourceMutex_);
andrewm@0 37 processAddRemoveQueue();
andrewm@0 38 }
andrewm@0 39
andrewm@0 40 std::set<TriggerDestination*>::iterator it = triggerDestinations_.begin();
andrewm@0 41 TriggerDestination* target;
andrewm@0 42 while(it != triggerDestinations_.end()) { // Advance the iterator before sending the trigger
andrewm@0 43 target = *it; // in case the triggerReceived routine causes the object to unregister
andrewm@0 44 #ifdef DEBUG_TRIGGERS
andrewm@0 45 std::cerr << " --> " << target << std::endl;
andrewm@0 46 #endif
andrewm@0 47 target->triggerReceived(this, timestamp);
andrewm@0 48 it++;
andrewm@0 49 }
andrewm@0 50 }
andrewm@0 51
andrewm@0 52 void TriggerSource::addTriggerDestination(TriggerDestination* dest) {
andrewm@0 53 #ifdef DEBUG_TRIGGERS
andrewm@0 54 std::cerr << "addTriggerDestination (" << this << "): " << dest << "\n";
andrewm@0 55 #endif
andrewm@0 56 if(dest == 0 || (void*)dest == (void*)this)
andrewm@0 57 return;
andrewm@0 58 ScopedLock sl(triggerSourceMutex_);
andrewm@0 59 // Make sure this trigger isn't already present
andrewm@0 60 if(triggerDestinations_.count(dest) == 0) {
andrewm@0 61 triggersToAdd_.insert(dest);
andrewm@0 62 triggerDestinationsModified_ = true;
andrewm@0 63 }
andrewm@0 64 // If the trigger is also slated to be removed, cancel that request
andrewm@0 65 if(triggersToRemove_.count(dest) != 0)
andrewm@0 66 triggersToRemove_.erase(dest);
andrewm@0 67 }
andrewm@0 68
andrewm@0 69 void TriggerSource::removeTriggerDestination(TriggerDestination* dest) {
andrewm@0 70 #ifdef DEBUG_TRIGGERS
andrewm@0 71 std::cerr << "removeTriggerDestination (" << this << "): " << dest << "\n";
andrewm@0 72 #endif
andrewm@0 73 ScopedLock sl(triggerSourceMutex_);
andrewm@0 74 // Check whether this trigger is actually present
andrewm@0 75 if(triggerDestinations_.count(dest) != 0) {
andrewm@0 76 triggersToRemove_.insert(dest);
andrewm@0 77 triggerDestinationsModified_ = true;
andrewm@0 78 }
andrewm@0 79 // If the trigger is also slated to be added, cancel that request
andrewm@0 80 if(triggersToAdd_.count(dest) != 0)
andrewm@0 81 triggersToAdd_.erase(dest);
andrewm@0 82 }
andrewm@0 83
andrewm@0 84 void TriggerSource::clearTriggerDestinations() {
andrewm@0 85 #ifdef DEBUG_TRIGGERS
andrewm@0 86 std::cerr << "clearTriggerDestinations (" << this << ")\n";
andrewm@0 87 #endif
andrewm@0 88 ScopedLock sl(triggerSourceMutex_);
andrewm@0 89 processAddRemoveQueue();
andrewm@0 90 std::set<TriggerDestination*>::iterator it;
andrewm@0 91 for(it = triggerDestinations_.begin(); it != triggerDestinations_.end(); ++it)
andrewm@0 92 (*it)->triggerSourceDeleted(this);
andrewm@0 93 triggerDestinations_.clear();
andrewm@0 94 }
andrewm@0 95
andrewm@0 96 // Process everything in the add and remove groups and transfer them
andrewm@0 97 // into the main set of trigger destinations. Do this with mutex locked.
andrewm@0 98 void TriggerSource::processAddRemoveQueue() {
andrewm@0 99 #ifdef DEBUG_TRIGGERS
andrewm@0 100 std::cerr << "processAddRemoveQueue (" << this << ")\n";
andrewm@0 101 #endif
andrewm@0 102 std::set<TriggerDestination*>::iterator it;
andrewm@0 103 for(it = triggersToAdd_.begin(); it != triggersToAdd_.end(); ++it) {
andrewm@0 104 triggerDestinations_.insert(*it);
andrewm@0 105 #ifdef DEBUG_TRIGGERS
andrewm@0 106 std::cerr << " --> added " << *it << std::endl;
andrewm@0 107 #endif
andrewm@0 108 }
andrewm@0 109 for(it = triggersToRemove_.begin(); it != triggersToRemove_.end(); ++it) {
andrewm@0 110 triggerDestinations_.erase(*it);
andrewm@0 111 #ifdef DEBUG_TRIGGERS
andrewm@0 112 std::cerr << " --> removed " << *it << std::endl;
andrewm@0 113 #endif
andrewm@0 114 }
andrewm@0 115 triggersToAdd_.clear();
andrewm@0 116 triggersToRemove_.clear();
andrewm@0 117 triggerDestinationsModified_ = false;
andrewm@0 118 }