Entropy Piano Tuner  1.1.3 (documentation not yet complete)
An open-source experimental software for piano tuning by entropy minimization
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
messagehandler.cpp
Go to the documentation of this file.
1 /*****************************************************************************
2  * Copyright 2015 Haye Hinrichsen, Christoph Wick
3  *
4  * This file is part of Entropy Piano Tuner.
5  *
6  * Entropy Piano Tuner is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by the
8  * Free Software Foundation, either version 3 of the License, or (at your
9  * option) any later version.
10  *
11  * Entropy Piano Tuner is distributed in the hope that it will be useful, but
12  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13  * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14  * more details.
15  *
16  * You should have received a copy of the GNU General Public License along with
17  * Entropy Piano Tuner. If not, see http://www.gnu.org/licenses/.
18  *****************************************************************************/
19 
20 #include "messagehandler.h"
21 #include <assert.h>
22 #include <algorithm>
23 #include <iostream>
24 #include "messagelistener.h"
25 
26 
27 //---------- Singleton variable holding the only instance of this class ---------
28 
30 
31 //---------------------------- Empty constructor --------------------------------
32 
34 {
35 }
36 
37 //---------------------------- Empty descructor ---------------------------------
38 
40 {
41 }
42 
43 //------------------------- get Singleton reference -----------------------------
44 
46  return mSingleton;
47 }
48 
49 //-------------------------- get Singleton pointer ------------------------------
50 
52  return &mSingleton;
53 }
54 
55 //----------- Main task: process the queue and handle the messages --------------
56 
58 {
59  // update the listeners
61  // first add then remove, since it can occur, that adding and removing is in the same frame
62  std::for_each(mListenersToAdd.begin(), mListenersToAdd.end(), [this](MessageListener *l) {mListeners.push_back(l);});
63  std::for_each(mListenersToRemove.begin(), mListenersToRemove.end(), [this](MessageListener *l) {mListeners.remove(l);});
64  mListenersToAdd.clear();
65  mListenersToRemove.clear();
66  mListenersChangesMutex.unlock();
67 
68  // copy all messages to a local list, to prevent adding while processing
69  std::list<MessagePtr> list;
70  mMessageMutex.lock();
71  mMessages.swap(list);
72  mMessageMutex.unlock();
73 
74  // handle messages
75  while (!list.empty())
76  {
77  MessagePtr nextmessage (list.front());
78  list.pop_front();
79  for (auto listener : mListeners) {
80  // check if listener is in remove list, then skip, because this listener is destroyed
81  {
82  // lock mutex
83  std::lock_guard<std::mutex> lock(mListenersChangesMutex);
84  // check if existing
85  if (std::find(mListenersToRemove.begin(), mListenersToRemove.end(), listener) != mListenersToRemove.end()) {
86  // skip
87  continue;
88  }
89  }
90 
91  // normal message handling
92  if (listener->isMessageListenerActive()) {
93  listener->handleMessage (nextmessage);
94  }
95  }
96  }
97 }
98 
99 //----------------- Add a new listener to the messaging system -----------------
100 
102  std::lock_guard<std::mutex> lock(mListenersChangesMutex);
103 
104  assert (listener);
105  assert (std::find(mListenersToAdd.begin(), mListenersToAdd.end(), listener) == mListenersToAdd.end());
106  mListenersToAdd.push_back(listener);
107 }
108 
109 //---------------- Remove a listener from the messaging system -----------------
110 
112  std::lock_guard<std::mutex> lock(mListenersChangesMutex);
113 
114  assert (listener);
115  assert (std::find(mListenersToRemove.begin(), mListenersToRemove.end(), listener) == mListenersToRemove.end());
116  mListenersToRemove.push_back(listener);
117 }
118 
119 //--------------------------- Submit a message ---------------------------------
120 
123 void MessageHandler::addMessage(MessagePtr message, bool dropOlder) {
124  assert (message);
125  mMessageMutex.lock();
126  if (dropOlder) {
127  for (auto it = mMessages.begin(); it != mMessages.end();) {
128  if ((*it)->getType() == message->getType()) {
129  it = mMessages.erase(it);
130  } else {
131  ++it;
132  }
133  }
134  }
135  mMessages.push_back(message);
136  mMessageMutex.unlock();
137 }
std::shared_ptr< Message > MessagePtr
Global type of a shared message pointer.
Definition: message.h:98
static MessageHandler & getSingleton()
get a reference to the singleton class
MessageHandler()
private constructor since this class is a singleton
std::list< MessagePtr > mMessages
Queue of messages to be submitted.
std::mutex mMessageMutex
Mutex for accessing the queue.
void addMessage(MessagePtr message, bool dropOlder=false)
Submit a message.
void addListener(MessageListener *listener)
Connect a new message listener.
std::list< MessageListener * > mListenersToRemove
List of listeners to remove in the next frame.
static MessageHandler mSingleton
Singleton instance.
std::list< MessageListener * > mListeners
List of all listeners.
void process()
Main task, processing the events in the queue.
std::list< MessageListener * > mListenersToAdd
List of listeners to add in the next frame.
Class for handling and sending messages.
std::mutex mListenersChangesMutex
Mutex for accessing the listeners list.
static MessageHandler * getSingletonPtr()
get a pointer to the singleton class
~MessageHandler()
Empty desctructor.
void removeListener(MessageListener *listener)
Disconnect a message listener.