2 * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 * @file waitable_handle_watch_support.cpp
18 * @author Przemyslaw Dobrowolski (p.dobrowolsk@samsung.com)
20 * @brief This file is the implementation file of waitable handle watch
24 #include <dpl/waitable_handle_watch_support.h>
25 #include <dpl/thread.h>
26 #include <dpl/log/log.h>
28 #include <dpl/assert.h>
31 WaitableHandleWatchSupport::WaitableHandleWatchSupport()
34 WaitableHandleWatchSupport::~WaitableHandleWatchSupport()
36 // Developer assertions
37 if (!m_watchersMap.empty()) {
38 LogWarning("### Leaked watchers map dump ###");
40 for (WaitableHandleWatchersMap::const_iterator iterator =
41 m_watchersMap.begin();
42 iterator != m_watchersMap.end();
45 LogWarning("### Waitable handle: " << iterator->first);
48 "### Read listeners: " <<
49 iterator->second.readListenersCount);
51 "### Write listeners: " <<
52 iterator->second.writeListenersCount);
54 for (WaitableHandleListenerList::const_iterator listenersIterator =
55 iterator->second.listeners.begin();
56 listenersIterator != iterator->second.listeners.end();
60 "### Mode: " << listenersIterator->mode <<
61 ". Listener: 0x" << std::hex << listenersIterator->listener);
67 WaitableHandle WaitableHandleWatchSupport::WaitableInvokerHandle() const
69 return m_watchersInvoker.GetHandle();
72 WaitableHandleListEx WaitableHandleWatchSupport::WaitableWatcherHandles() const
76 std::lock_guard<std::recursive_mutex> lock(m_watchersMutex);
78 WaitableHandleListEx handleList;
80 for (WaitableHandleWatchersMap::const_iterator iterator =
81 m_watchersMap.begin();
82 iterator != m_watchersMap.end();
85 // Register waitable event id for wait
86 // Check if there are any read listeners and write listeners
87 // and register for both if applicable
88 if (iterator->second.readListenersCount > 0) {
89 handleList.push_back(std::make_pair(iterator->first,
93 if (iterator->second.writeListenersCount > 0) {
94 handleList.push_back(std::make_pair(iterator->first,
103 void WaitableHandleWatchSupport::InvokerFinished()
105 LogPedantic("Invoker finished called");
108 m_watchersInvoker.Reset();
111 m_watchersInvokerCommit.Signal();
114 void WaitableHandleWatchSupport::HandleWatcher(WaitableHandle waitableHandle,
118 // Waitable event occurred
119 // Now call all listeners for that waitable event. It is possible
120 // that some of listeners early disappeared. This is not a problem.
121 // Warning: Listeners and/or watcher may also disappear during dispatching
124 LogPedantic("Waitable event occurred");
126 // Critical section for other threads
128 std::lock_guard<std::recursive_mutex> lock(m_watchersMutex);
130 // Notice: We must carefully call watchers here as they may disappear
131 // (zero listeners) or be created during each of handler call
132 // All removed listeners are handled correctly. Adding
133 // additional listener to the same waitable handle
134 // during handler dispatch sequence is _not_ supported.
135 WaitableHandleWatchersMap trackedWatchers = m_watchersMap;
137 for (WaitableHandleWatchersMap::const_iterator trackedWatchersIterator
138 = trackedWatchers.begin();
139 trackedWatchersIterator != trackedWatchers.end();
140 ++trackedWatchersIterator)
142 // Check if this watcher still exists
143 // If not, go to next tracked watcher
144 if (m_watchersMap.find(trackedWatchersIterator->first) ==
147 LogPedantic("Watcher disappeared during watcher handler");
151 // Is this is a waitable handle that we are searching for ?
152 if (waitableHandle != trackedWatchersIterator->first) {
156 // Track watcher listeners list
157 WaitableHandleListenerList trackedListeners =
158 trackedWatchersIterator->second.listeners;
161 "Calling waitable event listeners (" <<
162 trackedListeners.size() << ")...");
164 // Notice: We must carefully call listeners here as they may
165 // disappear or be created during each of handler call
166 // All removed listeners are handled correctly. Adding
167 // additional listener to the same waitable handle
168 // during handler dispatch sequence is should be also
169 // handled, as an extremly case.
171 // Call all waitable event listeners who listen for that event
172 for (WaitableHandleListenerList::const_iterator
173 trackedListenersIterator = trackedListeners.begin();
174 trackedListenersIterator != trackedListeners.end();
175 ++trackedListenersIterator)
177 // Check if this watcher still exists
178 // If not, there cannot be another one. Must exit now (after
179 // break, we actually exit)
180 if (m_watchersMap.find(trackedWatchersIterator->first) ==
183 LogPedantic("Watcher disappeared during watcher handler");
187 // Check if this watcher listener still exists
188 // If not, go to next tracked watcher listener
189 bool listenerStillExists = false;
191 for (WaitableHandleListenerList::const_iterator
192 searchListenerIterator =
193 trackedWatchersIterator->second.listeners.begin();
194 searchListenerIterator !=
195 trackedWatchersIterator->second.listeners.end();
196 ++searchListenerIterator)
198 if (searchListenerIterator->listener ==
199 trackedListenersIterator->listener &&
200 searchListenerIterator->mode ==
201 trackedListenersIterator->mode)
203 listenerStillExists = true;
208 if (!listenerStillExists) {
210 "Watcher listener disappeared during watcher handler");
214 // Is this is a listener mode that we are searching for ?
215 if (mode != trackedListenersIterator->mode) {
219 // Call waitable event watch listener
220 LogPedantic("Before tracker listener call...");
221 trackedListenersIterator->listener->OnWaitableHandleEvent(
222 trackedWatchersIterator->first,
223 trackedListenersIterator->mode);
224 LogPedantic("After tracker listener call...");
227 // Now call all those listeners who registered during listener calls
228 // FIXME: Implement! Notice, that scenario may be recursive!
230 LogPedantic("Waitable event listeners called");
232 // No more waitable events possible - consistency check
238 void WaitableHandleWatchSupport::CommitInvoker()
240 // Check calling context and execute invoker
241 if (Thread::GetCurrentThread() == GetInvokerThread()) {
242 LogPedantic("Calling direct invoker");
244 // Direct invoker call
245 HandleDirectInvoker();
247 LogPedantic("Calling indirect invoker");
249 // Indirect invoker call
250 m_watchersInvoker.Signal();
252 WaitableHandleList waitHandles;
253 waitHandles.push_back(m_watchersInvokerCommit.GetHandle());
254 WaitForMultipleHandles(waitHandles);
256 m_watchersInvokerCommit.Reset();