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>
22 #include <dali/devel-api/common/owner-container.h>
23 #include <dali/devel-api/threading/mutex.h>
24 #include <dali/integration-api/debug.h>
25 #include <dali/internal/common/message.h>
26 #include <dali/internal/event/common/complete-notification-interface.h>
27 #include <dali/internal/event/common/property-notification-impl.h>
28 #include <dali/public-api/common/dali-common.h>
36 typedef Dali::Vector<CompleteNotificationInterface*> InterfaceContainer;
39 * helper to move elements from one container to another
40 * @param from where to move
41 * @param to move target
43 void MoveElements(InterfaceContainer& from, InterfaceContainer& to)
45 // check if there's something in from
46 const InterfaceContainer::SizeType fromCount = from.Count();
49 // check if to has some elements
50 const InterfaceContainer::SizeType toCount = to.Count();
53 // to is empty so we can swap with from
58 to.Reserve(toCount + fromCount);
59 for(InterfaceContainer::SizeType i = 0; i < fromCount; ++i)
69 using MessageQueueMutex = Dali::Mutex;
70 using MessageContainer = OwnerContainer<MessageBase*>;
72 struct NotificationManager::Impl
76 // reserve space on the vectors to avoid reallocs
77 // applications typically have up-to 20-30 notifications at startup
78 updateCompletedMessageQueue.Reserve(32);
79 updateWorkingMessageQueue.Reserve(32);
80 eventMessageQueue.Reserve(32);
82 // only a few manager objects get complete notifications (animation, render list, property notifications, ...)
83 updateCompletedInterfaceQueue.Reserve(4);
84 updateWorkingInterfaceQueue.Reserve(4);
85 eventInterfaceQueue.Reserve(4);
90 // queueMutex must be locked whilst accessing queue
91 MessageQueueMutex queueMutex;
92 // three queues for objects owned by notification manager
93 MessageContainer updateCompletedMessageQueue;
94 MessageContainer updateWorkingMessageQueue;
95 MessageContainer eventMessageQueue;
96 // three queues for objects referenced by notification manager
97 InterfaceContainer updateCompletedInterfaceQueue;
98 InterfaceContainer updateWorkingInterfaceQueue;
99 InterfaceContainer eventInterfaceQueue;
102 NotificationManager::NotificationManager()
107 NotificationManager::~NotificationManager()
112 void NotificationManager::QueueCompleteNotification(CompleteNotificationInterface* instance)
114 // queueMutex must be locked whilst accessing queues
115 MessageQueueMutex::ScopedLock lock(mImpl->queueMutex);
117 mImpl->updateWorkingInterfaceQueue.PushBack(instance);
120 void NotificationManager::QueueMessage(MessageBase* message)
122 DALI_ASSERT_DEBUG(NULL != message);
124 // queueMutex must be locked whilst accessing queues
125 MessageQueueMutex::ScopedLock lock(mImpl->queueMutex);
127 mImpl->updateWorkingMessageQueue.PushBack(message);
130 void NotificationManager::UpdateCompleted()
132 // queueMutex must be locked whilst accessing queues
133 MessageQueueMutex::ScopedLock lock(mImpl->queueMutex);
134 // Move messages from update working queue to completed queue
135 // note that in theory its possible for update completed to have last frames
136 // events as well still hanging around. we need to keep them as well
137 mImpl->updateCompletedMessageQueue.MoveFrom(mImpl->updateWorkingMessageQueue);
138 // move pointers from interface queue
139 MoveElements(mImpl->updateWorkingInterfaceQueue, mImpl->updateCompletedInterfaceQueue);
140 // finally the lock is released
143 bool NotificationManager::MessagesToProcess()
145 // queueMutex must be locked whilst accessing queues
146 MessageQueueMutex::ScopedLock lock(mImpl->queueMutex);
148 return (0u < mImpl->updateCompletedMessageQueue.Count() ||
149 (0u < mImpl->updateCompletedInterfaceQueue.Count()));
152 void NotificationManager::ProcessMessages()
154 // queueMutex must be locked whilst accessing queues
156 MessageQueueMutex::ScopedLock lock(mImpl->queueMutex);
158 // Move messages from update completed queue to event queue
159 // note that in theory its possible for event queue to have
160 // last frames events as well still hanging around so need to keep them
161 mImpl->eventMessageQueue.MoveFrom(mImpl->updateCompletedMessageQueue);
162 MoveElements(mImpl->updateCompletedInterfaceQueue, mImpl->eventInterfaceQueue);
164 // end of scope, lock is released
166 MessageContainer::Iterator iter = mImpl->eventMessageQueue.Begin();
167 const MessageContainer::Iterator end = mImpl->eventMessageQueue.End();
170 DALI_LOG_RELEASE_INFO("Start ProcessMessages\n");
171 for(; iter != end; ++iter)
173 (*iter)->Process(0u /*ignored*/);
175 DALI_LOG_RELEASE_INFO("End ProcessMessages\n");
177 // release the processed messages from event side queue
178 mImpl->eventMessageQueue.Clear();
180 InterfaceContainer::Iterator iter2 = mImpl->eventInterfaceQueue.Begin();
181 const InterfaceContainer::Iterator end2 = mImpl->eventInterfaceQueue.End();
182 for(; iter2 != end2; ++iter2)
184 CompleteNotificationInterface* interface = *iter2;
187 interface->NotifyCompleted();
190 // just clear the container, we dont own the objects
191 mImpl->eventInterfaceQueue.Clear();
194 } // namespace Internal