From: David Steele Date: Mon, 19 Oct 2020 13:35:41 +0000 (+0000) Subject: Merge "add base type of enum to reduce class size." into devel/master X-Git-Tag: dali_1.9.35~3 X-Git-Url: http://review.tizen.org/git/?p=platform%2Fcore%2Fuifw%2Fdali-core.git;a=commitdiff_plain;h=59b2ee3e18e36e7263c916ca1a2e2398878e8a91;hp=a574c54cfc69361385f8b8d6ade4482a93324a86 Merge "add base type of enum to reduce class size." into devel/master --- diff --git a/automated-tests/src/dali/utc-Dali-SignalTemplates.cpp b/automated-tests/src/dali/utc-Dali-SignalTemplates.cpp index e612ccb..d3a03fc 100644 --- a/automated-tests/src/dali/utc-Dali-SignalTemplates.cpp +++ b/automated-tests/src/dali/utc-Dali-SignalTemplates.cpp @@ -167,23 +167,16 @@ int UtcDaliSignalConnectP01(void) int UtcDaliSignalConnectN01(void) { - // difficult to perform a negative test on Connect as no checks are performed - // when creating a callback for a null function ( during Connect). - // so we test an assert on Emit TestApplication application; // Create core for debug logging TestSignals::VoidRetNoParamSignal signal; - signal.Connect(NULL); - try - { - signal.Emit(); - } - catch(Dali::DaliException& e) - { - // Tests that a negative test of an assertion succeeds - DALI_TEST_PRINT_ASSERT(e); - tet_result(TET_PASS); - } + signal.Connect(nullptr); + signal.Emit(); + + // No assert occurs any more - the callback is silently ignored. + // If we execute this code, then the test case didn't crash. + tet_result(TET_PASS); + END_TEST; } diff --git a/automated-tests/src/dali/utc-Dali-TouchProcessing.cpp b/automated-tests/src/dali/utc-Dali-TouchProcessing.cpp old mode 100644 new mode 100755 index 2aaf3e2..3c01346 --- a/automated-tests/src/dali/utc-Dali-TouchProcessing.cpp +++ b/automated-tests/src/dali/utc-Dali-TouchProcessing.cpp @@ -2068,3 +2068,56 @@ int UtcDaliTouchEventIntegNewTouchEvent(void) END_TEST; } + + +int UtcDaliTouchEventIntercept(void) +{ + TestApplication application; + + Actor parent = Actor::New(); + parent.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f)); + parent.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT); + application.GetScene().Add(parent); + + Actor actor = Actor::New(); + actor.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f)); + actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT); + parent.Add(actor); + + // Render and notify + application.SendNotification(); + application.Render(); + + // Connect to actor's touched signal + SignalData data; + TouchEventFunctor functor(data, false /* Do not consume */); + actor.TouchedSignal().Connect(&application, functor); + + + // Connect to parent's touched signal + SignalData parentData; + TouchEventFunctor parentFunctor(parentData, false /* Do not consume */); + parent.TouchedSignal().Connect(&application, parentFunctor); + // Connect to parent's intercept touched signal + SignalData interceptData; + TouchEventFunctor interceptFunctor(interceptData, true /* Do intercept */); + Dali::DevelActor::InterceptTouchedSignal(parent).Connect(&application, interceptFunctor); + + // Emit a down signal + application.ProcessEvent(GenerateSingleTouch(PointState::DOWN, Vector2(10.0f, 10.0f))); + // The actor touched signal is not called because the touch is intercepted in the parent. + DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION); + DALI_TEST_EQUALS(true, interceptData.functorCalled, TEST_LOCATION); + DALI_TEST_EQUALS(PointState::DOWN, interceptData.receivedTouch.points[0].state, TEST_LOCATION); + DALI_TEST_CHECK(actor == interceptData.receivedTouch.points[0].hitActor); + DALI_TEST_CHECK(parent == interceptData.touchedActor); + DALI_TEST_EQUALS(true, parentData.functorCalled, TEST_LOCATION); + DALI_TEST_EQUALS(PointState::DOWN, parentData.receivedTouch.points[0].state, TEST_LOCATION); + DALI_TEST_CHECK(actor == parentData.receivedTouch.points[0].hitActor); + DALI_TEST_CHECK(parent == parentData.touchedActor); + data.Reset(); + parentData.Reset(); + + END_TEST; +} + diff --git a/automated-tests/src/dali/utc-Dali-Vector.cpp b/automated-tests/src/dali/utc-Dali-Vector.cpp index f0dd410..7616cc0 100644 --- a/automated-tests/src/dali/utc-Dali-Vector.cpp +++ b/automated-tests/src/dali/utc-Dali-Vector.cpp @@ -1389,6 +1389,108 @@ int UtcDaliVectorMoveAssignment(void) END_TEST; } +int UtcDaliVectorEraseFreeFunction(void) +{ + tet_infoline("Testing Dali::Erase>"); + + Vector vector; + + // erasing from empty vector + Dali::Erase(vector, 2); + DALI_TEST_EQUALS(ZERO, vector.Count(), TEST_LOCATION); + DALI_TEST_EQUALS(ZERO, vector.Capacity(), TEST_LOCATION); + + + vector.PushBack(1); + vector.PushBack(2); + vector.PushBack(3); + vector.PushBack(4); + vector.PushBack(5); + vector.PushBack(3); + + // erase multiple value + Dali::Erase(vector, 3); + DALI_TEST_EQUALS(static_cast(4), vector.Count(), TEST_LOCATION); + + DALI_TEST_EQUALS(vector[0], 1, TEST_LOCATION); + DALI_TEST_EQUALS(vector[1], 2, TEST_LOCATION); + DALI_TEST_EQUALS(vector[2], 4, TEST_LOCATION); + DALI_TEST_EQUALS(vector[3], 5, TEST_LOCATION); + + + // erase an element present at start + Dali::Erase(vector, 1); + DALI_TEST_EQUALS(static_cast(3), vector.Count(), TEST_LOCATION); + DALI_TEST_EQUALS(vector[0], 2, TEST_LOCATION); + DALI_TEST_EQUALS(vector[1], 4, TEST_LOCATION); + DALI_TEST_EQUALS(vector[2], 5, TEST_LOCATION); + + // erase an element present at end + Dali::Erase(vector, 5); + DALI_TEST_EQUALS(static_cast(2), vector.Count(), TEST_LOCATION); + DALI_TEST_EQUALS(vector[0], 2, TEST_LOCATION); + DALI_TEST_EQUALS(vector[1], 4, TEST_LOCATION); + + // erase an element not present in the vector + Dali::Erase(vector, 42); + DALI_TEST_EQUALS(static_cast(2), vector.Count(), TEST_LOCATION); + DALI_TEST_EQUALS(vector[0], 2, TEST_LOCATION); + DALI_TEST_EQUALS(vector[1], 4, TEST_LOCATION); + + END_TEST; +} + +int UtcDaliVectorEraseIfFreeFunction(void) +{ + tet_infoline("Testing Dali::EraseIf>"); + + Vector vector; + + // erasing from empty vector + Dali::EraseIf(vector, [](const auto & value) {return value == 2;}); + DALI_TEST_EQUALS(ZERO, vector.Count(), TEST_LOCATION); + DALI_TEST_EQUALS(ZERO, vector.Capacity(), TEST_LOCATION); + + + vector.PushBack(1); + vector.PushBack(2); + vector.PushBack(3); + vector.PushBack(4); + vector.PushBack(5); + vector.PushBack(3); + + // erase multiple value + Dali::EraseIf(vector, [](const auto & value) {return value == 3;}); + DALI_TEST_EQUALS(static_cast(4), vector.Count(), TEST_LOCATION); + + DALI_TEST_EQUALS(vector[0], 1, TEST_LOCATION); + DALI_TEST_EQUALS(vector[1], 2, TEST_LOCATION); + DALI_TEST_EQUALS(vector[2], 4, TEST_LOCATION); + DALI_TEST_EQUALS(vector[3], 5, TEST_LOCATION); + + + // erase an element present at start + Dali::EraseIf(vector, [](const auto & value) {return value == 1;}); + DALI_TEST_EQUALS(static_cast(3), vector.Count(), TEST_LOCATION); + DALI_TEST_EQUALS(vector[0], 2, TEST_LOCATION); + DALI_TEST_EQUALS(vector[1], 4, TEST_LOCATION); + DALI_TEST_EQUALS(vector[2], 5, TEST_LOCATION); + + // erase an element present at end + Dali::EraseIf(vector, [](const auto & value) {return value == 5;}); + DALI_TEST_EQUALS(static_cast(2), vector.Count(), TEST_LOCATION); + DALI_TEST_EQUALS(vector[0], 2, TEST_LOCATION); + DALI_TEST_EQUALS(vector[1], 4, TEST_LOCATION); + + // erase an element not present in the vector + Dali::EraseIf(vector, [](const auto & value) {return value == 42;}); + DALI_TEST_EQUALS(static_cast(2), vector.Count(), TEST_LOCATION); + DALI_TEST_EQUALS(vector[0], 2, TEST_LOCATION); + DALI_TEST_EQUALS(vector[1], 4, TEST_LOCATION); + + END_TEST; +} + /* * this does not compile at the moment * Vector< Actor > classvector; this does not compile yet either diff --git a/dali/devel-api/actors/actor-devel.cpp b/dali/devel-api/actors/actor-devel.cpp old mode 100644 new mode 100755 index 68a5205..fd08434 --- a/dali/devel-api/actors/actor-devel.cpp +++ b/dali/devel-api/actors/actor-devel.cpp @@ -48,6 +48,11 @@ ChildOrderChangedSignalType& ChildOrderChangedSignal(Actor actor) return GetImplementation(actor).ChildOrderChangedSignal(); } +Actor::TouchEventSignalType& InterceptTouchedSignal(Actor actor) +{ + return GetImplementation(actor).InterceptTouchedSignal(); +} + } // namespace DevelActor } // namespace Dali diff --git a/dali/devel-api/actors/actor-devel.h b/dali/devel-api/actors/actor-devel.h old mode 100644 new mode 100755 index 43b44f7..cda374f --- a/dali/devel-api/actors/actor-devel.h +++ b/dali/devel-api/actors/actor-devel.h @@ -215,6 +215,40 @@ using ChildOrderChangedSignalType = Signal; ///< Used when the acto */ DALI_CORE_API ChildOrderChangedSignalType& ChildOrderChangedSignal(Actor actor); +/** + * @brief This signal is emitted when intercepting the actor's touch event. + * + * A callback of the following type may be connected: + * @code + * void MyCallbackName( Actor actor ); + * @endcode + * actor The actor to intercept + * + * @note TouchEvent callbacks are called from the last child in the order of the parent's actor. + * The InterceptTouchEvent callback is to intercept the touch event in the parent. + * So, if the parent interepts the touch event, the child cannot receive the touch event. + * + * @note example + * Actor parent = Actor::New(); + * Actor child = Actor::New(); + * parent.Add(child); + * child.TouchedSignal().Connect(&application, childFunctor); + * parent.TouchedSignal().Connect(&application, parentFunctor); + * The touch event callbacks are called in the order childFunctor -> parentFunctor. + * + * If you connect interceptTouchSignal to parentActor. + * Dali::DevelActor::InterceptTouchedSignal(parent).Connect(&application, interceptFunctor); + * + * When interceptFunctor returns false, the touch event callbacks are called in the same order childFunctor -> parentFunctor. + * If interceptFunctor returns true, it means that the TouchEvent was intercepted. + * So the child actor will not be able to receive touch events. + * Only the parentFunctor is called. + * + * @return The signal to connect to + * @pre The Actor has been initialized + */ +DALI_CORE_API Actor::TouchEventSignalType& InterceptTouchedSignal(Actor actor); + } // namespace DevelActor } // namespace Dali diff --git a/dali/internal/event/actors/actor-impl.cpp b/dali/internal/event/actors/actor-impl.cpp old mode 100644 new mode 100755 index 321b111..4fdf0c2 --- a/dali/internal/event/actors/actor-impl.cpp +++ b/dali/internal/event/actors/actor-impl.cpp @@ -836,6 +836,8 @@ void Actor::SetOpacity( float opacity ) // node is being used in a separate thread; queue a message to set the value & base value SceneGraph::NodePropertyComponentMessage::Send( GetEventThreadServices(), &GetNode(), &GetNode().mColor, &AnimatableProperty::BakeW, opacity ); + + RequestRenderingMessage( GetEventThreadServices().GetUpdateManager() ); } float Actor::GetCurrentOpacity() const @@ -855,6 +857,8 @@ void Actor::SetColor( const Vector4& color ) // node is being used in a separate thread; queue a message to set the value & base value SceneGraph::NodePropertyMessage::Send( GetEventThreadServices(), &GetNode(), &GetNode().mColor, &AnimatableProperty::Bake, color ); + + RequestRenderingMessage( GetEventThreadServices().GetUpdateManager() ); } void Actor::SetColorRed( float red ) @@ -863,6 +867,8 @@ void Actor::SetColorRed( float red ) // node is being used in a separate thread; queue a message to set the value & base value SceneGraph::NodePropertyComponentMessage::Send( GetEventThreadServices(), &GetNode(), &GetNode().mColor, &AnimatableProperty::BakeX, red ); + + RequestRenderingMessage( GetEventThreadServices().GetUpdateManager() ); } void Actor::SetColorGreen( float green ) @@ -871,6 +877,8 @@ void Actor::SetColorGreen( float green ) // node is being used in a separate thread; queue a message to set the value & base value SceneGraph::NodePropertyComponentMessage::Send( GetEventThreadServices(), &GetNode(), &GetNode().mColor, &AnimatableProperty::BakeY, green ); + + RequestRenderingMessage( GetEventThreadServices().GetUpdateManager() ); } void Actor::SetColorBlue( float blue ) @@ -879,6 +887,8 @@ void Actor::SetColorBlue( float blue ) // node is being used in a separate thread; queue a message to set the value & base value SceneGraph::NodePropertyComponentMessage::Send( GetEventThreadServices(), &GetNode(), &GetNode().mColor, &AnimatableProperty::BakeZ, blue ); + + RequestRenderingMessage( GetEventThreadServices().GetUpdateManager() ); } const Vector4& Actor::GetCurrentColor() const @@ -1319,6 +1329,11 @@ bool Actor::IsGestureRequired( GestureType::Value type ) const return mGestureData && mGestureData->IsGestureRequired( type ); } +bool Actor::EmitInterceptTouchEventSignal( const Dali::TouchEvent& touch ) +{ + return EmitConsumingSignal( *this, mInterceptTouchedSignal, touch ); +} + bool Actor::EmitTouchEventSignal( const Dali::TouchEvent& touch ) { return EmitConsumingSignal( *this, mTouchedSignal, touch ); @@ -1418,6 +1433,7 @@ Actor::Actor( DerivedType derivedType, const SceneGraph::Node& node ) mAnchorPoint( nullptr ), mRelayoutData( nullptr ), mGestureData( nullptr ), + mInterceptTouchedSignal(), mTouchedSignal(), mHoveredSignal(), mWheelEventSignal(), @@ -2492,6 +2508,8 @@ void Actor::SetVisibleInternal( bool visible, SendMessage::Type sendMessage ) { // node is being used in a separate thread; queue a message to set the value & base value SceneGraph::NodePropertyMessage::Send( GetEventThreadServices(), &GetNode(), &GetNode().mVisible, &AnimatableProperty::Bake, visible ); + + RequestRenderingMessage( GetEventThreadServices().GetUpdateManager() ); } mVisible = visible; diff --git a/dali/internal/event/actors/actor-impl.h b/dali/internal/event/actors/actor-impl.h old mode 100644 new mode 100755 index 5a11cd0..a982904 --- a/dali/internal/event/actors/actor-impl.h +++ b/dali/internal/event/actors/actor-impl.h @@ -1326,6 +1326,16 @@ public: return mKeyboardFocusable; } + + /** + * Query whether the application or derived actor type requires intercept touch events. + * @return True if intercept touch events are required. + */ + bool GetInterceptTouchRequired() const + { + return !mInterceptTouchedSignal.Empty(); + } + /** * Query whether the application or derived actor type requires touch events. * @return True if touch events are required. @@ -1394,6 +1404,13 @@ public: // Signals /** + * Used by the EventProcessor to emit intercept touch event signals. + * @param[in] touch The touch data. + * @return True if the event was intercepted. + */ + bool EmitInterceptTouchEventSignal( const Dali::TouchEvent& touch ); + + /** * Used by the EventProcessor to emit touch event signals. * @param[in] touch The touch data. * @return True if the event was consumed. @@ -1440,6 +1457,14 @@ public: void EmitChildRemovedSignal( Actor& child ); /** + * @copydoc DevelActor::InterceptTouchedSignal() + */ + Dali::Actor::TouchEventSignalType& InterceptTouchedSignal() + { + return mInterceptTouchedSignal; + } + + /** * @copydoc Dali::Actor::TouchedSignal() */ Dali::Actor::TouchEventSignalType& TouchedSignal() @@ -1982,6 +2007,7 @@ protected: ActorGestureData* mGestureData; ///< Optional Gesture data. Only created when actor requires gestures // Signals + Dali::Actor::TouchEventSignalType mInterceptTouchedSignal; Dali::Actor::TouchEventSignalType mTouchedSignal; Dali::Actor::HoverSignalType mHoveredSignal; Dali::Actor::WheelEventSignalType mWheelEventSignal; diff --git a/dali/internal/event/events/touch-event-processor.cpp b/dali/internal/event/events/touch-event-processor.cpp old mode 100644 new mode 100755 index 864ce8c..146387c --- a/dali/internal/event/events/touch-event-processor.cpp +++ b/dali/internal/event/events/touch-event-processor.cpp @@ -60,6 +60,36 @@ const char * TOUCH_POINT_STATE[ 6 ] = #endif // defined(DEBUG_ENABLED) +Dali::Actor EmitInterceptTouchSignals( Dali::Actor actor, const Dali::TouchEvent& touchEvent ) +{ + Dali::Actor interceptedActor; + + if( actor ) + { + Dali::Actor parent = actor.GetParent(); + if( parent ) + { + // Recursively deliver events to the actor and its parents for intercept touch event. + interceptedActor = EmitInterceptTouchSignals( parent, touchEvent ); + } + + if( !interceptedActor ) + { + bool intercepted = false; + Actor& actorImpl( GetImplementation(actor) ); + if( actorImpl.GetInterceptTouchRequired() ) + { + intercepted = actorImpl.EmitInterceptTouchEventSignal( touchEvent ); + if( intercepted ) + { + interceptedActor = Dali::Actor( &actorImpl ); + } + } + } + } + + return interceptedActor; +} /** * Recursively deliver events to the actor and its parents, until the event is consumed or the stage is reached. @@ -315,7 +345,16 @@ bool TouchEventProcessor::ProcessTouchEvent( const Integration::TouchEvent& even Dali::Actor consumedActor; if ( currentRenderTask ) { - consumedActor = EmitTouchSignals( touchEventImpl->GetPoint( 0 ).GetHitActor(), touchEventHandle ); + // Emit the intercept touch signal + Dali::Actor interceptedActor = EmitInterceptTouchSignals( touchEventImpl->GetPoint( 0 ).GetHitActor(), touchEventHandle ); + if( interceptedActor ) + { + consumedActor = EmitTouchSignals( interceptedActor, touchEventHandle ); + } + else + { + consumedActor = EmitTouchSignals( touchEventImpl->GetPoint( 0 ).GetHitActor(), touchEventHandle ); + } consumed = consumedActor ? true : false; } diff --git a/dali/internal/render/common/render-algorithms.cpp b/dali/internal/render/common/render-algorithms.cpp index f5d540c..d40614c 100755 --- a/dali/internal/render/common/render-algorithms.cpp +++ b/dali/internal/render/common/render-algorithms.cpp @@ -442,6 +442,22 @@ inline void RenderAlgorithms::ProcessRenderList( const RenderList& renderList, { const RenderItem& item = renderList.GetItem( index ); + // Discard renderers outside the root clipping rect + bool skip = true; + if( !rootClippingRect.IsEmpty() ) + { + auto rect = item.CalculateViewportSpaceAABB( item.mUpdateSize, mViewportRectangle.width, mViewportRectangle.height ); + + if(rect.Intersect( rootClippingRect )) + { + skip = false; + } + } + else + { + skip = false; + } + DALI_PRINT_RENDER_ITEM( item ); // Set up clipping based on both the Renderer and Actor APIs. @@ -455,9 +471,9 @@ inline void RenderAlgorithms::ProcessRenderList( const RenderList& renderList, // draw-mode state, such as Overlays. // If the flags are set to "AUTO", the behavior then depends on the type of renderer. Overlay Renderers will always // disable depth testing and writing. Color Renderers will enable them if the Layer does. - if( depthBufferAvailable == Integration::DepthBufferAvailable::TRUE ) + if (depthBufferAvailable == Integration::DepthBufferAvailable::TRUE) { - SetupDepthBuffer( item, context, autoDepthTestMode, firstDepthBufferUse ); + SetupDepthBuffer(item, context, autoDepthTestMode, firstDepthBufferUse); } // Depending on whether the renderer has draw commands attached or not the rendering process will @@ -465,12 +481,15 @@ inline void RenderAlgorithms::ProcessRenderList( const RenderList& renderList, // iteration must be done and the default behaviour of the renderer will be executed. // The queues allow to iterate over the same renderer multiple times changing the state of the renderer. // It is similar to the multi-pass rendering. - auto const MAX_QUEUE = item.mRenderer->GetDrawCommands().empty() ? 1 : DevelRenderer::RENDER_QUEUE_MAX; - for( auto queue = 0u; queue < MAX_QUEUE; ++queue ) + if( !skip ) { - // Render the item. - item.mRenderer->Render(context, bufferIndex, *item.mNode, item.mModelMatrix, item.mModelViewMatrix, - viewMatrix, projectionMatrix, item.mSize, !item.mIsOpaque, boundTextures, instruction, queue); + auto const MAX_QUEUE = item.mRenderer->GetDrawCommands().empty() ? 1 : DevelRenderer::RENDER_QUEUE_MAX; + for (auto queue = 0u; queue < MAX_QUEUE; ++queue) + { + // Render the item. + item.mRenderer->Render(context, bufferIndex, *item.mNode, item.mModelMatrix, item.mModelViewMatrix, + viewMatrix, projectionMatrix, item.mSize, !item.mIsOpaque, boundTextures, instruction, queue); + } } } } diff --git a/dali/internal/update/animation/scene-graph-animation.cpp b/dali/internal/update/animation/scene-graph-animation.cpp index f0d961d..bd4656f 100644 --- a/dali/internal/update/animation/scene-graph-animation.cpp +++ b/dali/internal/update/animation/scene-graph-animation.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019 Samsung Electronics Co., Ltd. + * Copyright (c) 2020 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. @@ -78,7 +78,8 @@ Animation::Animation( float durationSeconds, float speedFactor, const Vector2& p mDisconnectAction(disconnectAction), mState(Stopped), mProgressReachedSignalRequired( false ), - mAutoReverseEnabled( false ) + mAutoReverseEnabled( false ), + mIsActive{ false } { } @@ -426,6 +427,8 @@ void Animation::Update( BufferIndex bufferIndex, float elapsedSeconds, bool& loo void Animation::UpdateAnimators( BufferIndex bufferIndex, bool bake, bool animationFinished ) { + mIsActive[bufferIndex] = false; + const Vector2 playRange( mPlayRange * mDurationSeconds ); float elapsedSecondsClamped = Clamp( mElapsedSeconds, playRange.x, playRange.y ); @@ -456,6 +459,11 @@ void Animation::UpdateAnimators( BufferIndex bufferIndex, bool bake, bool animat progress = Clamp((elapsedSecondsClamped - intervalDelay) / animatorDuration, 0.0f , 1.0f ); } animator->Update(bufferIndex, progress, bake); + + if (animatorDuration > 0.0f && (elapsedSecondsClamped - intervalDelay) <= animatorDuration) + { + mIsActive[bufferIndex] = true; + } } applied = true; } diff --git a/dali/internal/update/animation/scene-graph-animation.h b/dali/internal/update/animation/scene-graph-animation.h index a4e309f..0617041 100644 --- a/dali/internal/update/animation/scene-graph-animation.h +++ b/dali/internal/update/animation/scene-graph-animation.h @@ -2,7 +2,7 @@ #define DALI_INTERNAL_SCENE_GRAPH_ANIMATION_H /* - * Copyright (c) 2019 Samsung Electronics Co., Ltd. + * Copyright (c) 2020 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. @@ -259,6 +259,16 @@ public: } /** + * Query whether the animation is currently active (i.e. at least one of the animators has been updated in either frame) + * @return True if the animation is currently active + */ + bool IsActive() const + { + // As we have double buffering, if animator is updated in either frame, it needs to be rendered. + return mIsActive[0] || mIsActive[1]; + } + + /** * @brief Sets the looping mode. * * Animation plays forwards and then restarts from the beginning or runs backwards again. @@ -349,6 +359,7 @@ protected: bool mProgressReachedSignalRequired; // Flag to indicate the progress marker was hit bool mAutoReverseEnabled; // Flag to identify that the looping mode is auto reverse. + bool mIsActive[2]; // Flag to indicate whether the animation is active in the current frame (which is double buffered) }; }; //namespace SceneGraph diff --git a/dali/internal/update/manager/transform-manager.cpp b/dali/internal/update/manager/transform-manager.cpp index c2cc4bb..7951e32 100644 --- a/dali/internal/update/manager/transform-manager.cpp +++ b/dali/internal/update/manager/transform-manager.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018 Samsung Electronics Co., Ltd. + * Copyright (c) 2020 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. @@ -229,8 +229,10 @@ void TransformManager::ResetToBaseValue() } } -void TransformManager::Update() +bool TransformManager::Update() { + bool componentsChanged = false; + if( mReorder ) { //If some transform component has change its parent or has been removed since last update @@ -322,8 +324,11 @@ void TransformManager::Update() mBoundingSpheres[i] = mWorld[i].GetTranslation(); mBoundingSpheres[i].w = Length( centerToEdgeWorldSpace ); + componentsChanged = componentsChanged || mComponentDirty[i]; mComponentDirty[i] = false; } + + return componentsChanged; } void TransformManager::SwapComponents( unsigned int i, unsigned int j ) @@ -382,31 +387,26 @@ Vector3& TransformManager::GetVector3PropertyValue( TransformId id, TransformMan case TRANSFORM_PROPERTY_POSITION: { TransformId index( mIds[id] ); - mComponentDirty[ index ] = true; return mTxComponentAnimatable[ index ].mPosition; } case TRANSFORM_PROPERTY_SCALE: { TransformId index( mIds[id] ); - mComponentDirty[ index ] = true; return mTxComponentAnimatable[ index ].mScale; } case TRANSFORM_PROPERTY_PARENT_ORIGIN: { TransformId index( mIds[id] ); - mComponentDirty[ index ] = true; return mTxComponentStatic[ index ].mParentOrigin; } case TRANSFORM_PROPERTY_ANCHOR_POINT: { TransformId index( mIds[id] ); - mComponentDirty[ index ] = true; return mTxComponentStatic[ index ].mAnchorPoint; } case TRANSFORM_PROPERTY_SIZE: { TransformId index( mIds[id] ); - mComponentDirty[ index ] = true; return mSize[ index ]; } default: @@ -835,7 +835,6 @@ void TransformManager::BakeZVector3PropertyValue( TransformId id, TransformManag Quaternion& TransformManager::GetQuaternionPropertyValue( TransformId id ) { TransformId index( mIds[id] ); - mComponentDirty[ index ] = true; return mTxComponentAnimatable[ index ].mOrientation; } diff --git a/dali/internal/update/manager/transform-manager.h b/dali/internal/update/manager/transform-manager.h index d003f57..068c39ff 100644 --- a/dali/internal/update/manager/transform-manager.h +++ b/dali/internal/update/manager/transform-manager.h @@ -2,7 +2,7 @@ #define DALI_INTERNAL_TRANSFORM_MANAGER_H /* - * Copyright (c) 2018 Samsung Electronics Co., Ltd. + * Copyright (c) 2020 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. @@ -192,8 +192,9 @@ public: /** * Recomputes all world transform matrices + * @return true if any component has been changed in this frame, false otherwise */ - void Update(); + bool Update(); /** * Resets all the animatable properties to its base value diff --git a/dali/internal/update/manager/update-manager.cpp b/dali/internal/update/manager/update-manager.cpp index 58fb0bc..a7ca327 100644 --- a/dali/internal/update/manager/update-manager.cpp +++ b/dali/internal/update/manager/update-manager.cpp @@ -189,7 +189,8 @@ struct UpdateManager::Impl previousUpdateScene( false ), renderTaskWaiting( false ), renderersAdded( false ), - surfaceRectChanged( false ) + surfaceRectChanged( false ), + renderingRequired( false ) { sceneController = new SceneControllerImpl( renderMessageDispatcher, renderQueue, discardQueue ); @@ -298,6 +299,7 @@ struct UpdateManager::Impl bool renderTaskWaiting; ///< A REFRESH_ONCE render task is waiting to be rendered bool renderersAdded; ///< Flag to keep track when renderers have been added to avoid unnecessary processing bool surfaceRectChanged; ///< True if the default surface rect is changed + bool renderingRequired; ///< True if required to render the current frame private: @@ -734,8 +736,10 @@ bool UpdateManager::ProcessGestures( BufferIndex bufferIndex, uint32_t lastVSync return gestureUpdated; } -void UpdateManager::Animate( BufferIndex bufferIndex, float elapsedSeconds ) +bool UpdateManager::Animate( BufferIndex bufferIndex, float elapsedSeconds ) { + bool animationActive = false; + auto&& iter = mImpl->animations.Begin(); bool animationLooped = false; @@ -747,6 +751,8 @@ void UpdateManager::Animate( BufferIndex bufferIndex, float elapsedSeconds ) bool progressMarkerReached = false; animation->Update( bufferIndex, elapsedSeconds, looped, finished, progressMarkerReached ); + animationActive = animationActive || animation->IsActive(); + if ( progressMarkerReached ) { mImpl->notificationManager.QueueMessage( Internal::NotifyProgressReachedMessage( mImpl->animationPlaylist, animation ) ); @@ -772,6 +778,8 @@ void UpdateManager::Animate( BufferIndex bufferIndex, float elapsedSeconds ) // The application should be notified by NotificationManager, in another thread mImpl->notificationManager.QueueCompleteNotification( &mImpl->animationPlaylist ); } + + return animationActive; } void UpdateManager::ConstrainCustomObjects( BufferIndex bufferIndex ) @@ -852,7 +860,7 @@ void UpdateManager::UpdateRenderers( BufferIndex bufferIndex ) //Apply constraints ConstrainPropertyOwner( *renderer, bufferIndex ); - renderer->PrepareRender( bufferIndex ); + mImpl->renderingRequired = renderer->PrepareRender( bufferIndex ) || mImpl->renderingRequired; } } @@ -884,17 +892,20 @@ uint32_t UpdateManager::Update( float elapsedSeconds, //Clear nodes/resources which were previously discarded mImpl->discardQueue.Clear( bufferIndex ); + bool isAnimationRunning = IsAnimationRunning(); + //Process Touches & Gestures const bool gestureUpdated = ProcessGestures( bufferIndex, lastVSyncTimeMilliseconds, nextVSyncTimeMilliseconds ); bool updateScene = // The scene-graph requires an update if.. (mImpl->nodeDirtyFlags & RenderableUpdateFlags) || // ..nodes were dirty in previous frame OR - IsAnimationRunning() || // ..at least one animation is running OR + isAnimationRunning || // ..at least one animation is running OR mImpl->messageQueue.IsSceneUpdateRequired() || // ..a message that modifies the scene graph node tree is queued OR mImpl->frameCallbackProcessor || // ..a frame callback processor is existed OR gestureUpdated; // ..a gesture property was updated bool keepRendererRendering = false; + mImpl->renderingRequired = false; // Although the scene-graph may not require an update, we still need to synchronize double-buffered // values if the scene was updated in the previous frame. @@ -919,7 +930,7 @@ uint32_t UpdateManager::Update( float elapsedSeconds, if( updateScene || mImpl->previousUpdateScene ) { //Animate - Animate( bufferIndex, elapsedSeconds ); + bool animationActive = Animate( bufferIndex, elapsedSeconds ); //Constraint custom objects ConstrainCustomObjects( bufferIndex ); @@ -957,7 +968,10 @@ uint32_t UpdateManager::Update( float elapsedSeconds, UpdateRenderers( bufferIndex ); //Update the transformations of all the nodes - mImpl->transformManager.Update(); + if ( mImpl->transformManager.Update() ) + { + mImpl->nodeDirtyFlags |= NodePropertyFlags::TRANSFORM; + } //Process Property Notifications ProcessPropertyNotifications( bufferIndex ); @@ -982,7 +996,6 @@ uint32_t UpdateManager::Update( float elapsedSeconds, } } - std::size_t numberOfRenderInstructions = 0; for ( auto&& scene : mImpl->scenes ) { @@ -991,13 +1004,19 @@ uint32_t UpdateManager::Update( float elapsedSeconds, scene->scene->GetRenderInstructions().ResetAndReserve( bufferIndex, static_cast( scene->taskList->GetTasks().Count() ) ); - keepRendererRendering |= mImpl->renderTaskProcessor.Process( bufferIndex, - *scene->taskList, - *scene->root, - scene->sortedLayerList, - scene->scene->GetRenderInstructions(), - renderToFboEnabled, - isRenderingToFbo ); + // If there are animations running, only add render instruction if at least one animation is currently active (i.e. not delayed) + // or the nodes are dirty + if ( !isAnimationRunning || animationActive || mImpl->renderingRequired || (mImpl->nodeDirtyFlags & RenderableUpdateFlags) ) + { + keepRendererRendering |= mImpl->renderTaskProcessor.Process( bufferIndex, + *scene->taskList, + *scene->root, + scene->sortedLayerList, + scene->scene->GetRenderInstructions(), + renderToFboEnabled, + isRenderingToFbo ); + + } numberOfRenderInstructions += scene->scene->GetRenderInstructions().Count( bufferIndex ); } @@ -1139,6 +1158,11 @@ void UpdateManager::SetRenderingBehavior( DevelStage::Rendering renderingBehavio mImpl->renderingBehavior = renderingBehavior; } +void UpdateManager::RequestRendering() +{ + mImpl->renderingRequired = true; +} + void UpdateManager::SetLayerDepths( const SortedLayerPointers& layers, const Layer* rootLayer ) { for ( auto&& scene : mImpl->scenes ) diff --git a/dali/internal/update/manager/update-manager.h b/dali/internal/update/manager/update-manager.h index bf5d3e4..3368970 100644 --- a/dali/internal/update/manager/update-manager.h +++ b/dali/internal/update/manager/update-manager.h @@ -646,6 +646,14 @@ public: void SetRenderingBehavior( DevelStage::Rendering renderingBehavior ); /** + * Request to render the current frame + * @note This is a temporary workaround (to be removed in the future) to request the rendering of + * the current frame if the color or visibility of any actor is updated. It MUST NOT be used + * for any other purposes. + */ + void RequestRendering(); + + /** * Sets the depths of all layers. * @param layers The layers in depth order. * @param[in] rootLayer The root layer of the sorted layers. @@ -711,8 +719,9 @@ private: * Perform animation updates * @param[in] bufferIndex to use * @param[in] elapsedSeconds time since last frame + * @return true if at least one animations is currently active or false otherwise */ - void Animate( BufferIndex bufferIndex, float elapsedSeconds ); + bool Animate( BufferIndex bufferIndex, float elapsedSeconds ); /** * Applies constraints to CustomObjects @@ -1110,6 +1119,17 @@ inline void SetRenderingBehaviorMessage( UpdateManager& manager, DevelStage::Ren new (slot) LocalType( &manager, &UpdateManager::SetRenderingBehavior, renderingBehavior ); } +inline void RequestRenderingMessage( UpdateManager& manager ) +{ + using LocalType = Message; + + // Reserve some memory inside the message queue + uint32_t* slot = manager.ReserveMessageSlot( sizeof( LocalType ) ); + + // Construct message in the message queue memory; note that delete should not be called on the return value + new (slot) LocalType( &manager, &UpdateManager::RequestRendering ); +} + /** * Create a message for setting the depth of a layer * @param[in] manager The update manager diff --git a/dali/internal/update/rendering/scene-graph-renderer.cpp b/dali/internal/update/rendering/scene-graph-renderer.cpp index e821f6e..cce7464 100644 --- a/dali/internal/update/rendering/scene-graph-renderer.cpp +++ b/dali/internal/update/rendering/scene-graph-renderer.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018 Samsung Electronics Co., Ltd. + * Copyright (c) 2020 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. @@ -181,7 +181,7 @@ void Renderer::operator delete( void* ptr ) } -void Renderer::PrepareRender( BufferIndex updateBufferIndex ) +bool Renderer::PrepareRender( BufferIndex updateBufferIndex ) { if( mRegenerateUniformMap == UNIFORM_MAP_READY ) { @@ -221,6 +221,8 @@ void Renderer::PrepareRender( BufferIndex updateBufferIndex ) mRegenerateUniformMap--; } + bool rendererUpdated = mUniformMapChanged[updateBufferIndex] || mResendFlag; + if( mResendFlag != 0 ) { if( mResendFlag & RESEND_GEOMETRY ) @@ -365,6 +367,8 @@ void Renderer::PrepareRender( BufferIndex updateBufferIndex ) mResendFlag = 0; } + + return rendererUpdated; } void Renderer::SetTextures( TextureSet* textureSet ) diff --git a/dali/internal/update/rendering/scene-graph-renderer.h b/dali/internal/update/rendering/scene-graph-renderer.h index b3ab63e..a06fa2a 100644 --- a/dali/internal/update/rendering/scene-graph-renderer.h +++ b/dali/internal/update/rendering/scene-graph-renderer.h @@ -2,7 +2,7 @@ #define DALI_INTERNAL_SCENE_GRAPH_RENDERER_H /* - * Copyright (c) 2018 Samsung Electronics Co., Ltd. + * Copyright (c) 2020 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. @@ -339,8 +339,9 @@ public: * Prepare the object for rendering. * This is called by the UpdateManager when an object is due to be rendered in the current frame. * @param[in] updateBufferIndex The current update buffer index. + * @return Whether this renderer has been updated in the current frame */ - void PrepareRender( BufferIndex updateBufferIndex ); + bool PrepareRender( BufferIndex updateBufferIndex ); /** * Retrieve the Render thread renderer diff --git a/dali/public-api/actors/custom-actor-impl.h b/dali/public-api/actors/custom-actor-impl.h index 3afaa88..120d5e1 100644 --- a/dali/public-api/actors/custom-actor-impl.h +++ b/dali/public-api/actors/custom-actor-impl.h @@ -105,7 +105,6 @@ public: * D E F * * @endcode - * @param[in] depth The depth in the hierarchy for the actor */ virtual void OnSceneConnection(int32_t depth) = 0; diff --git a/dali/public-api/actors/custom-actor.h b/dali/public-api/actors/custom-actor.h index 5a4a98a..d353d6c 100644 --- a/dali/public-api/actors/custom-actor.h +++ b/dali/public-api/actors/custom-actor.h @@ -93,7 +93,6 @@ public: * * @SINCE_1_0.0 * @param[in] implementation The implementation for this custom actor - * @return A handle to a newly allocated Dali resource */ CustomActor(CustomActorImpl& implementation); diff --git a/dali/public-api/animation/alpha-function.h b/dali/public-api/animation/alpha-function.h index 1ea2677..48c32b0 100644 --- a/dali/public-api/animation/alpha-function.h +++ b/dali/public-api/animation/alpha-function.h @@ -83,7 +83,6 @@ public: * @brief Default constructor. * Creates an alpha function object with the default built-in alpha function. * @SINCE_1_0.0 - * @return The alpha function */ AlphaFunction(); @@ -93,7 +92,6 @@ public: * to the constructor. * @SINCE_1_0.0 * @param[in] function One of the built-in alpha functions - * @return The alpha function */ AlphaFunction(BuiltinFunction function); @@ -103,7 +101,6 @@ public: * to the constructor. * @SINCE_1_0.0 * @param[in] function A pointer to an alpha function - * @return The alpha function */ AlphaFunction(AlphaFunctionPrototype function); @@ -115,7 +112,6 @@ public: * @SINCE_1_0.0 * @param[in] controlPoint0 A Vector2 which will be used as the first control point of the curve * @param[in] controlPoint1 A Vector2 which will be used as the second control point of the curve - * @return The alpha function * @note The x components of the control points will be clamped to the range [0,1] to prevent * non monotonic curves. */ diff --git a/dali/public-api/animation/constraint.h b/dali/public-api/animation/constraint.h index 5a487ac..6bdcb7c 100644 --- a/dali/public-api/animation/constraint.h +++ b/dali/public-api/animation/constraint.h @@ -170,12 +170,12 @@ public: CallbackBase* Clone() { CallbackBase* callback = nullptr; - if(mImpl && mImpl->mObjectPointer && mCopyConstructorDispatcher) + if(mImpl.mObjectPointer && mCopyConstructorDispatcher) { - callback = new Function(mCopyConstructorDispatcher(reinterpret_cast(mImpl->mObjectPointer)) /* Copy the object */, + callback = new Function(mCopyConstructorDispatcher(reinterpret_cast(mImpl.mObjectPointer)) /* Copy the object */, mMemberFunction, - mImpl->mMemberFunctionDispatcher, - mImpl->mDestructorDispatcher, + mImpl.mMemberFunctionDispatcher, + mImpl.mDestructorDispatcher, mCopyConstructorDispatcher); } else diff --git a/dali/public-api/common/dali-vector.h b/dali/public-api/common/dali-vector.h index e4bb8ce..5a61b64 100644 --- a/dali/public-api/common/dali-vector.h +++ b/dali/public-api/common/dali-vector.h @@ -847,6 +847,38 @@ public: // API }; /** + * @brief Erases all elements that compare equal to value from the vector. + * + * @SINCE_1_9.33 + * @param[in] vector The vector + * @param[in] value The value to be removed. + */ +template +inline void Erase(Dali::Vector& vector, const U& value) +{ + auto begin = vector.Begin(); + auto end = vector.End(); + + vector.Erase(std::remove(begin, end, value), end); +} + +/** + * @brief Erases all elements that satisfy the predicate from the vector. + * + * @SINCE_1_9.33 + * @param[in] vector The vector + * @param[in] predicate The predicate + */ +template +inline void EraseIf(Dali::Vector& vector, Predicate predicate) +{ + auto begin = vector.Begin(); + auto end = vector.End(); + + vector.Erase(std::remove_if(begin, end, predicate), end); +} + +/** * @} */ } // namespace Dali diff --git a/dali/public-api/dali-core-version.cpp b/dali/public-api/dali-core-version.cpp index 7ee6ca0..8ff52e1 100644 --- a/dali/public-api/dali-core-version.cpp +++ b/dali/public-api/dali-core-version.cpp @@ -27,7 +27,7 @@ namespace Dali { const uint32_t CORE_MAJOR_VERSION = 1; const uint32_t CORE_MINOR_VERSION = 9; -const uint32_t CORE_MICRO_VERSION = 32; +const uint32_t CORE_MICRO_VERSION = 34; const char* const CORE_BUILD_DATE = __DATE__ " " __TIME__; #ifdef DEBUG_ENABLED diff --git a/dali/public-api/object/handle.h b/dali/public-api/object/handle.h index b98df2f..d7dc63f 100644 --- a/dali/public-api/object/handle.h +++ b/dali/public-api/object/handle.h @@ -74,7 +74,7 @@ public: /** * @brief PropertySetSignal function prototype for signal handler. Called when a property is set on this object. */ - using PropertySetSignalType = Signal; + using PropertySetSignalType = Signal; public: /** diff --git a/dali/public-api/signals/base-signal.cpp b/dali/public-api/signals/base-signal.cpp index 0b3cfd7..eb52b56 100644 --- a/dali/public-api/signals/base-signal.cpp +++ b/dali/public-api/signals/base-signal.cpp @@ -47,71 +47,17 @@ BaseSignal::~BaseSignal() // The signal is being destroyed. We have to inform any slots // that are connected, that the signal is dead. - const std::size_t count(mSignalConnections.Count()); + const std::size_t count(mSignalConnections.size()); for(std::size_t i = 0; i < count; i++) { - SignalConnection* connection = mSignalConnections[i]; + auto& connection = mSignalConnections[i]; // Note that values are set to NULL in DeleteConnection if(connection) { - connection->Disconnect(this); - delete connection; + connection.Disconnect(this); } } - - mSignalConnections.Clear(); -} - -bool BaseSignal::Empty() const -{ - return (0 == GetConnectionCount()); -} - -std::size_t BaseSignal::GetConnectionCount() const -{ - std::size_t count(0); - - const std::size_t size(mSignalConnections.Count()); - for(std::size_t i = 0; i < size; ++i) - { - // Note that values are set to NULL in DeleteConnection - if(nullptr != mSignalConnections[i]) - { - ++count; - } - } - - return count; -} - -void BaseSignal::Emit() -{ - // Guards against nested Emit() calls - EmitGuard guard(mEmittingFlag); // Guards against nested Emit() calls - if(guard.ErrorOccurred()) - { - return; - } - - // If more connections are added by callbacks, these are ignore until the next Emit() - // Note that mSignalConnections.Count() count cannot be reduced while iterating - const std::size_t initialCount(mSignalConnections.Count()); - - for(std::size_t i = 0; i < initialCount; ++i) - { - CallbackBase* callback(GetCallback(i)); - - // Note that connections will be set to NULL when disconnected - // This is preferable to reducing the connection count while iterating - if(callback) - { - CallbackBase::Execute(*callback); - } - } - - // Cleanup NULL values from Connection container - CleanupConnections(); } void BaseSignal::OnConnect(CallbackBase* callback) @@ -124,9 +70,9 @@ void BaseSignal::OnConnect(CallbackBase* callback) if(INVALID_CALLBACK_INDEX == index) { // create a new signal connection object, to allow the signal to track the connection. - SignalConnection* connection = new SignalConnection(callback); + //SignalConnection* connection = new SignalConnection(callback); - mSignalConnections.PushBack(connection); + mSignalConnections.push_back(SignalConnection(callback)); } else { @@ -161,9 +107,9 @@ void BaseSignal::OnConnect(ConnectionTrackerInterface* tracker, CallbackBase* ca if(INVALID_CALLBACK_INDEX == index) { // create a new signal connection object, to allow the signal to track the connection. - SignalConnection* connection = new SignalConnection(tracker, callback); + //SignalConnection* connection = new SignalConnection(tracker, callback); - mSignalConnections.PushBack(connection); + mSignalConnections.push_back({tracker, callback}); // Let the connection tracker know that a connection between a signal and a slot has been made. tracker->SignalConnected(this, callback); @@ -185,7 +131,7 @@ void BaseSignal::OnDisconnect(ConnectionTrackerInterface* tracker, CallbackBase* if(index > INVALID_CALLBACK_INDEX) { // temporary pointer to disconnected callback - CallbackBase* disconnectedCallback = mSignalConnections[index]->GetCallback(); + CallbackBase* disconnectedCallback = mSignalConnections[index].GetCallback(); // close the signal side connection first. DeleteConnection(index); @@ -201,7 +147,7 @@ void BaseSignal::OnDisconnect(ConnectionTrackerInterface* tracker, CallbackBase* // for SlotObserver::SlotDisconnected void BaseSignal::SlotDisconnected(CallbackBase* callback) { - const std::size_t count(mSignalConnections.Count()); + const std::size_t count(mSignalConnections.size()); for(std::size_t i = 0; i < count; ++i) { const CallbackBase* connectionCallback = GetCallback(i); @@ -220,32 +166,15 @@ void BaseSignal::SlotDisconnected(CallbackBase* callback) DALI_ABORT("Callback lost in SlotDisconnected()"); } -CallbackBase* BaseSignal::GetCallback(std::size_t connectionIndex) const -{ - DALI_ASSERT_ALWAYS(connectionIndex < mSignalConnections.Count() && "GetCallback called with invalid index"); - - CallbackBase* callback(nullptr); - - SignalConnection* connection(mSignalConnections[connectionIndex]); - // Note that values are set to NULL in DeleteConnection - if(connection) - { - callback = connection->GetCallback(); - } - - return callback; -} - -int32_t BaseSignal::FindCallback(CallbackBase* callback) +int32_t BaseSignal::FindCallback(CallbackBase* callback) const noexcept { int32_t index(INVALID_CALLBACK_INDEX); // A signal can have multiple slots connected to it. // We need to search for the slot which has the same call back function (if it's static) // Or the same object / member function (for non-static) - const std::size_t count = mSignalConnections.Count(); - for(std::size_t i = 0; i < count; ++i) + for(auto i = 0u; i < mSignalConnections.size(); ++i) { const CallbackBase* connectionCallback = GetCallback(i); @@ -262,49 +191,34 @@ int32_t BaseSignal::FindCallback(CallbackBase* callback) void BaseSignal::DeleteConnection(std::size_t connectionIndex) { - DALI_ASSERT_ALWAYS(connectionIndex < mSignalConnections.Count() && "DeleteConnection called with invalid index"); - - // delete the object - SignalConnection* connection(mSignalConnections[connectionIndex]); - delete connection; if(mEmittingFlag) { - // IMPORTANT - do not remove from items from mSignalConnections, set to NULL instead. + // IMPORTANT - do not remove from items from mSignalConnections, reset instead. // Signal Emit() methods require that connection count is not reduced while iterating // i.e. DeleteConnection can be called from within callbacks, while iterating through mSignalConnections. - mSignalConnections[connectionIndex] = nullptr; + mSignalConnections[connectionIndex] = {nullptr}; + ++mNullConnections; } else { // If application connects and disconnects without the signal never emitting, // the mSignalConnections vector keeps growing and growing as CleanupConnections() is done from Emit. - mSignalConnections.Erase(mSignalConnections.Begin() + connectionIndex); + mSignalConnections.erase(mSignalConnections.begin() + connectionIndex); } } void BaseSignal::CleanupConnections() { - const std::size_t total = mSignalConnections.Count(); - // only do something if there are items - if(total > 0) + if(!mSignalConnections.empty()) { - std::size_t index = 0; - // process the whole vector - for(std::size_t i = 0; i < total; ++i) - { - if(mSignalConnections[index] == nullptr) - { - // items will be moved so don't increase index (erase will decrease the count of vector) - mSignalConnections.Erase(mSignalConnections.Begin() + index); - } - else - { - // increase to next element - ++index; - } - } + //Remove Signals that are already markeed nullptr. + mSignalConnections.erase(std::remove_if(mSignalConnections.begin(), + mSignalConnections.end(), + [](auto& elm) { return (elm) ? false : true; }), + mSignalConnections.end()); } + mNullConnections = 0; } // BaseSignal::EmitGuard diff --git a/dali/public-api/signals/base-signal.h b/dali/public-api/signals/base-signal.h index ddfe915..63dc801 100644 --- a/dali/public-api/signals/base-signal.h +++ b/dali/public-api/signals/base-signal.h @@ -18,6 +18,9 @@ * */ +// EXTERNAL INCLUDES +#include + // INTERNAL INCLUDES #include #include @@ -96,7 +99,10 @@ public: * @SINCE_1_0.0 * @return True if there are any slots connected to the signal. */ - bool Empty() const; + bool Empty() const + { + return (0 == GetConnectionCount()); + } /** * @brief Queries the number of slots. @@ -104,7 +110,10 @@ public: * @SINCE_1_0.0 * @return The number of slots connected to this signal */ - std::size_t GetConnectionCount() const; + std::size_t GetConnectionCount() const + { + return mSignalConnections.size() - mNullConnections; + } // Templated Emit functions for the Signal implementations @@ -141,22 +150,15 @@ public: }; /** - * @brief Emits a signal with no parameters. - * - * @SINCE_1_0.0 - * @pre Cannot be called from inside the same Signal's Emit methods. - */ - void Emit(); - - /** - * @brief Emits a signal with no parameters. + * @brief Emits a signal with parameter pack. * - * @SINCE_1_0.0 + * @SINCE_1_9.33 + * @param[in] args The parameter pack * @return The value returned by the last callback * @pre Cannot be called from inside the same Signal's Emit methods. */ - template - Ret EmitReturn() + template + Ret EmitReturn(Args... args) { Ret returnVal = Ret(); @@ -169,167 +171,7 @@ public: // If more connections are added by callbacks, these are ignore until the next Emit() // Note that count cannot be reduced while iterating - const std::size_t initialCount(mSignalConnections.Count()); - - for(std::size_t i = 0; i < initialCount; ++i) - { - CallbackBase* callback(GetCallback(i)); - - // Note that connections will be set to NULL when disconnected - // This is preferable to reducing the connection count while iterating - if(callback) - { - returnVal = CallbackBase::ExecuteReturn(*callback); - } - } - - // Cleanup NULL values from Connection container - CleanupConnections(); - - return returnVal; - } - - /** - * @brief Emits a signal with 1 parameter. - * - * @SINCE_1_0.0 - * @param[in] arg0 The first parameter - * @pre Cannot be called from inside the same Signal's Emit methods. - */ - template - void Emit(Arg0 arg0) - { - // Guards against nested Emit() calls - EmitGuard guard(mEmittingFlag); // Guards against nested Emit() calls - if(guard.ErrorOccurred()) - { - return; - } - - // If more connections are added by callbacks, these are ignore until the next Emit() - // Note that count cannot be reduced while iterating - const std::size_t initialCount(mSignalConnections.Count()); - - for(std::size_t i = 0; i < initialCount; ++i) - { - CallbackBase* callback(GetCallback(i)); - - // Note that connections will be set to NULL when disconnected - // This is preferable to reducing the connection count while iterating - if(callback) - { - CallbackBase::Execute(*callback, arg0); - } - } - - // Cleanup NULL values from Connection container - CleanupConnections(); - } - - /** - * @brief Emits a signal with 1 parameter. - * - * @SINCE_1_0.0 - * @param[in] arg0 The first parameter - * @return The value returned by the last callback - * @pre Cannot be called from inside the same Signal's Emit methods. - */ - template - Ret EmitReturn(Arg0 arg0) - { - Ret returnVal = Ret(); - - // Guards against nested Emit() calls - EmitGuard guard(mEmittingFlag); // Guards against nested Emit() calls - if(guard.ErrorOccurred()) - { - return returnVal; - } - - // If more connections are added by callbacks, these are ignore until the next Emit() - // Note that count cannot be reduced while iterating - const std::size_t initialCount(mSignalConnections.Count()); - - for(std::size_t i = 0; i < initialCount; ++i) - { - CallbackBase* callback(GetCallback(i)); - - // Note that connections will be set to NULL when disconnected - // This is preferable to reducing the connection count while iterating - if(callback) - { - returnVal = CallbackBase::ExecuteReturn(*callback, arg0); - } - } - - // Cleanup NULL values from Connection container - CleanupConnections(); - - return returnVal; - } - - /** - * @brief Emits a signal with 2 parameters. - * - * @SINCE_1_0.0 - * @param[in] arg0 The first parameter - * @param[in] arg1 The second parameter - * @pre Cannot be called from inside the same Signal's Emit methods. - */ - template - void Emit(Arg0 arg0, Arg1 arg1) - { - // Guards against nested Emit() calls - EmitGuard guard(mEmittingFlag); // Guards against nested Emit() calls - if(guard.ErrorOccurred()) - { - return; - } - - // If more connections are added by callbacks, these are ignore until the next Emit() - // Note that count cannot be reduced while iterating - const std::size_t initialCount(mSignalConnections.Count()); - - for(std::size_t i = 0; i < initialCount; ++i) - { - CallbackBase* callback(GetCallback(i)); - - // Note that connections will be set to NULL when disconnected - // This is preferable to reducing the connection count while iterating - if(callback) - { - CallbackBase::Execute(*callback, arg0, arg1); - } - } - - // Cleanup NULL values from Connection container - CleanupConnections(); - } - - /** - * @brief Emits a signal with 2 parameters. - * - * @SINCE_1_0.0 - * @param[in] arg0 The first parameter - * @param[in] arg1 The second parameter - * @return The value returned by the last callback - * @pre Cannot be called from inside the same Signal's Emit methods. - */ - template - Ret EmitReturn(Arg0 arg0, Arg1 arg1) - { - Ret returnVal = Ret(); - - // Guards against nested Emit() calls - EmitGuard guard(mEmittingFlag); // Guards against nested Emit() calls - if(guard.ErrorOccurred()) - { - return returnVal; - } - - // If more connections are added by callbacks, these are ignore until the next Emit() - // Note that count cannot be reduced while iterating - const std::size_t initialCount(mSignalConnections.Count()); + const std::size_t initialCount(mSignalConnections.size()); for(std::size_t i = 0; i < initialCount; ++i) { @@ -339,7 +181,7 @@ public: // This is preferable to reducing the connection count while iterating if(callback) { - returnVal = CallbackBase::ExecuteReturn(*callback, arg0, arg1); + returnVal = CallbackBase::ExecuteReturn(*callback, args...); } } @@ -350,16 +192,14 @@ public: } /** - * @brief Emits a signal with 3 parameters. + * @brief Emits a signal with parameter pack. * - * @SINCE_1_0.0 - * @param[in] arg0 The first parameter - * @param[in] arg1 The second parameter - * @param[in] arg2 The third parameter + * @SINCE_1_9.33 + * @param[in] args The parameter pack * @pre Cannot be called from inside the same Signal's Emit methods. */ - template - void Emit(Arg0 arg0, Arg1 arg1, Arg2 arg2) + template + void Emit(Args... args) { // Guards against nested Emit() calls EmitGuard guard(mEmittingFlag); // Guards against nested Emit() calls @@ -370,49 +210,7 @@ public: // If more connections are added by callbacks, these are ignore until the next Emit() // Note that count cannot be reduced while iterating - const std::size_t initialCount(mSignalConnections.Count()); - - for(std::size_t i = 0; i < initialCount; ++i) - { - CallbackBase* callback(GetCallback(i)); - - // Note that connections will be set to NULL when disconnected - // This is preferable to reducing the connection count while iterating - if(callback) - { - CallbackBase::Execute(*callback, arg0, arg1, arg2); - } - } - - // Cleanup NULL values from Connection container - CleanupConnections(); - } - - /** - * @brief Emits a signal with 3 parameters. - * - * @SINCE_1_0.0 - * @param[in] arg0 The first parameter - * @param[in] arg1 The second parameter - * @param[in] arg2 The third parameter - * @return The value returned by the last callback - * @pre Cannot be called from inside the same Signal's Emit methods. - */ - template - Ret EmitReturn(Arg0 arg0, Arg1 arg1, Arg2 arg2) - { - Ret returnVal = Ret(); - - // Guards against nested Emit() calls - EmitGuard guard(mEmittingFlag); // Guards against nested Emit() calls - if(guard.ErrorOccurred()) - { - return returnVal; - } - - // If more connections are added by callbacks, these are ignore until the next Emit() - // Note that count cannot be reduced while iterating - const std::size_t initialCount(mSignalConnections.Count()); + const std::size_t initialCount(mSignalConnections.size()); for(std::size_t i = 0; i < initialCount; ++i) { @@ -422,14 +220,12 @@ public: // This is preferable to reducing the connection count while iterating if(callback) { - returnVal = CallbackBase::ExecuteReturn(*callback, arg0, arg1, arg2); + CallbackBase::Execute(*callback, args...); } } // Cleanup NULL values from Connection container CleanupConnections(); - - return returnVal; } // Connect / Disconnect function for use by Signal implementations @@ -482,7 +278,10 @@ private: * @param[in] connectionIndex The index of the callback * @return The callback, or NULL if the connection has been deleted */ - CallbackBase* GetCallback(std::size_t connectionIndex) const; + CallbackBase* GetCallback(std::size_t connectionIndex) const noexcept + { + return mSignalConnections[connectionIndex].GetCallback(); + } /** * @brief Helper to find whether a callback is connected. @@ -491,7 +290,7 @@ private: * @param[in] callback The call back object * @return A valid index if the callback is connected */ - int32_t FindCallback(CallbackBase* callback); + int32_t FindCallback(CallbackBase* callback) const noexcept; /** * @brief Deletes a connection object from the list of connections. @@ -514,9 +313,9 @@ private: BaseSignal& operator=(BaseSignal&&) = delete; ///< Deleted move assignment operator. @SINCE_1_9.25 private: - Dali::Vector mSignalConnections; ///< Array of connections - - bool mEmittingFlag; ///< Used to guard against nested Emit() calls + std::vector mSignalConnections; ///< Array of connections + uint32_t mNullConnections{0}; ///< Empty Connections in the array. + bool mEmittingFlag{false}; ///< Used to guard against nested Emit() calls }; /** diff --git a/dali/public-api/signals/callback.cpp b/dali/public-api/signals/callback.cpp index fd0576b..6e8fb93 100644 --- a/dali/public-api/signals/callback.cpp +++ b/dali/public-api/signals/callback.cpp @@ -23,8 +23,7 @@ namespace Dali // CallbackBase CallbackBase::CallbackBase() -: mImpl(nullptr), - mFunction(nullptr) +: mFunction(nullptr) { } @@ -34,77 +33,39 @@ CallbackBase::~CallbackBase() } CallbackBase::CallbackBase(Function function) -: mImpl(nullptr), - mFunction(function) +: mFunction(function) { } CallbackBase::CallbackBase(void* object, MemberFunction function, Dispatcher dispatcher) : mMemberFunction(function) { - mImpl = new CallbackBase::Impl; - if(mImpl) - { - mImpl->mObjectPointer = object; - mImpl->mMemberFunctionDispatcher = dispatcher; - mImpl->mDestructorDispatcher = nullptr; // object is not owned - } + mImpl.mObjectPointer = object; + mImpl.mMemberFunctionDispatcher = dispatcher; + mImpl.mDestructorDispatcher = nullptr; // object is not owned } CallbackBase::CallbackBase(void* object, MemberFunction function, Dispatcher dispatcher, Destructor destructor) : mMemberFunction(function) { - mImpl = new CallbackBase::Impl; - if(mImpl) - { - mImpl->mObjectPointer = object; - mImpl->mMemberFunctionDispatcher = dispatcher; - mImpl->mDestructorDispatcher = destructor; // object is owned - } + mImpl.mObjectPointer = object; + mImpl.mMemberFunctionDispatcher = dispatcher; + mImpl.mDestructorDispatcher = destructor; // object is owned } void CallbackBase::Reset() { - if(mImpl) + // if destructor function is set it means we own this object + if(mImpl.mObjectPointer && + mImpl.mDestructorDispatcher) { - // if destructor function is set it means we own this object - if(mImpl->mObjectPointer && - mImpl->mDestructorDispatcher) - { - // call the destructor dispatcher - (*mImpl->mDestructorDispatcher)(mImpl->mObjectPointer); - } - - delete mImpl; - mImpl = nullptr; + // call the destructor dispatcher + (*mImpl.mDestructorDispatcher)(mImpl.mObjectPointer); } - mFunction = nullptr; -} - -// CallbackBase::Impl - -CallbackBase::Impl::Impl() -: mObjectPointer(nullptr), - mMemberFunctionDispatcher(nullptr), - mDestructorDispatcher(nullptr) -{ -} - -// Non-member equality operator + mImpl = {}; -bool operator==(const CallbackBase& lhs, const CallbackBase& rhs) -{ - if(lhs.mImpl) - { - // check it's the same member function / object - return (lhs.mFunction == rhs.mFunction) && (lhs.mImpl->mObjectPointer == rhs.mImpl->mObjectPointer); - } - else - { - // check if it the same C function or a static member function - return (lhs.mFunction == rhs.mFunction); - } + mFunction = nullptr; } } // namespace Dali diff --git a/dali/public-api/signals/callback.h b/dali/public-api/signals/callback.h index 81d875f..0acc43d 100644 --- a/dali/public-api/signals/callback.h +++ b/dali/public-api/signals/callback.h @@ -62,119 +62,31 @@ public: /** * @brief Function to call the function or member function dispatcher. * - * @SINCE_1_0.0 - * @param[in] callback The callback to call - */ - static void Execute(CallbackBase& callback) - { - // if we point to a function, we can call it directly - // otherwise call the dispatcher function that knows the real type of the object - // Note that this template dispatcher lives in client code so the library containing - // the code has to be loaded, otherwise we crash boom bang - if(callback.mImpl && callback.mImpl->mObjectPointer) - { - Dispatcher dispatcher = callback.mImpl->mMemberFunctionDispatcher; - (*dispatcher)(callback); - } - // its also possible to have a member function pointer to a CallbackProvider - // that has been deleted, so check if we have impl still - else if(!callback.mImpl && callback.mFunction) - { - (*(callback.mFunction))(); - } - else - { - DALI_ASSERT_ALWAYS(0 && "no function to execute"); - } - } - - /** - * @brief Function to call the function or member function dispatcher. - * - * @SINCE_1_0.0 - * @param[in] callback The callback to call - * @return The value from the function - */ - template - static R ExecuteReturn(CallbackBase& callback) - { - R returnVal = R(); - // if we point to a function, we can call it directly - // otherwise call the dispatcher function that knows the real type of the object - // Note that this template dispatcher lives in client code so the library containing - // the code has to be loaded, otherwise we crash boom bang - if(callback.mImpl && callback.mImpl->mObjectPointer) - { - using Dispatcher = R (*)(CallbackBase&); - Dispatcher dispatcher = reinterpret_cast(callback.mImpl->mMemberFunctionDispatcher); - returnVal = (*dispatcher)(callback); - } - else if(!callback.mImpl && callback.mFunction) - { - using Function1 = R (*)(); - returnVal = (*(reinterpret_cast(callback.mFunction)))(); - } - - return returnVal; - } - - /** - * @brief Function to call the function or member function dispatcher. - * - * This function template gets instantiated at the call site. - * @SINCE_1_0.0 - * @param[in] callback The callback to call - * @param[in] param1 The first parameter to pass into the function - */ - template - static void Execute(CallbackBase& callback, P1 param1) - { - // if we point to a function, we can call it directly - // otherwise call the dispatcher function that knows the real type of the object - // Note that this template dispatcher lives in client code (where the callback was created) - // so the library containing the code has to be loaded, otherwise we crash boom bang - if(callback.mImpl && callback.mImpl->mObjectPointer) - { - using Dispatcher = void (*)(CallbackBase&, P1); - Dispatcher dispatcher = reinterpret_cast(callback.mImpl->mMemberFunctionDispatcher); - (*dispatcher)(callback, param1); - } - else if(!callback.mImpl && callback.mFunction) - { - // convert function type - using Function1 = void (*)(P1); - (*(reinterpret_cast(callback.mFunction)))(param1); - } - } - - /** - * @brief Function to call the function or member function dispatcher. - * * This function template gets instantiated at the call site. - * @SINCE_1_0.0 + * @SINCE_1_9.33 * @param[in] callback The callback to call - * @param[in] param1 The first parameter to pass into the function + * @param[in] args parameter pack to pass into the function * @return The value from the function */ - template - static R ExecuteReturn(CallbackBase& callback, P1 param1) + template + static R ExecuteReturn(CallbackBase& callback, Args... args) { R returnVal = R(); // if we point to a function, we can call it directly // otherwise call the dispatcher function that knows the real type of the object // Note that this template dispatcher lives in client code (where the callback was created) // so the library containing the code has to be loaded, otherwise we crash boom bang - if(callback.mImpl && callback.mImpl->mObjectPointer) + if(callback.mImpl.mObjectPointer) { - using Dispatcher = R (*)(CallbackBase&, P1); - Dispatcher dispatcher = reinterpret_cast(callback.mImpl->mMemberFunctionDispatcher); - returnVal = (*dispatcher)(callback, param1); + using Dispatcher = R (*)(CallbackBase&, Args...); + Dispatcher dispatcher = reinterpret_cast(callback.mImpl.mMemberFunctionDispatcher); + returnVal = (*dispatcher)(callback, args...); } - else if(!callback.mImpl && callback.mFunction) + else if(callback.mFunction) { // convert function type - using Function1 = R (*)(P1); - returnVal = (*(reinterpret_cast(callback.mFunction)))(param1); + using Function = R (*)(Args...); + returnVal = (*(reinterpret_cast(callback.mFunction)))(args...); } return returnVal; @@ -184,138 +96,48 @@ public: * @brief Function to call the function or member function dispatcher. * * This function template gets instantiated at the call site. - * @SINCE_1_0.0 + * @SINCE_1_9.33 * @param[in] callback The callback to call - * @param[in] param1 The first parameter to pass into the function - * @param[in] param2 The second parameter to pass into the function + * @param[in] args parameter pack to pass into the function */ - template - static void Execute(CallbackBase& callback, P1 param1, P2 param2) + template + static void Execute(CallbackBase& callback, Args... args) { // if we point to a function, we can call it directly // otherwise call the dispatcher function that knows the real type of the object // Note that this template dispatcher lives in client code (where the callback was created) // so the library containing the code has to be loaded, otherwise we crash boom bang - if(callback.mImpl && callback.mImpl->mObjectPointer) + if(callback.mImpl.mObjectPointer) { - using Dispatcher = void (*)(CallbackBase&, P1, P2); - Dispatcher dispatcher = reinterpret_cast(callback.mImpl->mMemberFunctionDispatcher); - (*dispatcher)(callback, param1, param2); + using Dispatcher = void (*)(CallbackBase&, Args...); + Dispatcher dispatcher = reinterpret_cast(callback.mImpl.mMemberFunctionDispatcher); + (*dispatcher)(callback, args...); } - else if(!callback.mImpl && callback.mFunction) + else if(callback.mFunction) { // convert function type - using Function2 = void (*)(P1, P2); - (*(reinterpret_cast(callback.mFunction)))(param1, param2); + using Function = void (*)(Args...); + (*(reinterpret_cast(callback.mFunction)))(args...); } } +public: /** - * @brief Function to call the function or member function dispatcher. - * - * This function template gets instantiated at the call site. - * @SINCE_1_0.0 - * @param[in] callback The callback to call - * @param[in] param1 The first parameter to pass into the function - * @param[in] param2 The second parameter to pass into the function - * @return The return value from the function - */ - template - static R ExecuteReturn(CallbackBase& callback, P1 param1, P2 param2) - { - R returnVal = R(); - // if we point to a function, we can call it directly - // otherwise call the dispatcher function that knows the real type of the object - // Note that this template dispatcher lives in client code (where the callback was created) - // so the library containing the code has to be loaded, otherwise we crash boom bang - if(callback.mImpl && callback.mImpl->mObjectPointer) - { - using Dispatcher = R (*)(CallbackBase&, P1, P2); - Dispatcher dispatcher = reinterpret_cast(callback.mImpl->mMemberFunctionDispatcher); - returnVal = (*dispatcher)(callback, param1, param2); - } - else if(!callback.mImpl && callback.mFunction) - { - // convert function type - using Function2 = R (*)(P1, P2); - returnVal = (*(reinterpret_cast(callback.mFunction)))(param1, param2); - } - - return returnVal; - } - - /** - * @brief Function to call the function or member function dispatcher. - * - * This function template gets instantiated at the call site. + * @brief Function with static linkage. * @SINCE_1_0.0 - * @param[in] callback The callback to call - * @param[in] param1 The first parameter to pass into the function - * @param[in] param2 The second parameter to pass into the function - * @param[in] param3 The third parameter to pass into the function */ - template - static void Execute(CallbackBase& callback, P1 param1, P2 param2, P3 param3) - { - // if we point to a function, we can call it directly - // otherwise call the dispatcher function that knows the real type of the object - // Note that this template dispatcher lives in client code (where the callback was created) - // so the library containing the code has to be loaded, otherwise we crash boom bang - if(callback.mImpl && callback.mImpl->mObjectPointer) - { - using Dispatcher = void (*)(CallbackBase&, P1, P2, P3); - Dispatcher dispatcher = reinterpret_cast(callback.mImpl->mMemberFunctionDispatcher); - (*dispatcher)(callback, param1, param2, param3); - } - else if(!callback.mImpl && callback.mFunction) - { - // convert function type - using Function2 = void (*)(P1, P2, P3); - (*(reinterpret_cast(callback.mFunction)))(param1, param2, param3); - } - } + using Function = void (*)(); /** - * @brief Function to call the function or member function dispatcher. + * @brief Constructor for function with static linkage. * - * This function template gets instantiated at the call site. * @SINCE_1_0.0 - * @param[in] callback The callback to call - * @param[in] param1 The first parameter to pass into the function - * @param[in] param2 The second parameter to pass into the function - * @param[in] param3 The third parameter to pass into the function - * @return The return value from the function + * @param[in] function The function to call */ - template - static R ExecuteReturn(CallbackBase& callback, P1 param1, P2 param2, P3 param3) - { - R returnVal = R(); - // if we point to a function, we can call it directly - // otherwise call the dispatcher function that knows the real type of the object - // Note that this template dispatcher lives in client code (where the callback was created) - // so the library containing the code has to be loaded, otherwise we crash boom bang - if(callback.mImpl && callback.mImpl->mObjectPointer) - { - using Dispatcher = R (*)(CallbackBase&, P1, P2, P3); - Dispatcher dispatcher = reinterpret_cast(callback.mImpl->mMemberFunctionDispatcher); - returnVal = (*dispatcher)(callback, param1, param2, param3); - } - else if(!callback.mImpl && callback.mFunction) - { - // convert function type - using Function2 = R (*)(P1, P2, P3); - returnVal = (*(reinterpret_cast(callback.mFunction)))(param1, param2, param3); - } - - return returnVal; - } + CallbackBase(Function function); protected: // Constructors for deriving classes - /** - * @brief Function with static linkage. - * @SINCE_1_0.0 - */ - using Function = void (*)(); + /** * @brief Member function. @@ -351,14 +173,6 @@ protected: // Constructors for deriving classes CallbackBase& operator=(const CallbackBase& rhs); /** - * @brief Constructor for function with static linkage. - * - * @SINCE_1_0.0 - * @param[in] function The function to call - */ - CallbackBase(Function function); - - /** * @brief Constructor for member function. * * @SINCE_1_0.0 @@ -386,13 +200,11 @@ public: // Data for deriving classes & Dispatchers */ struct Impl { - Impl(); ///< Default constructor @SINCE_1_0.0 - - void* mObjectPointer; ///< Object whose member function will be called. Not owned if mDestructorDispatcher is NULL. - Dispatcher mMemberFunctionDispatcher; ///< Dispatcher for member functions - Destructor mDestructorDispatcher; ///< Destructor for owned objects. NULL if mDestructorDispatcher is not owned. + void* mObjectPointer{nullptr}; ///< Object whose member function will be called. Not owned if mDestructorDispatcher is NULL. + Dispatcher mMemberFunctionDispatcher{nullptr}; ///< Dispatcher for member functions + Destructor mDestructorDispatcher{nullptr}; ///< Destructor for owned objects. NULL if mDestructorDispatcher is not owned. }; - Impl* mImpl; ///< Implementation pointer + Impl mImpl; union { @@ -408,7 +220,15 @@ public: // Data for deriving classes & Dispatchers * @param[in] rhs A reference to compare to * @return True if lhs is same as rhs */ -bool operator==(const CallbackBase& lhs, const CallbackBase& rhs); +inline bool operator==(const CallbackBase& lhs, const CallbackBase& rhs) +{ + if (lhs.mFunction == rhs.mFunction && + lhs.mImpl.mObjectPointer == rhs.mImpl.mObjectPointer) + { + return true; + } + return false; +} /** * @brief Dispatcher to delete an object. @@ -446,7 +266,7 @@ struct Dispatcher0 static void Dispatch(CallbackBase& callback) { // "downcast" the object and function type back to the correct ones - T* object = reinterpret_cast(callback.mImpl->mObjectPointer); + T* object = reinterpret_cast(callback.mImpl.mObjectPointer); using MemberFunction = void (T::*)(); MemberFunction function = reinterpret_cast(callback.mMemberFunction); (object->*function)(); @@ -470,7 +290,7 @@ struct Dispatcher1 static void Dispatch(CallbackBase& callback, P1 param1) { // "downcast" the object and function type back to the correct ones - T* object = reinterpret_cast(callback.mImpl->mObjectPointer); + T* object = reinterpret_cast(callback.mImpl.mObjectPointer); using MemberFunction = void (T::*)(P1); MemberFunction function = reinterpret_cast(callback.mMemberFunction); (object->*function)(param1); @@ -495,7 +315,7 @@ struct Dispatcher2 static void Dispatch(CallbackBase& callback, P1 param1, P2 param2) { // "downcast" the object and function type back to the correct ones - T* object = reinterpret_cast(callback.mImpl->mObjectPointer); + T* object = reinterpret_cast(callback.mImpl.mObjectPointer); using MemberFunction = void (T::*)(P1, P2); MemberFunction function = reinterpret_cast(callback.mMemberFunction); (object->*function)(param1, param2); @@ -521,7 +341,7 @@ struct Dispatcher3 static void Dispatch(CallbackBase& callback, P1 param1, P2 param2, P3 param3) { // "downcast" the object and function type back to the correct ones - T* object = reinterpret_cast(callback.mImpl->mObjectPointer); + T* object = reinterpret_cast(callback.mImpl.mObjectPointer); using MemberFunction = void (T::*)(P1, P2, P3); MemberFunction function = reinterpret_cast(callback.mMemberFunction); (object->*function)(param1, param2, param3); @@ -545,7 +365,7 @@ struct DispatcherReturn0 static R Dispatch(CallbackBase& callback) { // "downcast" the object and function type back to the correct ones - T* object = reinterpret_cast(callback.mImpl->mObjectPointer); + T* object = reinterpret_cast(callback.mImpl.mObjectPointer); using MemberFunction = R (T::*)(); MemberFunction function = reinterpret_cast(callback.mMemberFunction); return (object->*function)(); @@ -570,7 +390,7 @@ struct DispatcherReturn1 static R Dispatch(CallbackBase& callback, P1 param1) { // "downcast" the object and function type back to the correct ones - T* object = reinterpret_cast(callback.mImpl->mObjectPointer); + T* object = reinterpret_cast(callback.mImpl.mObjectPointer); using MemberFunction = R (T::*)(P1); MemberFunction function = reinterpret_cast(callback.mMemberFunction); return (object->*function)(param1); @@ -596,7 +416,7 @@ struct DispatcherReturn2 static R Dispatch(CallbackBase& callback, P1 param1, P2 param2) { // "downcast" the object and function type back to the correct ones - T* object = reinterpret_cast(callback.mImpl->mObjectPointer); + T* object = reinterpret_cast(callback.mImpl.mObjectPointer); using MemberFunction = R (T::*)(P1, P2); MemberFunction function = reinterpret_cast(callback.mMemberFunction); return (object->*function)(param1, param2); @@ -623,7 +443,7 @@ struct DispatcherReturn3 static R Dispatch(CallbackBase& callback, P1 param1, P2 param2, P3 param3) { // "downcast" the object and function type back to the correct ones - T* object = reinterpret_cast(callback.mImpl->mObjectPointer); + T* object = reinterpret_cast(callback.mImpl.mObjectPointer); using MemberFunction = R (T::*)(P1, P2, P3); MemberFunction function = reinterpret_cast(callback.mMemberFunction); return (object->*function)(param1, param2, param3); @@ -646,7 +466,7 @@ struct FunctorDispatcher0 static void Dispatch(CallbackBase& callback) { // "downcast" the object and function type back to the correct ones - T* object = reinterpret_cast(callback.mImpl->mObjectPointer); + T* object = reinterpret_cast(callback.mImpl.mObjectPointer); (*object)(); } }; @@ -668,7 +488,7 @@ struct FunctorDispatcher1 static void Dispatch(CallbackBase& callback, P1 param1) { // "downcast" the object and function type back to the correct ones - T* object = reinterpret_cast(callback.mImpl->mObjectPointer); + T* object = reinterpret_cast(callback.mImpl.mObjectPointer); (*object)(param1); } }; @@ -691,7 +511,7 @@ struct FunctorDispatcher2 static void Dispatch(CallbackBase& callback, P1 param1, P2 param2) { // "downcast" the object and function type back to the correct ones - T* object = reinterpret_cast(callback.mImpl->mObjectPointer); + T* object = reinterpret_cast(callback.mImpl.mObjectPointer); (*object)(param1, param2); } }; @@ -715,7 +535,7 @@ struct FunctorDispatcher3 static void Dispatch(CallbackBase& callback, P1 param1, P2 param2, P3 param3) { // "downcast" the object and function type back to the correct ones - T* object = reinterpret_cast(callback.mImpl->mObjectPointer); + T* object = reinterpret_cast(callback.mImpl.mObjectPointer); (*object)(param1, param2, param3); } }; @@ -737,7 +557,7 @@ struct FunctorDispatcherReturn0 static R Dispatch(CallbackBase& callback) { // "downcast" the object and function type back to the correct ones - T* object = reinterpret_cast(callback.mImpl->mObjectPointer); + T* object = reinterpret_cast(callback.mImpl.mObjectPointer); return (*object)(); } }; @@ -760,7 +580,7 @@ struct FunctorDispatcherReturn1 static R Dispatch(CallbackBase& callback, P1 param1) { // "downcast" the object and function type back to the correct ones - T* object = reinterpret_cast(callback.mImpl->mObjectPointer); + T* object = reinterpret_cast(callback.mImpl.mObjectPointer); return (*object)(param1); } }; @@ -784,7 +604,7 @@ struct FunctorDispatcherReturn2 static R Dispatch(CallbackBase& callback, P1 param1, P2 param2) { // "downcast" the object and function type back to the correct ones - T* object = reinterpret_cast(callback.mImpl->mObjectPointer); + T* object = reinterpret_cast(callback.mImpl.mObjectPointer); return (*object)(param1, param2); } }; @@ -809,7 +629,7 @@ struct FunctorDispatcherReturn3 static R Dispatch(CallbackBase& callback, P1 param1, P2 param2, P3 param3) { // "downcast" the object and function type back to the correct ones - T* object = reinterpret_cast(callback.mImpl->mObjectPointer); + T* object = reinterpret_cast(callback.mImpl.mObjectPointer); return (*object)(param1, param2, param3); } }; @@ -832,7 +652,7 @@ struct VoidFunctorDispatcher0 static void Dispatch(CallbackBase& callback) { // "downcast" the object and function type back to the correct ones - T* object = reinterpret_cast(callback.mImpl->mObjectPointer); + T* object = reinterpret_cast(callback.mImpl.mObjectPointer); using MemberFunction = void (T::*)(); MemberFunction function = reinterpret_cast(callback.mMemberFunction); (object->*function)(); @@ -858,7 +678,7 @@ struct VoidFunctorDispatcher1 static void Dispatch(CallbackBase& callback, P1 param1) { // "downcast" the object and function type back to the correct ones - T* object = reinterpret_cast(callback.mImpl->mObjectPointer); + T* object = reinterpret_cast(callback.mImpl.mObjectPointer); using MemberFunction = void (T::*)(); MemberFunction function = reinterpret_cast(callback.mMemberFunction); (object->*function)(/*ignore params*/); @@ -885,7 +705,7 @@ struct VoidFunctorDispatcher2 static void Dispatch(CallbackBase& callback, P1 param1, P2 param2) { // "downcast" the object and function type back to the correct ones - T* object = reinterpret_cast(callback.mImpl->mObjectPointer); + T* object = reinterpret_cast(callback.mImpl.mObjectPointer); using MemberFunction = void (T::*)(); MemberFunction function = reinterpret_cast(callback.mMemberFunction); (object->*function)(/*ignore params*/); @@ -913,7 +733,7 @@ struct VoidFunctorDispatcher3 static void Dispatch(CallbackBase& callback, P1 param1, P2 param2, P3 param3) { // "downcast" the object and function type back to the correct ones - T* object = reinterpret_cast(callback.mImpl->mObjectPointer); + T* object = reinterpret_cast(callback.mImpl.mObjectPointer); using MemberFunction = void (T::*)(); MemberFunction function = reinterpret_cast(callback.mMemberFunction); (object->*function)(/*ignore params*/); @@ -939,7 +759,7 @@ struct VoidFunctorDispatcherReturn0 static R Dispatch(CallbackBase& callback) { // "downcast" the object and function type back to the correct ones - T* object = reinterpret_cast(callback.mImpl->mObjectPointer); + T* object = reinterpret_cast(callback.mImpl.mObjectPointer); using MemberFunction = void (T::*)(); MemberFunction function = reinterpret_cast(callback.mMemberFunction); (object->*function)(/*ignore params*/); @@ -967,7 +787,7 @@ struct VoidFunctorDispatcherReturn1 static R Dispatch(CallbackBase& callback, P1 param1) { // "downcast" the object and function type back to the correct ones - T* object = reinterpret_cast(callback.mImpl->mObjectPointer); + T* object = reinterpret_cast(callback.mImpl.mObjectPointer); using MemberFunction = void (T::*)(); MemberFunction function = reinterpret_cast(callback.mMemberFunction); (object->*function)(/*ignore params*/); @@ -996,7 +816,7 @@ struct VoidFunctorDispatcherReturn2 static R Dispatch(CallbackBase& callback, P1 param1, P2 param2) { // "downcast" the object and function type back to the correct ones - T* object = reinterpret_cast(callback.mImpl->mObjectPointer); + T* object = reinterpret_cast(callback.mImpl.mObjectPointer); using MemberFunction = void (T::*)(); MemberFunction function = reinterpret_cast(callback.mMemberFunction); (object->*function)(/*ignore params*/); @@ -1026,7 +846,7 @@ struct VoidFunctorDispatcherReturn3 static R Dispatch(CallbackBase& callback, P1 param1, P2 param2, P3 param3) { // "downcast" the object and function type back to the correct ones - T* object = reinterpret_cast(callback.mImpl->mObjectPointer); + T* object = reinterpret_cast(callback.mImpl.mObjectPointer); using MemberFunction = void (T::*)(); MemberFunction function = reinterpret_cast(callback.mMemberFunction); (object->*function)(/*ignore params*/); @@ -1120,69 +940,6 @@ public: }; /** - * @brief Specializations for static function callbacks. - * @SINCE_1_0.0 - */ -class CallbackFunction : public CallbackBase -{ -public: - /** - * @brief Default constructor. - * @SINCE_1_0.0 - */ - CallbackFunction() - : CallbackBase() - { - } - - /** - * @brief Constructors for functions with static linkage. - * - * @SINCE_1_0.0 - * @param[in] function The function to call - */ - CallbackFunction(void (*function)()) - : CallbackBase(reinterpret_cast(function)) - { - } - template - CallbackFunction(R (*function)()) - : CallbackBase(reinterpret_cast(function)) - { - } - template - CallbackFunction(void (*function)(P1)) - : CallbackBase(reinterpret_cast(function)) - { - } - template - CallbackFunction(R (*function)(P1)) - : CallbackBase(reinterpret_cast(function)) - { - } - template - CallbackFunction(void (*function)(P1, P2)) - : CallbackBase(reinterpret_cast(function)) - { - } - template - CallbackFunction(R (*function)(P1, P2)) - : CallbackBase(reinterpret_cast(function)) - { - } - template - CallbackFunction(void (*function)(P1, P2, P3)) - : CallbackBase(reinterpret_cast(function)) - { - } - template - CallbackFunction(R (*function)(P1, P2, P3)) - : CallbackBase(reinterpret_cast(function)) - { - } -}; - -/** * @brief Specializations for function object callbacks. * @SINCE_1_0.0 */ @@ -1560,106 +1317,16 @@ public: // Callback creation thin templates /** - * @brief Creates a callback from a C function or static member function with no parameters. - * - * @SINCE_1_0.0 - * @param[in] function The function to call - * @return A newly allocated Callback object, ownership transferred to caller - */ -inline CallbackBase* MakeCallback(void (*function)(void)) -{ - return new CallbackFunction(function); -} - -/** - * @brief Creates a callback from a C function or static member function with one parameter. - * - * @SINCE_1_0.0 - * @param[in] function The function to call - * @return A newly allocated Callback object, ownership transferred to caller - */ -template -inline CallbackBase* MakeCallback(void (*function)(P1)) -{ - return new CallbackFunction(function); -} - -/** - * @brief Creates a callback from a C function or static member function with no parameters and a return type. - * - * @SINCE_1_0.0 - * @param[in] function The function to call - * @return A newly allocated Callback object, ownership transferred to caller - */ -template -inline CallbackBase* MakeCallback(R (*function)(void)) -{ - return new CallbackFunction(function); -} - -/** - * @brief Creates a callback from a C function or static member function with one parameter and a return type. + * @brief Creates a callback from a free function with parameter pack. * - * @SINCE_1_0.0 - * @param[in] function The function to call - * @return A newly allocated Callback object, ownership transferred to caller - */ -template -inline CallbackBase* MakeCallback(R (*function)(P1)) -{ - return new CallbackFunction(function); -} - -/** - * @brief Creates a callback from a C function or static member function with two parameters. - * - * @SINCE_1_0.0 - * @param[in] function The function to call - * @return A newly allocated Callback object, ownership transferred to caller - */ -template -inline CallbackBase* MakeCallback(void (*function)(P1, P2)) -{ - return new CallbackFunction(function); -} - -/** - * @brief Creates a callback from a C function or static member function with two parameters and a return type. - * - * @SINCE_1_0.0 - * @param[in] function The function to call - * @return A newly allocated Callback object, ownership transferred to caller - */ -template -inline CallbackBase* MakeCallback(R (*function)(P1, P2)) -{ - return new CallbackFunction(function); -} - -/** - * @brief Creates a callback from a C function or static member function with three parameters. - * - * @SINCE_1_0.0 - * @param[in] function The function to call - * @return A newly allocated Callback object, ownership transferred to caller - */ -template -inline CallbackBase* MakeCallback(void (*function)(P1, P2, P3)) -{ - return new CallbackFunction(function); -} - -/** - * @brief Creates a callback from a C function or static member function with three parameters and a return type. - * - * @SINCE_1_0.0 + * @SINCE_1_9.33 * @param[in] function The function to call * @return A newly allocated Callback object, ownership transferred to caller */ -template -inline CallbackBase* MakeCallback(R (*function)(P1, P2, P3)) +template +inline CallbackBase* MakeCallback(R (*function)(Args... args)) { - return new CallbackFunction(function); + return new CallbackBase(reinterpret_cast(function)); } /** diff --git a/dali/public-api/signals/connection-tracker.cpp b/dali/public-api/signals/connection-tracker.cpp index fbab2a4..ef7a4c5 100644 --- a/dali/public-api/signals/connection-tracker.cpp +++ b/dali/public-api/signals/connection-tracker.cpp @@ -39,12 +39,11 @@ void ConnectionTracker::DisconnectAll() for(std::size_t i = 0; i < size; ++i) { - SlotConnection* connection = mConnections[i]; + auto& connection = mConnections[i]; // Tell the signal that the slot is disconnected - connection->GetSlotObserver()->SlotDisconnected(connection->GetCallback()); + connection.GetSlotObserver()->SlotDisconnected(connection.GetCallback()); - delete connection; } mConnections.Clear(); @@ -52,8 +51,7 @@ void ConnectionTracker::DisconnectAll() void ConnectionTracker::SignalConnected(SlotObserver* slotObserver, CallbackBase* callback) { - SlotConnection* connection = new SlotConnection(slotObserver, callback); - mConnections.PushBack(connection); + mConnections.PushBack(SlotConnection(slotObserver, callback)); } void ConnectionTracker::SignalDisconnected(SlotObserver* signal, CallbackBase* callback) @@ -62,17 +60,14 @@ void ConnectionTracker::SignalDisconnected(SlotObserver* signal, CallbackBase* c for(std::size_t i = 0; i < size; ++i) { - SlotConnection* connection = mConnections[i]; + auto& connection = mConnections[i]; // Pointer comparison i.e. SignalConnection contains pointer to same callback instance - if(connection->GetCallback() == callback) + if(connection.GetCallback() == callback) { // Remove from connection list mConnections.Erase(mConnections.Begin() + i); - // Delete connection - delete connection; - // Disconnection complete return; } diff --git a/dali/public-api/signals/connection-tracker.h b/dali/public-api/signals/connection-tracker.h index 2d1538a..d2f6262 100644 --- a/dali/public-api/signals/connection-tracker.h +++ b/dali/public-api/signals/connection-tracker.h @@ -22,6 +22,7 @@ #include #include #include +#include namespace Dali { @@ -83,7 +84,7 @@ private: ConnectionTracker& operator=(ConnectionTracker&&) = delete; ///< Deleted move assignment operator. @SINCE_1_9.25 private: - Dali::Vector mConnections; ///< Vector of connection pointers + Dali::Vector mConnections; ///< Vector of connection }; /** diff --git a/dali/public-api/signals/dali-signal.h b/dali/public-api/signals/dali-signal.h index 7931c6a..c4fd2ed 100644 --- a/dali/public-api/signals/dali-signal.h +++ b/dali/public-api/signals/dali-signal.h @@ -52,6 +52,9 @@ * @SINCE_1_0.0 */ +// EXTERNAL_INCLUDES +#include + // INTERNAL INCLUDES #include #include @@ -137,31 +140,10 @@ class Signal { }; -/** - * @brief A template for Signals with no parameters or return value. - * @SINCE_1_0.0 - */ -template<> -class Signal +class SignalMixin { public: /** - * @brief Default constructor. - * @SINCE_1_0.0 - */ - Signal() - { - } - - /** - * @brief Non-virtual destructor. - * @SINCE_1_0.0 - */ - ~Signal() - { - } - - /** * @brief Queries whether there are any connected slots. * * @SINCE_1_0.0 @@ -169,7 +151,7 @@ public: */ bool Empty() const { - return mImpl.Empty(); + return mImpl ? mImpl->Empty() : true; } /** @@ -180,9 +162,31 @@ public: */ std::size_t GetConnectionCount() const { - return mImpl.GetConnectionCount(); + return mImpl ? mImpl->GetConnectionCount() : 0; } +protected: + BaseSignal& Impl() + { + if(!mImpl) + { + mImpl = std::make_unique(); + } + return *mImpl; + } + +private: + std::unique_ptr mImpl; +}; + +/** + * @brief A template for Signals with no parameters or return value. + * @SINCE_1_0.0 + */ +template<> +class Signal : public SignalMixin +{ +public: /** * @brief Connects a function. * @@ -191,7 +195,7 @@ public: */ void Connect(void (*func)()) { - mImpl.OnConnect(MakeCallback(func)); + Impl().OnConnect(MakeCallback(func)); } /** @@ -202,7 +206,7 @@ public: */ void Disconnect(void (*func)()) { - mImpl.OnDisconnect(MakeCallback(func)); + Impl().OnDisconnect(MakeCallback(func)); } /** @@ -215,7 +219,7 @@ public: template void Connect(X* obj, void (X::*func)()) { - mImpl.OnConnect(obj, MakeCallback(obj, func)); + Impl().OnConnect(obj, MakeCallback(obj, func)); } /** @@ -228,7 +232,7 @@ public: template void Disconnect(X* obj, void (X::*func)()) { - mImpl.OnDisconnect(obj, MakeCallback(obj, func)); + Impl().OnDisconnect(obj, MakeCallback(obj, func)); } /** @@ -241,7 +245,7 @@ public: template void Connect(SlotDelegate& delegate, void (X::*func)()) { - mImpl.OnConnect(delegate.GetConnectionTracker(), MakeCallback(delegate.GetSlot(), func)); + Impl().OnConnect(delegate.GetConnectionTracker(), MakeCallback(delegate.GetSlot(), func)); } /** @@ -254,7 +258,7 @@ public: template void Disconnect(SlotDelegate& delegate, void (X::*func)()) { - mImpl.OnDisconnect(delegate.GetConnectionTracker(), MakeCallback(delegate.GetSlot(), func)); + Impl().OnDisconnect(delegate.GetConnectionTracker(), MakeCallback(delegate.GetSlot(), func)); } /** @@ -267,7 +271,7 @@ public: template void Connect(ConnectionTrackerInterface* connectionTracker, const X& func) { - mImpl.OnConnect(connectionTracker, new CallbackFunctor0(func)); + Impl().OnConnect(connectionTracker, new CallbackFunctor0(func)); } /** @@ -279,7 +283,7 @@ public: */ void Connect(ConnectionTrackerInterface* connectionTracker, FunctorDelegate* delegate) { - mImpl.OnConnect(connectionTracker, new CallbackFunctorDelegate0(delegate)); + Impl().OnConnect(connectionTracker, new CallbackFunctorDelegate0(delegate)); } /** @@ -288,18 +292,8 @@ public: */ void Emit() { - mImpl.Emit(); + Impl().Emit(); } - -private: - Signal(const Signal&) = delete; ///< Deleted copy constructor, signals don't support copying. @SINCE_1_0.0 - Signal(Signal&&) = delete; ///< Deleted move constructor, signals don't support moving. @SINCE_1_9.25 - Signal& operator=(const Signal&) = delete; ///< Deleted copy assignment operator @SINCE_1_0.0 - Signal& operator=(Signal&&) = delete; ///< Deleted move assignment operator @SINCE_1_9.25 - -private: - // Use composition instead of inheritance (virtual methods don't mix well with templates) - BaseSignal mImpl; ///< The base signal implementation }; /** @@ -307,47 +301,10 @@ private: * @SINCE_1_0.0 */ template -class Signal +class Signal : public SignalMixin { public: /** - * @brief Default constructor. - * @SINCE_1_0.0 - */ - Signal() - { - } - - /** - * @brief Non-virtual destructor. - * @SINCE_1_0.0 - */ - ~Signal() - { - } - - /** - * @brief Queries whether there are any connected slots. - * - * @SINCE_1_0.0 - * @return True if there are any slots connected to the signal - */ - bool Empty() const - { - return mImpl.Empty(); - } - - /** - * @brief Queries the number of slots. - * - * @SINCE_1_0.0 - * @return The number of slots connected to this signal - */ - std::size_t GetConnectionCount() const - { - return mImpl.GetConnectionCount(); - } - /** * @brief Connects a function. * * @SINCE_1_0.0 @@ -355,7 +312,7 @@ public: */ void Connect(Ret (*func)()) { - mImpl.OnConnect(MakeCallback(func)); + Impl().OnConnect(MakeCallback(func)); } /** @@ -366,7 +323,7 @@ public: */ void Disconnect(Ret (*func)()) { - mImpl.OnDisconnect(MakeCallback(func)); + Impl().OnDisconnect(MakeCallback(func)); } /** @@ -379,7 +336,7 @@ public: template void Connect(X* obj, Ret (X::*func)()) { - mImpl.OnConnect(obj, MakeCallback(obj, func)); + Impl().OnConnect(obj, MakeCallback(obj, func)); } /** @@ -392,7 +349,7 @@ public: template void Disconnect(X* obj, Ret (X::*func)()) { - mImpl.OnDisconnect(obj, MakeCallback(obj, func)); + Impl().OnDisconnect(obj, MakeCallback(obj, func)); } /** @@ -405,7 +362,7 @@ public: template void Connect(SlotDelegate& delegate, Ret (X::*func)()) { - mImpl.OnConnect(delegate.GetConnectionTracker(), MakeCallback(delegate.GetSlot(), func)); + Impl().OnConnect(delegate.GetConnectionTracker(), MakeCallback(delegate.GetSlot(), func)); } /** @@ -418,7 +375,7 @@ public: template void Disconnect(SlotDelegate& delegate, Ret (X::*func)()) { - mImpl.OnDisconnect(delegate.GetConnectionTracker(), MakeCallback(delegate.GetSlot(), func)); + Impl().OnDisconnect(delegate.GetConnectionTracker(), MakeCallback(delegate.GetSlot(), func)); } /** @@ -431,7 +388,7 @@ public: template void Connect(ConnectionTrackerInterface* connectionTracker, const X& func) { - mImpl.OnConnect(connectionTracker, new CallbackFunctorReturn0(func)); + Impl().OnConnect(connectionTracker, new CallbackFunctorReturn0(func)); } /** @@ -443,7 +400,7 @@ public: */ void Connect(ConnectionTrackerInterface* connectionTracker, FunctorDelegate* delegate) { - mImpl.OnConnect(connectionTracker, new CallbackFunctorDelegateReturn0(delegate)); + Impl().OnConnect(connectionTracker, new CallbackFunctorDelegateReturn0(delegate)); } /** @@ -454,18 +411,8 @@ public: */ Ret Emit() { - return mImpl.EmitReturn(); + return Impl().template EmitReturn(); } - -private: - Signal(const Signal&) = delete; ///< Deleted copy constructor, signals don't support copying. @SINCE_1_0.0 - Signal(Signal&&) = delete; ///< Deleted move constructor, signals don't support moving. @SINCE_1_9.25 - Signal& operator=(const Signal&) = delete; ///< Deleted copy assignment operator @SINCE_1_0.0 - Signal& operator=(Signal&&) = delete; ///< Deleted move assignment operator @SINCE_1_9.25 - -private: - // Use composition instead of inheritance (virtual methods don't mix well with templates) - BaseSignal mImpl; ///< Implementation }; /** @@ -473,47 +420,10 @@ private: * @SINCE_1_0.0 */ template -class Signal +class Signal : public SignalMixin { public: /** - * @brief Default constructor. - * @SINCE_1_0.0 - */ - Signal() - { - } - - /** - * @brief Non-virtual destructor. - * @SINCE_1_0.0 - */ - ~Signal() - { - } - - /** - * @brief Queries whether there are any connected slots. - * - * @SINCE_1_0.0 - * @return True if there are any slots connected to the signal - */ - bool Empty() const - { - return mImpl.Empty(); - } - - /** - * @brief Queries the number of slots. - * - * @SINCE_1_0.0 - * @return The number of slots connected to this signal - */ - std::size_t GetConnectionCount() const - { - return mImpl.GetConnectionCount(); - } - /** * @brief Connects a function. * * @SINCE_1_0.0 @@ -521,7 +431,7 @@ public: */ void Connect(void (*func)(Arg0 arg0)) { - mImpl.OnConnect(MakeCallback(func)); + Impl().OnConnect(MakeCallback(func)); } /** @@ -532,7 +442,7 @@ public: */ void Disconnect(void (*func)(Arg0 arg0)) { - mImpl.OnDisconnect(MakeCallback(func)); + Impl().OnDisconnect(MakeCallback(func)); } /** @@ -545,7 +455,7 @@ public: template void Connect(X* obj, void (X::*func)(Arg0 arg0)) { - mImpl.OnConnect(obj, MakeCallback(obj, func)); + Impl().OnConnect(obj, MakeCallback(obj, func)); } /** @@ -558,7 +468,7 @@ public: template void Disconnect(X* obj, void (X::*func)(Arg0 arg0)) { - mImpl.OnDisconnect(obj, MakeCallback(obj, func)); + Impl().OnDisconnect(obj, MakeCallback(obj, func)); } /** @@ -571,7 +481,7 @@ public: template void Connect(SlotDelegate& delegate, void (X::*func)(Arg0 arg0)) { - mImpl.OnConnect(delegate.GetConnectionTracker(), MakeCallback(delegate.GetSlot(), func)); + Impl().OnConnect(delegate.GetConnectionTracker(), MakeCallback(delegate.GetSlot(), func)); } /** @@ -584,7 +494,7 @@ public: template void Disconnect(SlotDelegate& delegate, void (X::*func)(Arg0 arg0)) { - mImpl.OnDisconnect(delegate.GetConnectionTracker(), MakeCallback(delegate.GetSlot(), func)); + Impl().OnDisconnect(delegate.GetConnectionTracker(), MakeCallback(delegate.GetSlot(), func)); } /** @@ -597,7 +507,7 @@ public: template void Connect(ConnectionTrackerInterface* connectionTracker, const X& func) { - mImpl.OnConnect(connectionTracker, new CallbackFunctor1(func)); + Impl().OnConnect(connectionTracker, new CallbackFunctor1(func)); } /** @@ -609,7 +519,7 @@ public: */ void Connect(ConnectionTrackerInterface* connectionTracker, FunctorDelegate* delegate) { - mImpl.OnConnect(connectionTracker, new CallbackFunctorDelegate1(delegate)); + Impl().OnConnect(connectionTracker, new CallbackFunctorDelegate1(delegate)); } /** @@ -620,18 +530,8 @@ public: */ void Emit(Arg0 arg0) { - mImpl.Emit(arg0); + Impl().template Emit(arg0); } - -private: - Signal(const Signal&) = delete; ///< Deleted copy constructor, signals don't support copying. @SINCE_1_0.0 - Signal(Signal&&) = delete; ///< Deleted move constructor, signals don't support moving. @SINCE_1_9.25 - Signal& operator=(const Signal&) = delete; ///< Deleted copy assignment operator @SINCE_1_0.0 - Signal& operator=(Signal&&) = delete; ///< Deleted move assignment operator @SINCE_1_9.25 - -private: - // Use composition instead of inheritance (virtual methods don't mix well with templates) - BaseSignal mImpl; ///< Implementation }; /** @@ -639,47 +539,10 @@ private: * @SINCE_1_0.0 */ template -class Signal +class Signal : public SignalMixin { public: /** - * @brief Default constructor. - * @SINCE_1_0.0 - */ - Signal() - { - } - - /** - * @brief Non-virtual destructor. - * @SINCE_1_0.0 - */ - ~Signal() - { - } - - /** - * @brief Queries whether there are any connected slots. - * - * @SINCE_1_0.0 - * @return True if there are any slots connected to the signal - */ - bool Empty() const - { - return mImpl.Empty(); - } - - /** - * @brief Queries the number of slots. - * - * @SINCE_1_0.0 - * @return The number of slots connected to this signal - */ - std::size_t GetConnectionCount() const - { - return mImpl.GetConnectionCount(); - } - /** * @brief Connects a function. * * @SINCE_1_0.0 @@ -687,7 +550,7 @@ public: */ void Connect(Ret (*func)(Arg0 arg0)) { - mImpl.OnConnect(MakeCallback(func)); + Impl().OnConnect(MakeCallback(func)); } /** @@ -698,7 +561,7 @@ public: */ void Disconnect(Ret (*func)(Arg0 arg0)) { - mImpl.OnDisconnect(MakeCallback(func)); + Impl().OnDisconnect(MakeCallback(func)); } /** @@ -711,7 +574,7 @@ public: template void Connect(X* obj, Ret (X::*func)(Arg0 arg0)) { - mImpl.OnConnect(obj, MakeCallback(obj, func)); + Impl().OnConnect(obj, MakeCallback(obj, func)); } /** @@ -724,7 +587,7 @@ public: template void Disconnect(X* obj, Ret (X::*func)(Arg0 arg0)) { - mImpl.OnDisconnect(obj, MakeCallback(obj, func)); + Impl().OnDisconnect(obj, MakeCallback(obj, func)); } /** @@ -737,7 +600,7 @@ public: template void Connect(SlotDelegate& delegate, Ret (X::*func)(Arg0 arg0)) { - mImpl.OnConnect(delegate.GetConnectionTracker(), MakeCallback(delegate.GetSlot(), func)); + Impl().OnConnect(delegate.GetConnectionTracker(), MakeCallback(delegate.GetSlot(), func)); } /** @@ -750,7 +613,7 @@ public: template void Disconnect(SlotDelegate& delegate, Ret (X::*func)(Arg0 arg0)) { - mImpl.OnDisconnect(delegate.GetConnectionTracker(), MakeCallback(delegate.GetSlot(), func)); + Impl().OnDisconnect(delegate.GetConnectionTracker(), MakeCallback(delegate.GetSlot(), func)); } /** @@ -763,7 +626,7 @@ public: template void Connect(ConnectionTrackerInterface* connectionTracker, const X& func) { - mImpl.OnConnect(connectionTracker, new CallbackFunctorReturn1(func)); + Impl().OnConnect(connectionTracker, new CallbackFunctorReturn1(func)); } /** @@ -775,7 +638,7 @@ public: */ void Connect(ConnectionTrackerInterface* connectionTracker, FunctorDelegate* delegate) { - mImpl.OnConnect(connectionTracker, new CallbackFunctorDelegateReturn1(delegate)); + Impl().OnConnect(connectionTracker, new CallbackFunctorDelegateReturn1(delegate)); } /** @@ -787,18 +650,8 @@ public: */ Ret Emit(Arg0 arg0) { - return mImpl.EmitReturn(arg0); + return Impl().template EmitReturn(arg0); } - -private: - Signal(const Signal&) = delete; ///< Deleted copy constructor, signals don't support copying. @SINCE_1_0.0 - Signal(Signal&&) = delete; ///< Deleted move constructor, signals don't support moving. @SINCE_1_9.25 - Signal& operator=(const Signal&) = delete; ///< Deleted copy assignment operator @SINCE_1_0.0 - Signal& operator=(Signal&&) = delete; ///< Deleted move assignment operator @SINCE_1_9.25 - -private: - // Use composition instead of inheritance (virtual methods don't mix well with templates) - BaseSignal mImpl; ///< Implementation }; /** @@ -807,49 +660,10 @@ private: * @SINCE_1_0.0 */ template -class Signal +class Signal : public SignalMixin { public: /** - * @brief Default constructor. - * - * @SINCE_1_0.0 - */ - Signal() - { - } - - /** - * @brief Non-virtual destructor. - * - * @SINCE_1_0.0 - */ - ~Signal() - { - } - - /** - * @brief Queries whether there are any connected slots. - * - * @SINCE_1_0.0 - * @return True if there are any slots connected to the signal - */ - bool Empty() const - { - return mImpl.Empty(); - } - - /** - * @brief Queries the number of slots. - * - * @SINCE_1_0.0 - * @return The number of slots connected to this signal - */ - std::size_t GetConnectionCount() const - { - return mImpl.GetConnectionCount(); - } - /** * @brief Connects a function. * * @SINCE_1_0.0 @@ -857,7 +671,7 @@ public: */ void Connect(void (*func)(Arg0 arg0, Arg1 arg1)) { - mImpl.OnConnect(MakeCallback(func)); + Impl().OnConnect(MakeCallback(func)); } /** @@ -868,7 +682,7 @@ public: */ void Disconnect(void (*func)(Arg0 arg0, Arg1 arg1)) { - mImpl.OnDisconnect(MakeCallback(func)); + Impl().OnDisconnect(MakeCallback(func)); } /** @@ -881,7 +695,7 @@ public: template void Connect(X* obj, void (X::*func)(Arg0 arg0, Arg1 arg1)) { - mImpl.OnConnect(obj, MakeCallback(obj, func)); + Impl().OnConnect(obj, MakeCallback(obj, func)); } /** @@ -894,7 +708,7 @@ public: template void Disconnect(X* obj, void (X::*func)(Arg0 arg0, Arg1 arg1)) { - mImpl.OnDisconnect(obj, MakeCallback(obj, func)); + Impl().OnDisconnect(obj, MakeCallback(obj, func)); } /** @@ -907,7 +721,7 @@ public: template void Connect(SlotDelegate& delegate, void (X::*func)(Arg0 arg0, Arg1 arg1)) { - mImpl.OnConnect(delegate.GetConnectionTracker(), MakeCallback(delegate.GetSlot(), func)); + Impl().OnConnect(delegate.GetConnectionTracker(), MakeCallback(delegate.GetSlot(), func)); } /** @@ -920,7 +734,7 @@ public: template void Disconnect(SlotDelegate& delegate, void (X::*func)(Arg0 arg0, Arg1 arg1)) { - mImpl.OnDisconnect(delegate.GetConnectionTracker(), MakeCallback(delegate.GetSlot(), func)); + Impl().OnDisconnect(delegate.GetConnectionTracker(), MakeCallback(delegate.GetSlot(), func)); } /** @@ -933,7 +747,7 @@ public: template void Connect(ConnectionTrackerInterface* connectionTracker, const X& func) { - mImpl.OnConnect(connectionTracker, new CallbackFunctor2(func)); + Impl().OnConnect(connectionTracker, new CallbackFunctor2(func)); } /** @@ -945,7 +759,7 @@ public: */ void Connect(ConnectionTrackerInterface* connectionTracker, FunctorDelegate* delegate) { - mImpl.OnConnect(connectionTracker, new CallbackFunctorDelegate2(delegate)); + Impl().OnConnect(connectionTracker, new CallbackFunctorDelegate2(delegate)); } /** @@ -957,18 +771,8 @@ public: */ void Emit(Arg0 arg0, Arg1 arg1) { - mImpl.Emit(arg0, arg1); + Impl().template Emit(arg0, arg1); } - -private: - Signal(const Signal&) = delete; ///< Deleted copy constructor, signals don't support copying. @SINCE_1_0.0 - Signal(Signal&&) = delete; ///< Deleted move constructor, signals don't support moving. @SINCE_1_9.25 - Signal& operator=(const Signal&) = delete; ///< Deleted copy assignment operator @SINCE_1_0.0 - Signal& operator=(Signal&&) = delete; ///< Deleted move assignment operator @SINCE_1_9.25 - -private: - // Use composition instead of inheritance (virtual methods don't mix well with templates) - BaseSignal mImpl; ///< Implementation }; /** @@ -976,54 +780,17 @@ private: * @SINCE_1_0.0 */ template -class Signal +class Signal : public SignalMixin { public: /** - * @brief Default constructor. - * @SINCE_1_0.0 - */ - Signal() - { - } - - /** - * @brief Non-virtual destructor. - * @SINCE_1_0.0 - */ - ~Signal() - { - } - - /** - * @brief Queries whether there are any connected slots. - * - * @SINCE_1_0.0 - * @return True if there are any slots connected to the signal - */ - bool Empty() const - { - return mImpl.Empty(); - } - - /** - * @brief Queries the number of slots. - * - * @SINCE_1_0.0 - * @return The number of slots connected to this signal - */ - std::size_t GetConnectionCount() const - { - return mImpl.GetConnectionCount(); - } - /** * @brief Connects a function. * @SINCE_1_0.0 * @param[in] func The function to connect */ void Connect(Ret (*func)(Arg0 arg0, Arg1 arg1)) { - mImpl.OnConnect(MakeCallback(func)); + Impl().OnConnect(MakeCallback(func)); } /** @@ -1034,7 +801,7 @@ public: */ void Disconnect(Ret (*func)(Arg0 arg0, Arg1 arg1)) { - mImpl.OnDisconnect(MakeCallback(func)); + Impl().OnDisconnect(MakeCallback(func)); } /** @@ -1047,7 +814,7 @@ public: template void Connect(X* obj, Ret (X::*func)(Arg0 arg0, Arg1 arg1)) { - mImpl.OnConnect(obj, MakeCallback(obj, func)); + Impl().OnConnect(obj, MakeCallback(obj, func)); } /** @@ -1060,7 +827,7 @@ public: template void Disconnect(X* obj, Ret (X::*func)(Arg0 arg0, Arg1 arg1)) { - mImpl.OnDisconnect(obj, MakeCallback(obj, func)); + Impl().OnDisconnect(obj, MakeCallback(obj, func)); } /** @@ -1073,7 +840,7 @@ public: template void Connect(SlotDelegate& delegate, Ret (X::*func)(Arg0 arg0, Arg1 arg1)) { - mImpl.OnConnect(delegate.GetConnectionTracker(), MakeCallback(delegate.GetSlot(), func)); + Impl().OnConnect(delegate.GetConnectionTracker(), MakeCallback(delegate.GetSlot(), func)); } /** @@ -1086,7 +853,7 @@ public: template void Disconnect(SlotDelegate& delegate, Ret (X::*func)(Arg0 arg0, Arg1 arg1)) { - mImpl.OnDisconnect(delegate.GetConnectionTracker(), MakeCallback(delegate.GetSlot(), func)); + Impl().OnDisconnect(delegate.GetConnectionTracker(), MakeCallback(delegate.GetSlot(), func)); } /** @@ -1099,7 +866,7 @@ public: template void Connect(ConnectionTrackerInterface* connectionTracker, const X& func) { - mImpl.OnConnect(connectionTracker, new CallbackFunctorReturn2(func)); + Impl().OnConnect(connectionTracker, new CallbackFunctorReturn2(func)); } /** @@ -1111,7 +878,7 @@ public: */ void Connect(ConnectionTrackerInterface* connectionTracker, FunctorDelegate* delegate) { - mImpl.OnConnect(connectionTracker, new CallbackFunctorDelegateReturn2(delegate)); + Impl().OnConnect(connectionTracker, new CallbackFunctorDelegateReturn2(delegate)); } /** @@ -1124,18 +891,8 @@ public: */ Ret Emit(Arg0 arg0, Arg1 arg1) { - return mImpl.EmitReturn(arg0, arg1); + return Impl().template EmitReturn(arg0, arg1); } - -private: - Signal(const Signal&) = delete; ///< Deleted copy constructor, signals don't support copying. @SINCE_1_0.0 - Signal(Signal&&) = delete; ///< Deleted move constructor, signals don't support moving. @SINCE_1_9.25 - Signal& operator=(const Signal&) = delete; ///< Deleted copy assignment operator @SINCE_1_0.0 - Signal& operator=(Signal&&) = delete; ///< Deleted move assignment operator @SINCE_1_9.25 - -private: - // Use composition instead of inheritance (virtual methods don't mix well with templates) - BaseSignal mImpl; ///< Implementation }; /** @@ -1143,47 +900,10 @@ private: * @SINCE_1_0.0 */ template -class Signal +class Signal : public SignalMixin { public: /** - * @brief Default constructor. - * @SINCE_1_0.0 - */ - Signal() - { - } - - /** - * @brief Non-virtual destructor. - * @SINCE_1_0.0 - */ - ~Signal() - { - } - - /** - * @brief Queries whether there are any connected slots. - * - * @SINCE_1_0.0 - * @return True if there are any slots connected to the signal - */ - bool Empty() const - { - return mImpl.Empty(); - } - - /** - * @brief Queries the number of slots. - * - * @SINCE_1_0.0 - * @return The number of slots connected to this signal - */ - std::size_t GetConnectionCount() const - { - return mImpl.GetConnectionCount(); - } - /** * @brief Connects a function. * * @SINCE_1_0.0 @@ -1191,7 +911,7 @@ public: */ void Connect(void (*func)(Arg0 arg0, Arg1 arg1, Arg2 arg2)) { - mImpl.OnConnect(MakeCallback(func)); + Impl().OnConnect(MakeCallback(func)); } /** @@ -1202,7 +922,7 @@ public: */ void Disconnect(void (*func)(Arg0 arg0, Arg1 arg1, Arg2 arg2)) { - mImpl.OnDisconnect(MakeCallback(func)); + Impl().OnDisconnect(MakeCallback(func)); } /** @@ -1215,7 +935,7 @@ public: template void Connect(X* obj, void (X::*func)(Arg0 arg0, Arg1 arg1, Arg2 arg2)) { - mImpl.OnConnect(obj, MakeCallback(obj, func)); + Impl().OnConnect(obj, MakeCallback(obj, func)); } /** @@ -1228,7 +948,7 @@ public: template void Disconnect(X* obj, void (X::*func)(Arg0 arg0, Arg1 arg1, Arg2 arg2)) { - mImpl.OnDisconnect(obj, MakeCallback(obj, func)); + Impl().OnDisconnect(obj, MakeCallback(obj, func)); } /** @@ -1241,7 +961,7 @@ public: template void Connect(SlotDelegate& delegate, void (X::*func)(Arg0 arg0, Arg1 arg1, Arg2 arg2)) { - mImpl.OnConnect(delegate.GetConnectionTracker(), MakeCallback(delegate.GetSlot(), func)); + Impl().OnConnect(delegate.GetConnectionTracker(), MakeCallback(delegate.GetSlot(), func)); } /** @@ -1254,7 +974,7 @@ public: template void Disconnect(SlotDelegate& delegate, void (X::*func)(Arg0 arg0, Arg1 arg1, Arg2 arg2)) { - mImpl.OnDisconnect(delegate.GetConnectionTracker(), MakeCallback(delegate.GetSlot(), func)); + Impl().OnDisconnect(delegate.GetConnectionTracker(), MakeCallback(delegate.GetSlot(), func)); } /** @@ -1267,7 +987,7 @@ public: template void Connect(ConnectionTrackerInterface* connectionTracker, const X& func) { - mImpl.OnConnect(connectionTracker, new CallbackFunctor3(func)); + Impl().OnConnect(connectionTracker, new CallbackFunctor3(func)); } /** @@ -1279,7 +999,7 @@ public: */ void Connect(ConnectionTrackerInterface* connectionTracker, FunctorDelegate* delegate) { - mImpl.OnConnect(connectionTracker, new CallbackFunctorDelegate3(delegate)); + Impl().OnConnect(connectionTracker, new CallbackFunctorDelegate3(delegate)); } /** @@ -1292,18 +1012,8 @@ public: */ void Emit(Arg0 arg0, Arg1 arg1, Arg2 arg2) { - mImpl.Emit(arg0, arg1, arg2); + Impl().template Emit(arg0, arg1, arg2); } - -private: - Signal(const Signal&) = delete; ///< Deleted copy constructor, signals don't support copying. @SINCE_1_0.0 - Signal(Signal&&) = delete; ///< Deleted move constructor, signals don't support moving. @SINCE_1_9.25 - Signal& operator=(const Signal&) = delete; ///< Deleted copy assignment operator @SINCE_1_0.0 - Signal& operator=(Signal&&) = delete; ///< Deleted move assignment operator @SINCE_1_9.25 - -private: - // Use composition instead of inheritance (virtual methods don't mix well with templates) - BaseSignal mImpl; ///< Implementation }; /** @@ -1311,48 +1021,10 @@ private: * @SINCE_1_0.0 */ template -class Signal +class Signal : public SignalMixin { public: /** - * @brief Default constructor. - * @SINCE_1_0.0 - */ - Signal() - { - } - - /** - * @brief Non-virtual destructor. - * @SINCE_1_0.0 - */ - ~Signal() - { - } - - /** - * @brief Queries whether there are any connected slots. - * - * @SINCE_1_0.0 - * @return True if there are any slots connected to the signal - */ - bool Empty() const - { - return mImpl.Empty(); - } - - /** - * @brief Queries the number of slots. - * - * @SINCE_1_0.0 - * @return The number of slots connected to this signal - */ - std::size_t GetConnectionCount() const - { - return mImpl.GetConnectionCount(); - } - - /** * @brief Connects a function. * * @SINCE_1_0.0 @@ -1360,7 +1032,7 @@ public: */ void Connect(Ret (*func)(Arg0 arg0, Arg1 arg1, Arg2 arg2)) { - mImpl.OnConnect(MakeCallback(func)); + Impl().OnConnect(MakeCallback(func)); } /** @@ -1371,7 +1043,7 @@ public: */ void Disconnect(Ret (*func)(Arg0 arg0, Arg1 arg1, Arg2 arg2)) { - mImpl.OnDisconnect(MakeCallback(func)); + Impl().OnDisconnect(MakeCallback(func)); } /** @@ -1384,7 +1056,7 @@ public: template void Connect(X* obj, Ret (X::*func)(Arg0 arg0, Arg1 arg1, Arg2 arg2)) { - mImpl.OnConnect(obj, MakeCallback(obj, func)); + Impl().OnConnect(obj, MakeCallback(obj, func)); } /** @@ -1397,7 +1069,7 @@ public: template void Disconnect(X* obj, Ret (X::*func)(Arg0 arg0, Arg1 arg1, Arg2 arg2)) { - mImpl.OnDisconnect(obj, MakeCallback(obj, func)); + Impl().OnDisconnect(obj, MakeCallback(obj, func)); } /** @@ -1410,7 +1082,7 @@ public: template void Connect(SlotDelegate& delegate, Ret (X::*func)(Arg0 arg0, Arg1 arg1, Arg2 arg2)) { - mImpl.OnConnect(delegate.GetConnectionTracker(), MakeCallback(delegate.GetSlot(), func)); + Impl().OnConnect(delegate.GetConnectionTracker(), MakeCallback(delegate.GetSlot(), func)); } /** @@ -1423,7 +1095,7 @@ public: template void Disconnect(SlotDelegate& delegate, Ret (X::*func)(Arg0 arg0, Arg1 arg1, Arg2 arg2)) { - mImpl.OnDisconnect(delegate.GetConnectionTracker(), MakeCallback(delegate.GetSlot(), func)); + Impl().OnDisconnect(delegate.GetConnectionTracker(), MakeCallback(delegate.GetSlot(), func)); } /** @@ -1436,7 +1108,7 @@ public: template void Connect(ConnectionTrackerInterface* connectionTracker, const X& func) { - mImpl.OnConnect(connectionTracker, new CallbackFunctorReturn3(func)); + Impl().OnConnect(connectionTracker, new CallbackFunctorReturn3(func)); } /** @@ -1448,7 +1120,7 @@ public: */ void Connect(ConnectionTrackerInterface* connectionTracker, FunctorDelegate* delegate) { - mImpl.OnConnect(connectionTracker, new CallbackFunctorDelegateReturn3(delegate)); + Impl().OnConnect(connectionTracker, new CallbackFunctorDelegateReturn3(delegate)); } /** @@ -1462,18 +1134,8 @@ public: */ Ret Emit(Arg0 arg0, Arg1 arg1, Arg2 arg2) { - return mImpl.EmitReturn(arg0, arg1, arg2); + return Impl().template EmitReturn(arg0, arg1, arg2); } - -private: - Signal(const Signal&) = delete; ///< Deleted copy constructor, signals don't support copying. @SINCE_1_0.0 - Signal(Signal&&) = delete; ///< Deleted move constructor, signals don't support moving. @SINCE_1_9.25 - Signal& operator=(const Signal&) = delete; ///< Deleted copy assignment operator @SINCE_1_0.0 - Signal& operator=(Signal&&) = delete; ///< Deleted move assignment operator @SINCE_1_9.25 - -private: - // Use composition instead of inheritance (virtual methods don't mix well with templates) - BaseSignal mImpl; ///< Implementation }; /** diff --git a/dali/public-api/signals/signal-slot-connections.cpp b/dali/public-api/signals/signal-slot-connections.cpp index b03e133..1aef5dc 100644 --- a/dali/public-api/signals/signal-slot-connections.cpp +++ b/dali/public-api/signals/signal-slot-connections.cpp @@ -20,51 +20,21 @@ // EXTERNAL INCLUDES #include +#include // INTERNAL INCLUDES #include namespace Dali { + SlotConnection::SlotConnection(SlotObserver* slotObserver, CallbackBase* callback) : mSlotObserver(slotObserver), mCallback(callback) { } -SlotConnection::~SlotConnection() -{ -} - -CallbackBase* SlotConnection::GetCallback() -{ - return mCallback; -} - -SlotObserver* SlotConnection::GetSlotObserver() -{ - return mSlotObserver; -} - -SignalConnection::SignalConnection(CallbackBase* callback) -: mSignalObserver(nullptr), - mCallback(callback) -{ -} - -SignalConnection::SignalConnection(SignalObserver* signalObserver, CallbackBase* callback) -: mSignalObserver(signalObserver), - mCallback(callback) -{ -} - -SignalConnection::~SignalConnection() -{ - // signal connections have ownership of the callback. - delete mCallback; -} - -void SignalConnection::Disconnect(SlotObserver* slotObserver) +void SignalConnection::Disconnect(SlotObserver* slotObserver) noexcept { if(mSignalObserver) { @@ -78,9 +48,10 @@ void SignalConnection::Disconnect(SlotObserver* slotObserver) mCallback = nullptr; } -CallbackBase* SignalConnection::GetCallback() -{ - return mCallback; -} +static_assert(std::is_nothrow_move_constructible_v); +static_assert(std::is_nothrow_move_assignable_v); + +static_assert(std::is_copy_constructible_v == false); +static_assert(std::is_copy_assignable_v == false); } // namespace Dali diff --git a/dali/public-api/signals/signal-slot-connections.h b/dali/public-api/signals/signal-slot-connections.h index 2a76199..b063616 100644 --- a/dali/public-api/signals/signal-slot-connections.h +++ b/dali/public-api/signals/signal-slot-connections.h @@ -19,6 +19,7 @@ */ // INTERNAL INCLUDES +#include #include namespace Dali @@ -28,7 +29,6 @@ namespace Dali * @{ */ -class CallbackBase; /** * @brief Slot connection is the connection information held by a connection tracker. @@ -56,18 +56,15 @@ public: SlotConnection(SlotObserver* slotObserver, CallbackBase* callback); /** - * @brief Non-virtual destructor, not intended as a base class. - * @SINCE_1_0.0 - */ - ~SlotConnection(); - - /** * @brief Retrieves the callback. * * @SINCE_1_0.0 * @return A pointer to the callback */ - CallbackBase* GetCallback(); + CallbackBase* GetCallback() const + { + return mCallback; + } /** * @brief Retrieves the slot observer. @@ -75,17 +72,14 @@ public: * @SINCE_1_0.0 * @return A pointer to the slot observer */ - SlotObserver* GetSlotObserver(); - -private: - SlotConnection(const SlotConnection&) = delete; ///< Deleted copy constructor. @SINCE_1_0.0 - SlotConnection(SlotConnection&&) = delete; ///< Deleted move constructor. @SINCE_1_9.25 - SlotConnection& operator=(const SlotConnection&) = delete; ///< Deleted copy assignment operator. @SINCE_1_0.0 - SlotConnection& operator=(SlotConnection&&) = delete; ///< Deleted move assignment operator. @SINCE_1_9.25 + SlotObserver* GetSlotObserver() const + { + return mSlotObserver; + } private: - SlotObserver* mSlotObserver; ///< a pointer to the slot observer (not owned) - CallbackBase* mCallback; ///< The callback. This is not owned, the corresponding SignalConnection has ownership. + SlotObserver* mSlotObserver{nullptr}; ///< a pointer to the slot observer (not owned) + CallbackBase* mCallback{nullptr}; ///< The callback. This is not owned, the corresponding SignalConnection has ownership. }; /** @@ -111,7 +105,10 @@ public: * @SINCE_1_0.0 * @param[in] callback The callback which should be a C function */ - SignalConnection(CallbackBase* callback); + SignalConnection(CallbackBase* callback) noexcept + : mCallback(callback) + { + } /** * @brief Constructor. @@ -120,13 +117,21 @@ public: * @param[in] signalObserver The signal observer * @param[in] callback Ownership of this callback object is taken */ - SignalConnection(SignalObserver* signalObserver, CallbackBase* callback); + SignalConnection(SignalObserver* signalObserver, CallbackBase* callback) noexcept + : mSignalObserver(signalObserver), + mCallback(callback) + { + } /** * @brief Non-virtual destructor, not intended as a base class. * @SINCE_1_0.0 */ - ~SignalConnection(); + ~SignalConnection() noexcept + { + // signal connections have ownership of the callback. + delete mCallback; + } /** * @brief Disconnects the signal from the slot. @@ -134,7 +139,7 @@ public: * @SINCE_1_0.0 * @param[in] slotObserver The signal disconnecting from the slot */ - void Disconnect(SlotObserver* slotObserver); + void Disconnect(SlotObserver* slotObserver) noexcept; /** * @brief Retrieves the callback. @@ -142,17 +147,60 @@ public: * @SINCE_1_0.0 * @return A pointer to the callback */ - CallbackBase* GetCallback(); + CallbackBase* GetCallback() const noexcept + { + return mCallback; + } -private: SignalConnection(const SignalConnection&) = delete; ///< Deleted copy constructor. @SINCE_1_0.0 - SignalConnection(SignalConnection&&) = delete; ///< Deleted move constructor. @SINCE_1_9.25 SignalConnection& operator=(const SignalConnection&) = delete; ///< Deleted copy assignment operator. @SINCE_1_0.0 - SignalConnection& operator=(SignalConnection&&) = delete; ///< Deleted move assignment operator. @SINCE_1_9.25 + + /** + * @brief Move constructor. + * + * A move constructor enables the resources owned by an rvalue object to be moved into an lvalue without copying. + * @SINCE_1_9.38 + * @param[in] connection The property value to move from + */ + SignalConnection(SignalConnection&& connection) noexcept + : mSignalObserver(connection.mSignalObserver), + mCallback(connection.mCallback) + { + connection.mSignalObserver = nullptr; + connection.mCallback = nullptr; + } + + /** + * @brief Move assignment operator. + * + * @SINCE_1_9.38 + * @param[in] connection The connection to move from + * @return a reference to this + */ + SignalConnection& operator=(SignalConnection&& connection) noexcept + { + if(this != &connection) + { + // release the callback + delete mCallback; + + mSignalObserver = connection.mSignalObserver; + mCallback = connection.mCallback; + + connection.mSignalObserver = nullptr; + connection.mCallback = nullptr; + } + return *this; + } + + explicit operator bool() const noexcept + { + return mCallback ? true : false; + } private: - SignalObserver* mSignalObserver; ///< a pointer to the signal observer (not owned) - CallbackBase* mCallback; ///< The callback, has ownership. + SignalObserver* mSignalObserver{nullptr}; ///< a pointer to the signal observer (not owned) + CallbackBase* mCallback{nullptr}; ///< The callback, has ownership. }; /** diff --git a/packaging/dali.spec b/packaging/dali.spec index 25b5042..0e58a69 100644 --- a/packaging/dali.spec +++ b/packaging/dali.spec @@ -1,6 +1,6 @@ Name: dali2 Summary: DALi 3D Engine -Version: 1.9.32 +Version: 1.9.34 Release: 1 Group: System/Libraries License: Apache-2.0 and BSD-3-Clause and MIT