Refactor log system
[platform/core/security/cert-svc.git] / vcore / src / dpl / core / src / waitable_handle_watch_support.cpp
1 /*
2  * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  *    Licensed under the Apache License, Version 2.0 (the "License");
5  *    you may not use this file except in compliance with the License.
6  *    You may obtain a copy of the License at
7  *
8  *        http://www.apache.org/licenses/LICENSE-2.0
9  *
10  *    Unless required by applicable law or agreed to in writing, software
11  *    distributed under the License is distributed on an "AS IS" BASIS,
12  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  *    See the License for the specific language governing permissions and
14  *    limitations under the License.
15  */
16 /*
17  * @file        waitable_handle_watch_support.cpp
18  * @author      Przemyslaw Dobrowolski (p.dobrowolsk@samsung.com)
19  * @version     1.0
20  * @brief       This file is the implementation file of waitable handle watch
21  * support
22  */
23 #include <stddef.h>
24 #include <dpl/waitable_handle_watch_support.h>
25 #include <dpl/thread.h>
26 #include <dpl/log/log.h>
27 #include <algorithm>
28 #include <dpl/assert.h>
29
30 namespace VcoreDPL {
31 WaitableHandleWatchSupport::WaitableHandleWatchSupport()
32 {}
33
34 WaitableHandleWatchSupport::~WaitableHandleWatchSupport()
35 {
36     // Developer assertions
37     if (!m_watchersMap.empty()) {
38         LogWarning("### Leaked watchers map dump ###");
39
40         for (WaitableHandleWatchersMap::const_iterator iterator =
41                  m_watchersMap.begin();
42              iterator != m_watchersMap.end();
43              ++iterator)
44         {
45             LogWarning("###   Waitable handle: " << iterator->first);
46
47             LogWarning("###     Read listeners: " << iterator->second.readListenersCount);
48             LogWarning("###     Write listeners: " << iterator->second.writeListenersCount);
49
50             for (WaitableHandleListenerList::const_iterator listenersIterator =
51                      iterator->second.listeners.begin();
52                  listenersIterator != iterator->second.listeners.end();
53                  ++listenersIterator)
54             {
55                 LogWarning("###       Mode: " << listenersIterator->mode
56                     << ". Listener: " << listenersIterator->listener);
57             }
58         }
59     }
60 }
61
62 WaitableHandle WaitableHandleWatchSupport::WaitableInvokerHandle() const
63 {
64     return m_watchersInvoker.GetHandle();
65 }
66
67 WaitableHandleListEx WaitableHandleWatchSupport::WaitableWatcherHandles() const
68 {
69     // Critical section
70     {
71         std::lock_guard<std::recursive_mutex> lock(m_watchersMutex);
72
73         WaitableHandleListEx handleList;
74
75         for (WaitableHandleWatchersMap::const_iterator iterator =
76                  m_watchersMap.begin();
77              iterator != m_watchersMap.end();
78              ++iterator)
79         {
80             // Register waitable event id for wait
81             // Check if there are any read listeners and write listeners
82             // and register for both if applicable
83             if (iterator->second.readListenersCount > 0) {
84                 handleList.push_back(std::make_pair(iterator->first,
85                                                     WaitMode::Read));
86             }
87
88             if (iterator->second.writeListenersCount > 0) {
89                 handleList.push_back(std::make_pair(iterator->first,
90                                                     WaitMode::Write));
91             }
92         }
93
94         return handleList;
95     }
96 }
97
98 void WaitableHandleWatchSupport::InvokerFinished()
99 {
100     LogDebug("Invoker finished called");
101
102     // Reset invoker
103     m_watchersInvoker.Reset();
104
105     // Commit invoke
106     m_watchersInvokerCommit.Signal();
107 }
108
109 void WaitableHandleWatchSupport::HandleWatcher(WaitableHandle waitableHandle,
110                                                WaitMode::Type mode)
111 {
112     //
113     // Waitable event occurred
114     // Now call all listeners for that waitable event. It is possible
115     // that some of listeners early disappeared. This is not a problem.
116     // Warning: Listeners and/or watcher may also disappear during dispatching
117     // handlers!
118     //
119     LogDebug("Waitable event occurred");
120
121     // Critical section for other threads
122     {
123         std::lock_guard<std::recursive_mutex> lock(m_watchersMutex);
124
125         // Notice: We must carefully call watchers here as they may disappear
126         // (zero listeners) or be created during each of handler call
127         //         All removed listeners are handled correctly. Adding
128         // additional listener to the same waitable handle
129         //         during handler dispatch sequence is _not_ supported.
130         WaitableHandleWatchersMap trackedWatchers = m_watchersMap;
131
132         for (WaitableHandleWatchersMap::const_iterator trackedWatchersIterator
133                  = trackedWatchers.begin();
134              trackedWatchersIterator != trackedWatchers.end();
135              ++trackedWatchersIterator)
136         {
137             // Check if this watcher still exists
138             // If not, go to next tracked watcher
139             if (m_watchersMap.find(trackedWatchersIterator->first) ==
140                 m_watchersMap.end())
141             {
142                 LogDebug("Watcher disappeared during watcher handler");
143                 continue;
144             }
145
146             // Is this is a waitable handle that we are searching for ?
147             if (waitableHandle != trackedWatchersIterator->first) {
148                 continue;
149             }
150
151             // Track watcher listeners list
152             WaitableHandleListenerList trackedListeners =
153                 trackedWatchersIterator->second.listeners;
154
155             LogDebug("Calling waitable event listeners (" << trackedListeners.size() << ")...");
156
157             // Notice: We must carefully call listeners here as they may
158             // disappear or be created during each of handler call
159             //         All removed listeners are handled correctly. Adding
160             // additional listener to the same waitable handle
161             //         during handler dispatch sequence is should be also
162             // handled, as an extremly case.
163
164             // Call all waitable event listeners who listen for that event
165             for (WaitableHandleListenerList::const_iterator
166                  trackedListenersIterator = trackedListeners.begin();
167                  trackedListenersIterator != trackedListeners.end();
168                  ++trackedListenersIterator)
169             {
170                 // Check if this watcher still exists
171                 // If not, there cannot be another one. Must exit now (after
172                 // break, we actually exit)
173                 if (m_watchersMap.find(trackedWatchersIterator->first) ==
174                     m_watchersMap.end())
175                 {
176                     LogDebug("Watcher disappeared during watcher handler");
177                     break;
178                 }
179
180                 // Check if this watcher listener still exists
181                 // If not, go to next tracked watcher listener
182                 bool listenerStillExists = false;
183
184                 for (WaitableHandleListenerList::const_iterator
185                      searchListenerIterator =
186                          trackedWatchersIterator->second.listeners.begin();
187                      searchListenerIterator !=
188                      trackedWatchersIterator->second.listeners.end();
189                      ++searchListenerIterator)
190                 {
191                     if (searchListenerIterator->listener ==
192                         trackedListenersIterator->listener &&
193                         searchListenerIterator->mode ==
194                         trackedListenersIterator->mode)
195                     {
196                         listenerStillExists = true;
197                         break;
198                     }
199                 }
200
201                 if (!listenerStillExists) {
202                     LogDebug("Watcher listener disappeared during watcher handler");
203                     break;
204                 }
205
206                 // Is this is a listener mode that we are searching for ?
207                 if (mode != trackedListenersIterator->mode) {
208                     continue;
209                 }
210
211                 // Call waitable event watch listener
212                 LogDebug("Before tracker listener call...");
213                 trackedListenersIterator->listener->OnWaitableHandleEvent(
214                     trackedWatchersIterator->first,
215                     trackedListenersIterator->mode);
216                 LogDebug("After tracker listener call...");
217             }
218
219             // Now call all those listeners who registered during listener calls
220             // FIXME: Implement! Notice, that scenario may be recursive!
221
222             LogDebug("Waitable event listeners called");
223
224             // No more waitable events possible - consistency check
225             break;
226         }
227     }
228 }
229
230 void WaitableHandleWatchSupport::AddWaitableHandleWatch(
231     WaitableHandleListener* listener,
232     WaitableHandle waitableHandle,
233     WaitMode::Type mode)
234 {
235     // Enter waitable event list critical section
236     std::lock_guard<std::recursive_mutex> lock(m_watchersMutex);
237
238     // Find proper list to register into
239     WaitableHandleWatchersMap::iterator mapIterator = m_watchersMap.find(
240             waitableHandle);
241
242     if (mapIterator != m_watchersMap.end()) {
243         // Assert if there is no such listener already that is listening in this
244         // mode
245         for (WaitableHandleListenerList::iterator listenersIterator =
246                  mapIterator->second.listeners.begin();
247              listenersIterator != mapIterator->second.listeners.end();
248              ++listenersIterator)
249         {
250             // Must not insert same listener-mode pair
251             Assert(
252                 listenersIterator->listener != listener ||
253                 listenersIterator->mode != mode);
254         }
255     }
256
257     LogDebug("Adding waitable handle watch : " << waitableHandle);
258
259     // Push new waitable event watch
260     if (mapIterator != m_watchersMap.end()) {
261         mapIterator->second.listeners.push_back(WaitableHandleWatcher(listener,
262                                                                       mode));
263     } else {
264         m_watchersMap[waitableHandle].listeners.push_back(WaitableHandleWatcher(
265                                                               listener, mode));
266     }
267
268     // Update counters
269     switch (mode) {
270     case WaitMode::Read:
271         m_watchersMap[waitableHandle].readListenersCount++;
272         break;
273
274     case WaitMode::Write:
275         m_watchersMap[waitableHandle].writeListenersCount++;
276         break;
277
278     default:
279         Assert(0);
280     }
281
282     // Trigger waitable event invoker to commit changes
283     CommitInvoker();
284
285     LogDebug("Waitable event watch added and invoker signaled");
286 }
287
288 void WaitableHandleWatchSupport::RemoveWaitableHandleWatch(
289     WaitableHandleListener *listener,
290     WaitableHandle waitableHandle,
291     WaitMode::Type mode)
292 {
293     // Enter waitable event list critical section
294     std::lock_guard<std::recursive_mutex> lock(m_watchersMutex);
295
296     // Find proper list with listener
297     WaitableHandleWatchersMap::iterator mapIterator = m_watchersMap.find(
298             waitableHandle);
299
300     Assert(mapIterator != m_watchersMap.end());
301
302     // Assert if there is such listener and mode
303     WaitableHandleListenerList::iterator listIterator =
304         mapIterator->second.listeners.end();
305
306     for (WaitableHandleListenerList::iterator listenersIterator =
307              mapIterator->second.listeners.begin();
308          listenersIterator != mapIterator->second.listeners.end();
309          ++listenersIterator)
310     {
311         // Check same pair listener-mode
312         if (listenersIterator->listener == listener &&
313             listenersIterator->mode == mode)
314         {
315             listIterator = listenersIterator;
316             break;
317         }
318     }
319
320     // Same pair listener-mode must exist
321     Assert(listIterator != mapIterator->second.listeners.end());
322
323     LogDebug("Removing waitable handle watch : " << waitableHandle);
324
325     // Remove waitable event watch
326     mapIterator->second.listeners.erase(listIterator);
327
328     // Update counters
329     switch (mode) {
330     case WaitMode::Read:
331         mapIterator->second.readListenersCount--;
332         break;
333
334     case WaitMode::Write:
335         mapIterator->second.writeListenersCount--;
336         break;
337
338     default:
339         Assert(0);
340     }
341
342     // If list is empty, remove it too
343     if (mapIterator->second.listeners.empty()) {
344         m_watchersMap.erase(mapIterator);
345     }
346
347     // Trigger waitable event invoker to commit changes
348     CommitInvoker();
349
350     LogDebug("Waitable event watch removed and invoker signaled");
351 }
352
353 void WaitableHandleWatchSupport::CommitInvoker()
354 {
355     // Check calling context and execute invoker
356     if (Thread::GetCurrentThread() == GetInvokerThread()) {
357         LogDebug("Calling direct invoker");
358
359         // Direct invoker call
360         HandleDirectInvoker();
361     } else {
362         LogDebug("Calling indirect invoker");
363
364         // Indirect invoker call
365         m_watchersInvoker.Signal();
366
367         WaitableHandleList waitHandles;
368         waitHandles.push_back(m_watchersInvokerCommit.GetHandle());
369         WaitForMultipleHandles(waitHandles);
370
371         m_watchersInvokerCommit.Reset();
372     }
373 }
374
375 } // namespace VcoreDPL