2 * Copyright (c) 2014 Samsung Electronics Co., Ltd.
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.
19 #include <dali/internal/event/common/notification-manager.h>
23 #pragma clang diagnostic push
24 #pragma clang diagnostic ignored "-Wall"
26 #include <boost/thread/mutex.hpp>
28 #pragma clang diagnostic pop
31 #include <boost/thread/mutex.hpp>
36 #include <dali/public-api/common/dali-common.h>
37 #include <dali/internal/common/owner-container.h>
38 #include <dali/internal/common/message.h>
39 #include <dali/internal/event/common/property-notification-impl.h>
40 #include <dali/internal/event/common/complete-notification-interface.h>
50 typedef Dali::Vector< CompleteNotificationInterface* > InterfaceContainer;
53 * helper to move elements from one container to another
54 * @param from where to move
55 * @param to move target
57 void MoveElements( InterfaceContainer& from, InterfaceContainer& to )
59 // check if there's something in from
60 const InterfaceContainer::SizeType fromCount = from.Count();
63 // check if to has some elements
64 const InterfaceContainer::SizeType toCount = to.Count();
67 // to is empty so we can swap with from
72 to.Reserve( toCount + fromCount );
73 for( InterfaceContainer::SizeType i = 0; i < fromCount; ++i )
75 to.PushBack( from[ i ] );
83 typedef boost::mutex MessageQueueMutex;
84 typedef OwnerContainer< MessageBase* > MessageContainer;
86 struct NotificationManager::Impl
90 // reserve space on the vectors to avoid reallocs
91 // applications typically have up-to 20-30 notifications at startup
92 updateCompletedMessageQueue.Reserve( 32 );
93 updateWorkingMessageQueue.Reserve( 32 );
94 eventMessageQueue.Reserve( 32 );
96 // only a few manager objects get complete notifications (animation, render list, property notifications, ...)
97 updateCompletedInterfaceQueue.Reserve( 4 );
98 updateWorkingInterfaceQueue.Reserve( 4 );
99 eventInterfaceQueue.Reserve( 4 );
106 // queueMutex must be locked whilst accessing queue
107 MessageQueueMutex queueMutex;
108 // three queues for objects owned by notification manager
109 MessageContainer updateCompletedMessageQueue;
110 MessageContainer updateWorkingMessageQueue;
111 MessageContainer eventMessageQueue;
112 // three queues for objects referenced by notification manager
113 InterfaceContainer updateCompletedInterfaceQueue;
114 InterfaceContainer updateWorkingInterfaceQueue;
115 InterfaceContainer eventInterfaceQueue;
118 NotificationManager::NotificationManager()
123 NotificationManager::~NotificationManager()
128 void NotificationManager::QueueCompleteNotification( CompleteNotificationInterface* instance )
130 // queueMutex must be locked whilst accessing queues
131 MessageQueueMutex::scoped_lock lock( mImpl->queueMutex );
133 mImpl->updateWorkingInterfaceQueue.PushBack( instance );
136 void NotificationManager::QueueMessage( MessageBase* message )
138 DALI_ASSERT_DEBUG( NULL != message );
140 // queueMutex must be locked whilst accessing queues
141 MessageQueueMutex::scoped_lock lock( mImpl->queueMutex );
143 mImpl->updateWorkingMessageQueue.PushBack( message );
146 void NotificationManager::UpdateCompleted()
148 // queueMutex must be locked whilst accessing queues
149 MessageQueueMutex::scoped_lock lock( mImpl->queueMutex );
150 // Move messages from update working queue to completed queue
151 // note that in theory its possible for update completed to have last frames
152 // events as well still hanging around. we need to keep them as well
153 mImpl->updateCompletedMessageQueue.MoveFrom( mImpl->updateWorkingMessageQueue );
154 // move pointers from interface queue
155 MoveElements( mImpl->updateWorkingInterfaceQueue, mImpl->updateCompletedInterfaceQueue );
156 // finally the lock is released
159 bool NotificationManager::MessagesToProcess()
161 // queueMutex must be locked whilst accessing queues
162 MessageQueueMutex::scoped_lock lock( mImpl->queueMutex );
164 return ( 0u < mImpl->updateCompletedMessageQueue.Count() ||
165 ( 0u < mImpl->updateCompletedInterfaceQueue.Count() ) );
168 void NotificationManager::ProcessMessages()
170 // queueMutex must be locked whilst accessing queues
172 MessageQueueMutex::scoped_lock lock( mImpl->queueMutex );
174 // Move messages from update completed queue to event queue
175 // note that in theory its possible for event queue to have
176 // last frames events as well still hanging around so need to keep them
177 mImpl->eventMessageQueue.MoveFrom( mImpl->updateCompletedMessageQueue );
178 MoveElements( mImpl->updateCompletedInterfaceQueue, mImpl->eventInterfaceQueue );
180 // end of scope, lock is released
182 MessageContainer::Iterator iter = mImpl->eventMessageQueue.Begin();
183 const MessageContainer::Iterator end = mImpl->eventMessageQueue.End();
184 for( ; iter != end; ++iter )
186 (*iter)->Process( 0u/*ignored*/ );
188 // release the processed messages from event side queue
189 mImpl->eventMessageQueue.Clear();
191 InterfaceContainer::Iterator iter2 = mImpl->eventInterfaceQueue.Begin();
192 const InterfaceContainer::Iterator end2 = mImpl->eventInterfaceQueue.End();
193 for( ; iter2 != end2; ++iter2 )
195 CompleteNotificationInterface* interface = *iter2;
198 interface->NotifyCompleted();
201 // just clear the container, we dont own the objects
202 mImpl->eventInterfaceQueue.Clear();
205 } // namespace Internal