X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=dali%2Finternal%2Fevent%2Fcommon%2Fnotification-manager.cpp;h=828586acbc5aa9abe943942f7635abb77a65300a;hb=ab5d2ee99a1b975867bf694b5cdeb15df01b9cb5;hp=bbddf2d8c79bae9f2bd3e2b7d328469e85602216;hpb=66b4d48e3b0a763f5b8c4544e6ae86195e2880ad;p=platform%2Fcore%2Fuifw%2Fdali-core.git diff --git a/dali/internal/event/common/notification-manager.cpp b/dali/internal/event/common/notification-manager.cpp index bbddf2d..828586a 100644 --- a/dali/internal/event/common/notification-manager.cpp +++ b/dali/internal/event/common/notification-manager.cpp @@ -17,60 +17,89 @@ // CLASS HEADER #include -#include -#include - -// EXTERNAL INCLUDES -#ifdef __clang__ -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wall" - -#include - -#pragma clang diagnostic pop -#else - -#include - -#endif // __clang__ // INTERNAL INCLUDES -#include +#include +#include +#include +#include +#include +#include #include +#include namespace Dali { - namespace Internal { +namespace +{ +typedef Dali::Vector InterfaceContainer; -typedef boost::mutex MessageQueueMutex; -typedef OwnerContainer< MessageBase* > MessageContainer; +DALI_INIT_TRACE_FILTER(gTraceFilter, DALI_TRACE_PERFORMANCE_MARKER, false); -struct NotificationManager::Impl +/** + * helper to move elements from one container to another + * @param from where to move + * @param to move target + */ +void MoveElements(InterfaceContainer& from, InterfaceContainer& to) { - Impl() - : notificationCount(0) + // check if there's something in from + const InterfaceContainer::SizeType fromCount = from.Count(); + if(fromCount > 0u) { - // reserve space on the vectors to avoid reallocs - // applications typically have upto 20-30 notifications at startup - updateCompletedQueue.Reserve( 32 ); - updateWorkingQueue.Reserve( 32 ); - eventQueue.Reserve( 32 ); + // check if to has some elements + const InterfaceContainer::SizeType toCount = to.Count(); + if(toCount == 0u) + { + // to is empty so we can swap with from + to.Swap(from); + } + else + { + to.Reserve(toCount + fromCount); + for(InterfaceContainer::SizeType i = 0; i < fromCount; ++i) + { + to.PushBack(from[i]); + } + from.Clear(); + } } +} +} // namespace - ~Impl() +using MessageQueueMutex = Dali::Mutex; +using MessageContainer = OwnerContainer; + +struct NotificationManager::Impl +{ + Impl() { + // reserve space on the vectors to avoid reallocs + // applications typically have up-to 20-30 notifications at startup + updateCompletedMessageQueue.Reserve(32); + updateWorkingMessageQueue.Reserve(32); + eventMessageQueue.Reserve(32); + + // only a few manager objects get complete notifications (animation, render list, property notifications, ...) + updateCompletedInterfaceQueue.Reserve(4); + updateWorkingInterfaceQueue.Reserve(4); + eventInterfaceQueue.Reserve(4); } - // Used to skip duplicate operations during Notify() - unsigned int notificationCount; + ~Impl() = default; // queueMutex must be locked whilst accessing queue MessageQueueMutex queueMutex; - MessageContainer updateCompletedQueue; - MessageContainer updateWorkingQueue; - MessageContainer eventQueue; + // three queues for objects owned by notification manager + MessageContainer updateCompletedMessageQueue; + MessageContainer updateWorkingMessageQueue; + MessageContainer eventMessageQueue; + // three queues for objects referenced by notification manager + InterfaceContainer updateCompletedInterfaceQueue; + InterfaceContainer updateWorkingInterfaceQueue; + InterfaceContainer eventInterfaceQueue; }; NotificationManager::NotificationManager() @@ -83,65 +112,91 @@ NotificationManager::~NotificationManager() delete mImpl; } -void NotificationManager::QueueMessage( MessageBase* message ) +void NotificationManager::QueueCompleteNotification(CompleteNotificationInterface* instance) +{ + // queueMutex must be locked whilst accessing queues + MessageQueueMutex::ScopedLock lock(mImpl->queueMutex); + + mImpl->updateWorkingInterfaceQueue.PushBack(instance); +} + +void NotificationManager::QueueMessage(MessageBase* message) { - DALI_ASSERT_DEBUG( NULL != message ); + DALI_ASSERT_DEBUG(NULL != message); // queueMutex must be locked whilst accessing queues - MessageQueueMutex::scoped_lock lock( mImpl->queueMutex ); + MessageQueueMutex::ScopedLock lock(mImpl->queueMutex); - mImpl->updateWorkingQueue.PushBack( message ); + mImpl->updateWorkingMessageQueue.PushBack(message); } void NotificationManager::UpdateCompleted() { // queueMutex must be locked whilst accessing queues - MessageQueueMutex::scoped_lock lock( mImpl->queueMutex ); + MessageQueueMutex::ScopedLock lock(mImpl->queueMutex); // Move messages from update working queue to completed queue // note that in theory its possible for update completed to have last frames // events as well still hanging around. we need to keep them as well - mImpl->updateCompletedQueue.MoveFrom( mImpl->updateWorkingQueue ); + mImpl->updateCompletedMessageQueue.MoveFrom(mImpl->updateWorkingMessageQueue); + // move pointers from interface queue + MoveElements(mImpl->updateWorkingInterfaceQueue, mImpl->updateCompletedInterfaceQueue); // finally the lock is released } bool NotificationManager::MessagesToProcess() { // queueMutex must be locked whilst accessing queues - MessageQueueMutex::scoped_lock lock( mImpl->queueMutex ); + MessageQueueMutex::ScopedLock lock(mImpl->queueMutex); - return ( false == mImpl->updateCompletedQueue.IsEmpty() ); + return (0u < mImpl->updateCompletedMessageQueue.Count() || + (0u < mImpl->updateCompletedInterfaceQueue.Count())); } void NotificationManager::ProcessMessages() { - // Done before messages are processed, for notification count comparisons - ++mImpl->notificationCount; - // queueMutex must be locked whilst accessing queues { - MessageQueueMutex::scoped_lock lock( mImpl->queueMutex ); + MessageQueueMutex::ScopedLock lock(mImpl->queueMutex); // Move messages from update completed queue to event queue // note that in theory its possible for event queue to have // last frames events as well still hanging around so need to keep them - mImpl->eventQueue.MoveFrom( mImpl->updateCompletedQueue ); + mImpl->eventMessageQueue.MoveFrom(mImpl->updateCompletedMessageQueue); + MoveElements(mImpl->updateCompletedInterfaceQueue, mImpl->eventInterfaceQueue); } // end of scope, lock is released - MessageContainer::Iterator iter = mImpl->eventQueue.Begin(); - MessageContainer::Iterator end = mImpl->eventQueue.End(); - for( ; iter != end; ++iter ) + MessageContainer::Iterator iter = mImpl->eventMessageQueue.Begin(); + const MessageContainer::Iterator end = mImpl->eventMessageQueue.End(); + if(iter != end) { - (*iter)->Process( 0u/*ignored*/ ); + DALI_TRACE_BEGIN(gTraceFilter, "DALI_NOTIFICATION_PROCESS_MESSAGE"); + for(; iter != end; ++iter) + { + (*iter)->Process(0u /*ignored*/); + } + DALI_TRACE_END(gTraceFilter, "DALI_NOTIFICATION_PROCESS_MESSAGE"); } - // release the processed messages from event side queue - mImpl->eventQueue.Clear(); -} + mImpl->eventMessageQueue.Clear(); -unsigned int NotificationManager::GetNotificationCount() const -{ - return mImpl->notificationCount; + InterfaceContainer::Iterator iter2 = mImpl->eventInterfaceQueue.Begin(); + const InterfaceContainer::Iterator end2 = mImpl->eventInterfaceQueue.End(); + if(iter2 != end2) + { + DALI_TRACE_BEGIN(gTraceFilter, "DALI_NOTIFICATION_NOTIFY_COMPLETED"); + for(; iter2 != end2; ++iter2) + { + CompleteNotificationInterface* interface = *iter2; + if(interface) + { + interface->NotifyCompleted(); + } + } + DALI_TRACE_END(gTraceFilter, "DALI_NOTIFICATION_NOTIFY_COMPLETED"); + } + // just clear the container, we dont own the objects + mImpl->eventInterfaceQueue.Clear(); } } // namespace Internal