X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=dali%2Finternal%2Fevent%2Fcommon%2Fnotification-manager.cpp;h=828586acbc5aa9abe943942f7635abb77a65300a;hb=ab5d2ee99a1b975867bf694b5cdeb15df01b9cb5;hp=dbebbeca79de1111d99b8358266c8dab794cc46e;hpb=4c0a88c52820b7471e15465ac7caf3c7165a0790;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 dbebbec..828586a 100644 --- a/dali/internal/event/common/notification-manager.cpp +++ b/dali/internal/event/common/notification-manager.cpp @@ -18,54 +18,88 @@ // CLASS HEADER #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 - -using namespace std; +#include namespace Dali { - namespace Internal { +namespace +{ +typedef Dali::Vector InterfaceContainer; -typedef boost::mutex MessageQueueMutex; +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) { + // 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() @@ -78,60 +112,91 @@ NotificationManager::~NotificationManager() delete mImpl; } -void NotificationManager::QueueMessage( MessageBase* message ) +void NotificationManager::QueueCompleteNotification(CompleteNotificationInterface* instance) { - DALI_ASSERT_DEBUG( NULL != message ); + // queueMutex must be locked whilst accessing queues + MessageQueueMutex::ScopedLock lock(mImpl->queueMutex); - // queueMutex must be locked whilst accessing queue - MessageQueueMutex::scoped_lock lock( mImpl->queueMutex ); + mImpl->updateWorkingInterfaceQueue.PushBack(instance); +} - mImpl->updateWorkingQueue.PushBack( message ); +void NotificationManager::QueueMessage(MessageBase* message) +{ + DALI_ASSERT_DEBUG(NULL != message); + + // queueMutex must be locked whilst accessing queues + MessageQueueMutex::ScopedLock lock(mImpl->queueMutex); + + mImpl->updateWorkingMessageQueue.PushBack(message); } void NotificationManager::UpdateCompleted() { - // queueMutex must be locked whilst accessing queue - MessageQueueMutex::scoped_lock lock( mImpl->queueMutex ); - // Swap the queue, original queue ends up empty, then release the lock - mImpl->updateCompletedQueue.Swap( mImpl->updateWorkingQueue ); + // queueMutex must be locked whilst accessing queues + 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->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 queue - MessageQueueMutex::scoped_lock lock( mImpl->queueMutex ); + // queueMutex must be locked whilst accessing queues + 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 queue + // queueMutex must be locked whilst accessing queues { - MessageQueueMutex::scoped_lock lock( mImpl->queueMutex ); + MessageQueueMutex::ScopedLock lock(mImpl->queueMutex); - // Swap the queue, original queue ends up empty, then release the lock - mImpl->updateCompletedQueue.Swap( mImpl->eventQueue ); + // 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->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