END_TEST;
}
+int UtcDaliAnimationSignalOrder(void)
+{
+ TestApplication application;
+
+ Actor actor = Actor::New();
+ Stage::GetCurrent().Add( actor );
+
+ // Build the animations
+ Animation animation1 = Animation::New( 0.0f ); // finishes first frame
+ Animation animation2 = Animation::New( 0.02f ); // finishes in 20 ms
+
+ bool signal1Received = false;
+ animation1.FinishedSignal().Connect( &application, AnimationFinishCheck( signal1Received ) );
+
+ bool signal2Received = false;
+ animation2.FinishedSignal().Connect( &application, AnimationFinishCheck( signal2Received ) );
+
+ // Apply animations to actor
+ animation1.AnimateTo( Property(actor, Actor::POSITION), Vector3( 3.0f, 2.0f, 1.0f ), AlphaFunctions::Linear );
+ animation1.Play();
+ animation2.AnimateTo( Property(actor, Actor::SIZE ), Vector3( 10.0f, 20.0f, 30.0f ), AlphaFunctions::Linear );
+ animation2.Play();
+
+ DALI_TEST_EQUALS( signal1Received, false, TEST_LOCATION );
+ DALI_TEST_EQUALS( signal2Received, false, TEST_LOCATION );
+
+ application.SendNotification();
+ application.UpdateOnly( 10 ); // 10ms progress
+
+ // no notifications yet
+ DALI_TEST_EQUALS( signal1Received, false, TEST_LOCATION );
+ DALI_TEST_EQUALS( signal2Received, false, TEST_LOCATION );
+
+ application.SendNotification();
+
+ // first completed
+ DALI_TEST_EQUALS( signal1Received, true, TEST_LOCATION );
+ DALI_TEST_EQUALS( signal2Received, false, TEST_LOCATION );
+ signal1Received = false;
+
+ // 1st animation is complete now, do another update with no ProcessEvents in between
+ application.UpdateOnly( 20 ); // 20ms progress
+
+ // ProcessEvents
+ application.SendNotification();
+
+ // 2nd should complete now
+ DALI_TEST_EQUALS( signal1Received, false, TEST_LOCATION );
+ DALI_TEST_EQUALS( signal2Received, true, TEST_LOCATION );
+
+ END_TEST;
+}
}
END_TEST;
}
+
+static bool gCallBack2Called = false;
+void TestCallback2(PropertyNotification& source)
+{
+ gCallBack2Called = true;
+}
+
+int UtcDaliPropertyNotificationOrder(void)
+{
+ TestApplication application; // Reset all test adapter return codes
+
+ Actor actor = Actor::New();
+ Stage::GetCurrent().Add(actor);
+ // this should complete in first frame
+ PropertyNotification notification1 = actor.AddPropertyNotification( Actor::POSITION_X, GreaterThanCondition(90.0f) );
+ notification1.NotifySignal().Connect( &TestCallback );
+ // this should complete in second frame
+ PropertyNotification notification2 = actor.AddPropertyNotification( Actor::POSITION_X, GreaterThanCondition(150.0f) );
+ notification2.NotifySignal().Connect( &TestCallback2 );
+ Animation animation = Animation::New( 0.032f ); // finishes in 32 ms
+ animation.AnimateTo( Property(actor, Actor::POSITION ), Vector3( 200.0f, 0.0f, 0.0f ), AlphaFunctions::Linear );
+ animation.Play();
+
+ // flush the queue
+ application.SendNotification();
+ // first frame
+ application.Render(RENDER_FRAME_INTERVAL);
+ // no notifications yet
+ DALI_TEST_EQUALS( gCallBackCalled, false, TEST_LOCATION );
+ DALI_TEST_EQUALS( gCallBack2Called, false, TEST_LOCATION );
+ gCallBackCalled = false;
+ gCallBack2Called = false;
+
+ // dont serve the notifications but run another update & render
+ // this simulates situation where there is a notification in event side but it's not been picked up by event thread
+ // second frame
+ application.Render(RENDER_FRAME_INTERVAL);
+ DALI_TEST_EQUALS( gCallBackCalled, false, TEST_LOCATION );
+ DALI_TEST_EQUALS( gCallBack2Called, false, TEST_LOCATION );
+
+ // serve the notifications
+ application.SendNotification();
+ DALI_TEST_EQUALS( gCallBackCalled, true, TEST_LOCATION );
+ DALI_TEST_EQUALS( gCallBack2Called, true, TEST_LOCATION );
+
+ gCallBackCalled = false;
+ gCallBack2Called = false;
+ application.Render(RENDER_FRAME_INTERVAL);
+ application.SendNotification();
+ DALI_TEST_EQUALS( gCallBackCalled, false, TEST_LOCATION );
+ DALI_TEST_EQUALS( gCallBack2Called, false, TEST_LOCATION );
+
+ END_TEST;
+}
+++ /dev/null
-#ifndef __DALI_INTERNAL_MESSAGE_CONTAINER_H__
-#define __DALI_INTERNAL_MESSAGE_CONTAINER_H__
-
-/*
- * Copyright (c) 2014 Samsung Electronics Co., Ltd.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-// INTERNAL INCLUDES
-#include <dali/internal/common/message.h>
-#include <dali/internal/common/owner-container.h>
-
-namespace Dali
-{
-
-namespace Internal
-{
-
-typedef OwnerContainer< MessageBase* > MessageContainer;
-
-} // namespace Internal
-
-} // namespace Dali
-
-#endif // __DALI_INTERNAL_MESSAGE_CONTAINER_H__
Vector< T >::Resize( size );
}
+ /**
+ * Move the ownership of objects from another OwnerContainer to this one
+ * without deleting them. It will keep the original items here as well.
+ * @param[in] source where to move elements from to this OwnerContainer
+ */
+ void MoveFrom( OwnerContainer& source )
+ {
+ // Optimisation for the case that this is empty
+ if( IsEmpty() )
+ {
+ Swap( source );
+ }
+ else
+ {
+ // make space for new items
+ Reserve( VectorBase::Count() + source.Count() );
+ Iterator iter = source.Begin();
+ ConstIterator end = source.End();
+ for( ; iter != end; ++iter )
+ {
+ T pointer = *iter;
+ PushBack( pointer );
+ }
+ // cannot call Clear on OwnerContainer as that deletes the elements
+ source.Vector< T >::Clear();
+ }
+ }
+
private:
// Undefined copy constructor.
// CLASS HEADER
#include <dali/internal/event/common/notification-manager.h>
+#include <dali/internal/common/owner-container.h>
+#include <dali/internal/common/message.h>
// EXTERNAL INCLUDES
#ifdef __clang__
// INTERNAL INCLUDES
#include <dali/public-api/common/dali-common.h>
#include <dali/internal/event/common/property-notification-impl.h>
-#include <dali/internal/common/message-container.h>
-
-using namespace std;
namespace Dali
{
{
typedef boost::mutex MessageQueueMutex;
+typedef OwnerContainer< MessageBase* > MessageContainer;
struct NotificationManager::Impl
{
Impl()
: notificationCount(0)
{
+ // 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 );
}
~Impl()
{
DALI_ASSERT_DEBUG( NULL != message );
- // queueMutex must be locked whilst accessing queue
+ // queueMutex must be locked whilst accessing queues
MessageQueueMutex::scoped_lock lock( mImpl->queueMutex );
mImpl->updateWorkingQueue.PushBack( message );
void NotificationManager::UpdateCompleted()
{
- // queueMutex must be locked whilst accessing queue
+ // queueMutex must be locked whilst accessing queues
MessageQueueMutex::scoped_lock lock( mImpl->queueMutex );
- // Swap the queue, original queue ends up empty, then release the lock
- mImpl->updateCompletedQueue.Swap( mImpl->updateWorkingQueue );
+ // 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 );
+ // finally the lock is released
}
bool NotificationManager::MessagesToProcess()
{
- // queueMutex must be locked whilst accessing queue
+ // queueMutex must be locked whilst accessing queues
MessageQueueMutex::scoped_lock lock( mImpl->queueMutex );
return ( false == mImpl->updateCompletedQueue.IsEmpty() );
// 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 );
- // 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->eventQueue.MoveFrom( mImpl->updateCompletedQueue );
}
// end of scope, lock is released
*/
// INTERNAL INCLUDES
-#include <dali/internal/common/message.h>
namespace Dali
{
{
class PropertyNotification;
+class MessageBase;
/**
* Provides notifications to the event-thread regarding the changes in previous update(s).