1 // Copyright (C) 2014-20xx CEA/DEN, EDF R&D
3 // File: Events_Loop.hxx
4 // Created: Thu Mar 13 2014
5 // Author: Mikhail PONIKAROV
7 #include <Events_Loop.h>
8 #include <Events_MessageGroup.h>
13 Events_Loop* Events_Loop::loop()
15 // initialized on initialization of the application
16 static Events_Loop MAIN_LOOP;
20 Events_ID Events_Loop::eventByName(const char* theName)
22 ///! All events created in this session, uniquely identified by the text and char pointer
23 static std::map<std::string, char*> CREATED_EVENTS;
25 std::string aName(theName);
26 std::map<std::string, char*>::iterator aFound = CREATED_EVENTS.find(aName);
27 if (aFound == CREATED_EVENTS.end()) { //not created yet
29 aResult = _strdup(theName); // copy to make unique internal pointer
31 aResult = strdup(theName); // copy to make unique internal pointer
33 CREATED_EVENTS[aName] = aResult;
35 aResult = aFound->second;
37 return Events_ID(aResult);
40 void Events_Loop::sendProcessEvent(const std::shared_ptr<Events_Message>& theMessage,
41 std::list<Events_Listener*>& theListeners, const bool theFlushedNow)
43 std::list<Events_Listener*>::iterator aL = theListeners.begin();
44 for (; aL != theListeners.end(); aL++) {
45 if (theFlushedNow && (*aL)->groupMessages()) {
46 (*aL)->groupWhileFlush(theMessage);
48 (*aL)->processEvent(theMessage);
53 void Events_Loop::send(const std::shared_ptr<Events_Message>& theMessage, bool isGroup)
55 if (myImmediateListeners.find(theMessage->eventID().eventText()) != myImmediateListeners.end()) {
56 myImmediateListeners[theMessage->eventID().eventText()]->processEvent(theMessage);
58 // if it is grouped message, just accumulate it
59 bool isFlushedNow = myFlushed.find(theMessage->eventID().myID) != myFlushed.end();
60 if (isGroup && !isFlushedNow) {
61 std::shared_ptr<Events_MessageGroup> aGroup =
62 std::dynamic_pointer_cast<Events_MessageGroup>(theMessage);
64 std::map<char*, std::shared_ptr<Events_Message> >::iterator aMyGroup = myGroups.find(
65 aGroup->eventID().eventText());
66 if (aMyGroup == myGroups.end()) { // create a new group of messages for accumulation
67 myGroups[aGroup->eventID().eventText()] = aGroup->newEmpty();
68 aMyGroup = myGroups.find(aGroup->eventID().eventText());
70 std::shared_ptr<Events_MessageGroup> aStored =
71 std::dynamic_pointer_cast<Events_MessageGroup>(aMyGroup->second);
72 aStored->Join(aGroup);
77 std::map<char*, std::map<void*, std::list<Events_Listener*> > >::iterator aFindID =
78 myListeners.find(theMessage->eventID().eventText());
79 if (aFindID != myListeners.end()) {
80 std::map<void*, std::list<Events_Listener*> >::iterator aFindSender = aFindID->second.find(
81 theMessage->sender());
82 if (aFindSender != aFindID->second.end()) {
83 sendProcessEvent(theMessage, aFindSender->second, isFlushedNow && isGroup);
85 if (theMessage->sender()) { // also call for NULL senders registered
86 aFindSender = aFindID->second.find(NULL);
87 if (aFindSender != aFindID->second.end()) {
88 sendProcessEvent(theMessage, aFindSender->second, isFlushedNow && isGroup);
94 void Events_Loop::registerListener(Events_Listener* theListener, const Events_ID theID,
95 void* theSender, bool theImmediate)
97 if (theImmediate) { // just register as an immediate
98 myImmediateListeners[theID.eventText()] = theListener;
101 std::map<char*, std::map<void*, std::list<Events_Listener*> > >::iterator aFindID =
102 myListeners.find(theID.eventText());
103 if (aFindID == myListeners.end()) { // create container associated with ID
104 myListeners[theID.eventText()] = std::map<void*, std::list<Events_Listener*> >();
105 aFindID = myListeners.find(theID.eventText());
108 std::map<void*, std::list<Events_Listener*> >::iterator aFindSender =
109 aFindID->second.find(theSender);
110 if (aFindSender == aFindID->second.end()) { // create container associated with sender
111 aFindID->second[theSender] = std::list<Events_Listener*>();
112 aFindSender = aFindID->second.find(theSender);
114 // check that listener was not registered wit hsuch parameters before
115 std::list<Events_Listener*>& aListeners = aFindSender->second;
116 for (std::list<Events_Listener*>::iterator aL = aListeners.begin(); aL != aListeners.end(); aL++)
117 if (*aL == theListener)
118 return; // avoid duplicates
120 aListeners.push_back(theListener);
123 void Events_Loop::removeListener(Events_Listener* theListener)
125 // remove the listener in myListeners map
126 std::map<char*, std::map<void*, std::list<Events_Listener*> > >::const_reverse_iterator
127 anIt = myListeners.rbegin();
128 while(anIt != myListeners.rend()) {
129 std::map<void*, std::list<Events_Listener*> > aLMap = anIt->second;
130 std::map<void*, std::list<Events_Listener*> >::const_reverse_iterator aLIt = aLMap.rbegin();
131 while (aLIt != aLMap.rend()) {
132 std::list<Events_Listener*> aListeners = aLIt->second;
133 std::list<Events_Listener*>::const_reverse_iterator aLsIt = aListeners.rbegin();
134 for (; aLsIt != aListeners.rend(); aLsIt++) {
135 if (*aLsIt == theListener) {
136 aListeners.remove(theListener);
137 aLMap[aLIt->first] = aListeners;
138 myListeners[anIt->first] = aLMap;
142 if (aListeners.empty()) {
143 aLMap.erase(aLIt->first);
144 myListeners[anIt->first] = aLMap;
146 break; // avoid incrementation of the iterator if the the container is empty
150 if (anIt->second.empty()) {
151 myListeners.erase(anIt->first);
152 if (myListeners.empty())
153 break; // avoid incrementation of the iterator if the the container is empty
158 // remove the listener in myImmediateListeners map
159 std::map<char*, Events_Listener*>::const_reverse_iterator anImIt = myImmediateListeners.rbegin();
160 while(anImIt != myImmediateListeners.rend()) {
161 if (anImIt->second == theListener) {
162 myImmediateListeners.erase(anImIt->first);
163 if (myImmediateListeners.empty())
164 break; // avoid incrementation of the iterator if the the container is empty
170 void Events_Loop::flush(const Events_ID& theID)
174 bool hasEventsToFlush = !myGroups.empty();
175 std::map<char*, std::shared_ptr<Events_Message> >::iterator aMyGroup;
176 for(aMyGroup = myGroups.find(theID.eventText());
177 aMyGroup != myGroups.end(); aMyGroup = myGroups.find(theID.eventText()))
179 bool aWasFlushed = myFlushed.find(theID.myID) != myFlushed.end();
181 myFlushed.insert(theID.myID);
182 std::shared_ptr<Events_Message> aGroup = aMyGroup->second;
183 myGroups.erase(aMyGroup);
187 // TODO: Stabilization fix. Check later.
188 if(myFlushed.find(theID.myID) != myFlushed.end()) {
189 myFlushed.erase(myFlushed.find(theID.myID));
191 bool aProblem = true;
194 // send accumulated messages to "groupListeners"
195 std::map<char*, std::map<void*, std::list<Events_Listener*> > >::iterator aFindID =
196 myListeners.find(theID.eventText());
197 if (aFindID != myListeners.end()) {
198 std::map<void*, std::list<Events_Listener*> >::iterator aFindSender =
199 aFindID->second.begin();
200 for(; aFindSender != aFindID->second.end(); aFindSender++) {
201 std::list<Events_Listener*>::iterator aListener = aFindSender->second.begin();
202 for(; aListener != aFindSender->second.end(); aListener++) {
203 if ((*aListener)->groupMessages()) {
204 (*aListener)->flushGrouped(theID);
210 if (hasEventsToFlush && myGroups.empty() && myFlushed.empty()) {
211 // no more messages left in the queue, so, finalize the sketch processing
212 static Events_ID anID = Events_Loop::eventByName("SketchPrepared");
213 std::shared_ptr<Events_Message> aMsg(new Events_Message(anID, this));
214 Events_Loop::loop()->send(aMsg, false);
218 void Events_Loop::eraseMessages(const Events_ID& theID)
220 std::map<char*, std::shared_ptr<Events_Message> >::iterator aMyGroup =
221 myGroups.find(theID.eventText());
222 if (aMyGroup != myGroups.end()) {
223 myGroups.erase(aMyGroup);
228 bool Events_Loop::activateFlushes(const bool theActivate)
230 bool isActive = myFlushActive;
231 myFlushActive = theActivate;
235 void Events_Loop::clear(const Events_ID& theID)
237 std::map<char*, std::shared_ptr<Events_Message>>::iterator aMyGroup =
238 myGroups.find(theID.eventText());
239 if (aMyGroup != myGroups.end()) { // really sends
240 myGroups.erase(aMyGroup);
244 bool Events_Loop::isFlushed(const Events_ID& theID)
246 return myFlushed.find(theID.myID) != myFlushed.end();
249 void Events_Loop::setFlushed(const Events_ID& theID, const bool theValue)
252 myFlushed.insert(theID.myID);
254 myFlushed.erase(myFlushed.find(theID.myID));
257 bool Events_Loop::hasGrouppedEvent(const Events_ID& theID)
259 return myGroups.find(theID.myID) != myGroups.end();