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/internal/common/message.h>
25 #include <dali/internal/event/common/complete-notification-interface.h>
26 #include <dali/internal/event/common/property-notification-impl.h>
27 #include <dali/public-api/common/dali-common.h>
35 typedef Dali::Vector<CompleteNotificationInterface*> InterfaceContainer;
38 * helper to move elements from one container to another
39 * @param from where to move
40 * @param to move target
42 void MoveElements(InterfaceContainer& from, InterfaceContainer& to)
44 // check if there's something in from
45 const InterfaceContainer::SizeType fromCount = from.Count();
48 // check if to has some elements
49 const InterfaceContainer::SizeType toCount = to.Count();
52 // to is empty so we can swap with from
57 to.Reserve(toCount + fromCount);
58 for(InterfaceContainer::SizeType i = 0; i < fromCount; ++i)
68 using MessageQueueMutex = Dali::Mutex;
69 using MessageContainer = OwnerContainer<MessageBase*>;
71 struct NotificationManager::Impl
75 // reserve space on the vectors to avoid reallocs
76 // applications typically have up-to 20-30 notifications at startup
77 updateCompletedMessageQueue.Reserve(32);
78 updateWorkingMessageQueue.Reserve(32);
79 eventMessageQueue.Reserve(32);
81 // only a few manager objects get complete notifications (animation, render list, property notifications, ...)
82 updateCompletedInterfaceQueue.Reserve(4);
83 updateWorkingInterfaceQueue.Reserve(4);
84 eventInterfaceQueue.Reserve(4);
89 // queueMutex must be locked whilst accessing queue
90 MessageQueueMutex queueMutex;
91 // three queues for objects owned by notification manager
92 MessageContainer updateCompletedMessageQueue;
93 MessageContainer updateWorkingMessageQueue;
94 MessageContainer eventMessageQueue;
95 // three queues for objects referenced by notification manager
96 InterfaceContainer updateCompletedInterfaceQueue;
97 InterfaceContainer updateWorkingInterfaceQueue;
98 InterfaceContainer eventInterfaceQueue;
101 NotificationManager::NotificationManager()
106 NotificationManager::~NotificationManager()
111 void NotificationManager::QueueCompleteNotification(CompleteNotificationInterface* instance)
113 // queueMutex must be locked whilst accessing queues
114 MessageQueueMutex::ScopedLock lock(mImpl->queueMutex);
116 mImpl->updateWorkingInterfaceQueue.PushBack(instance);
119 void NotificationManager::QueueMessage(MessageBase* message)
121 DALI_ASSERT_DEBUG(NULL != message);
123 // queueMutex must be locked whilst accessing queues
124 MessageQueueMutex::ScopedLock lock(mImpl->queueMutex);
126 mImpl->updateWorkingMessageQueue.PushBack(message);
129 void NotificationManager::UpdateCompleted()
131 // queueMutex must be locked whilst accessing queues
132 MessageQueueMutex::ScopedLock lock(mImpl->queueMutex);
133 // Move messages from update working queue to completed queue
134 // note that in theory its possible for update completed to have last frames
135 // events as well still hanging around. we need to keep them as well
136 mImpl->updateCompletedMessageQueue.MoveFrom(mImpl->updateWorkingMessageQueue);
137 // move pointers from interface queue
138 MoveElements(mImpl->updateWorkingInterfaceQueue, mImpl->updateCompletedInterfaceQueue);
139 // finally the lock is released
142 bool NotificationManager::MessagesToProcess()
144 // queueMutex must be locked whilst accessing queues
145 MessageQueueMutex::ScopedLock lock(mImpl->queueMutex);
147 return (0u < mImpl->updateCompletedMessageQueue.Count() ||
148 (0u < mImpl->updateCompletedInterfaceQueue.Count()));
151 void NotificationManager::ProcessMessages()
153 // queueMutex must be locked whilst accessing queues
155 MessageQueueMutex::ScopedLock lock(mImpl->queueMutex);
157 // Move messages from update completed queue to event queue
158 // note that in theory its possible for event queue to have
159 // last frames events as well still hanging around so need to keep them
160 mImpl->eventMessageQueue.MoveFrom(mImpl->updateCompletedMessageQueue);
161 MoveElements(mImpl->updateCompletedInterfaceQueue, mImpl->eventInterfaceQueue);
163 // end of scope, lock is released
165 MessageContainer::Iterator iter = mImpl->eventMessageQueue.Begin();
166 const MessageContainer::Iterator end = mImpl->eventMessageQueue.End();
167 for(; iter != end; ++iter)
169 (*iter)->Process(0u /*ignored*/);
171 // release the processed messages from event side queue
172 mImpl->eventMessageQueue.Clear();
174 InterfaceContainer::Iterator iter2 = mImpl->eventInterfaceQueue.Begin();
175 const InterfaceContainer::Iterator end2 = mImpl->eventInterfaceQueue.End();
176 for(; iter2 != end2; ++iter2)
178 CompleteNotificationInterface* interface = *iter2;
181 interface->NotifyCompleted();
184 // just clear the container, we dont own the objects
185 mImpl->eventInterfaceQueue.Clear();
188 } // namespace Internal