Salome HOME
Merge remote branch 'remotes/origin/vsr/libxml2_mdv' into Dev_2.1.0
[modules/shaper.git] / src / Events / Events_Loop.cpp
1 // Copyright (C) 2014-20xx CEA/DEN, EDF R&D
2
3 // File:        Events_Loop.hxx
4 // Created:     Thu Mar 13 2014
5 // Author:      Mikhail PONIKAROV
6
7 #include <Events_Loop.h>
8 #include <Events_MessageGroup.h>
9
10 #include <string>
11 #include <cstring>
12
13 using namespace std;
14
15 Events_Loop* Events_Loop::loop()
16 {
17   // initialized on initialization of the application
18   static Events_Loop MAIN_LOOP;
19   return &MAIN_LOOP;
20 }
21
22 Events_ID Events_Loop::eventByName(const char* theName)
23 {
24   ///! All events created in this session, uniquely identified by the text and char pointer
25   static map<string, char*> CREATED_EVENTS;
26   char* aResult;
27   string aName(theName);
28   map<string, char*>::iterator aFound = CREATED_EVENTS.find(aName);
29   if (aFound == CREATED_EVENTS.end()) {  //not created yet
30 #ifdef WIN32
31     aResult = _strdup(theName);  // copy to make unique internal pointer
32 #else
33     aResult = strdup(theName);  // copy to make unique internal pointer
34 #endif
35     CREATED_EVENTS[aName] = aResult;
36   } else
37     aResult = aFound->second;
38
39   return Events_ID(aResult);
40 }
41
42 void Events_Loop::send(const std::shared_ptr<Events_Message>& theMessage, bool isGroup)
43 {
44   if (myImmediateListeners.find(theMessage->eventID().eventText()) != myImmediateListeners.end()) {
45     myImmediateListeners[theMessage->eventID().eventText()]->processEvent(theMessage);
46   }
47   // if it is grouped message, just accumulate it
48   if (isGroup && myFlushed.find(theMessage->eventID().myID) == myFlushed.end()) {
49     std::shared_ptr<Events_MessageGroup> aGroup = 
50       std::dynamic_pointer_cast<Events_MessageGroup>(theMessage);
51     if (aGroup) {
52       std::map<char*, std::shared_ptr<Events_Message> >::iterator aMyGroup = myGroups.find(
53           aGroup->eventID().eventText());
54       if (aMyGroup == myGroups.end()) {  // create a new group of messages for accumulation
55         myGroups[aGroup->eventID().eventText()] = aGroup->newEmpty();
56         aMyGroup = myGroups.find(aGroup->eventID().eventText());
57       }
58       std::shared_ptr<Events_MessageGroup> aStored =
59         std::dynamic_pointer_cast<Events_MessageGroup>(aMyGroup->second);
60       aStored->Join(aGroup);
61       return;
62     }
63   }
64
65   // TODO: make it in thread and with usage of semaphores
66
67   map<char*, map<void*, list<Events_Listener*> > >::iterator aFindID = myListeners.find(
68       theMessage->eventID().eventText());
69   if (aFindID != myListeners.end()) {
70     map<void*, list<Events_Listener*> >::iterator aFindSender = aFindID->second.find(
71         theMessage->sender());
72     if (aFindSender != aFindID->second.end()) {
73       list<Events_Listener*>& aListeners = aFindSender->second;
74       for (list<Events_Listener*>::iterator aL = aListeners.begin(); aL != aListeners.end(); aL++)
75         (*aL)->processEvent(theMessage);
76     }
77     if (theMessage->sender()) {  // also call for NULL senders registered
78       aFindSender = aFindID->second.find(NULL);
79       if (aFindSender != aFindID->second.end()) {
80         list<Events_Listener*>& aListeners = aFindSender->second;
81         for (list<Events_Listener*>::iterator aL = aListeners.begin(); aL != aListeners.end(); aL++)
82           (*aL)->processEvent(theMessage);
83       }
84     }
85   }
86 }
87
88 void Events_Loop::registerListener(Events_Listener* theListener, const Events_ID theID,
89                                    void* theSender, bool theImmediate)
90 {
91   if (theImmediate) { // just register as an immediate
92     myImmediateListeners[theID.eventText()] = theListener;
93     return;
94   }
95   map<char*, map<void*, list<Events_Listener*> > >::iterator aFindID = myListeners.find(
96       theID.eventText());
97   if (aFindID == myListeners.end()) {  // create container associated with ID
98     myListeners[theID.eventText()] = map<void*, list<Events_Listener*> >();
99     aFindID = myListeners.find(theID.eventText());
100   }
101
102   map<void*, list<Events_Listener*> >::iterator aFindSender = aFindID->second.find(theSender);
103   if (aFindSender == aFindID->second.end()) {  // create container associated with sender
104     aFindID->second[theSender] = list<Events_Listener*>();
105     aFindSender = aFindID->second.find(theSender);
106   }
107   // check that listener was not registered wit hsuch parameters before
108   list<Events_Listener*>& aListeners = aFindSender->second;
109   for (list<Events_Listener*>::iterator aL = aListeners.begin(); aL != aListeners.end(); aL++)
110     if (*aL == theListener)
111       return;  // avoid duplicates
112
113   aListeners.push_back(theListener);
114 }
115
116 void Events_Loop::flush(const Events_ID& theID)
117 {
118   if (!myFlushActive)
119     return;
120   std::map<char*, std::shared_ptr<Events_Message> >::iterator aMyGroup;
121   for(aMyGroup = myGroups.find(theID.eventText());
122     aMyGroup != myGroups.end(); aMyGroup = myGroups.find(theID.eventText()))
123   {  // really sends
124     bool aWasFlushed = myFlushed.find(theID.myID) != myFlushed.end();
125     if (!aWasFlushed)
126       myFlushed.insert(theID.myID);
127     std::shared_ptr<Events_Message> aGroup = aMyGroup->second;
128     myGroups.erase(aMyGroup);
129     send(aGroup, false);
130
131     if (!aWasFlushed)
132       // TODO: Stabilization fix. Check later.
133       if(myFlushed.find(theID.myID) != myFlushed.end()) {
134         myFlushed.erase(myFlushed.find(theID.myID));
135       }
136   }
137 }
138
139 void Events_Loop::eraseMessages(const Events_ID& theID)
140 {
141   std::map<char*, std::shared_ptr<Events_Message> >::iterator aMyGroup =
142     myGroups.find(theID.eventText());
143   if (aMyGroup != myGroups.end()) {
144     myGroups.erase(aMyGroup);
145   }
146 }
147
148
149 bool Events_Loop::activateFlushes(const bool theActivate)
150 {
151   bool isActive = myFlushActive;
152   myFlushActive = theActivate;
153   return isActive;
154 }
155
156 void Events_Loop::clear(const Events_ID& theID)
157 {
158   std::map<char*, std::shared_ptr<Events_Message>>::iterator aMyGroup =
159     myGroups.find(theID.eventText());
160   if (aMyGroup != myGroups.end()) {  // really sends
161     myGroups.erase(aMyGroup);
162   }
163 }
164
165 void Events_Loop::autoFlush(const Events_ID& theID, const bool theAuto)
166 {
167   if (theAuto)
168     myFlushed.insert(theID.myID);
169   else
170     myFlushed.erase(myFlushed.find(theID.myID));
171 }
172
173 bool Events_Loop::isFlushed(const Events_ID& theID)
174 {
175   return myFlushed.find(theID.myID) != myFlushed.end();
176 }
177
178 void Events_Loop::setFlushed(const Events_ID& theID, const bool theValue)
179 {
180   if (theValue)
181     myFlushed.insert(theID.myID);
182   else
183     myFlushed.erase(myFlushed.find(theID.myID));
184 }