mirror of
https://github.com/ETLCPP/etl.git
synced 2026-10-28 18:07:10 +08:00
Added delegate_observable
This commit is contained in:
parent
51a4d0e8da
commit
7504646301
208
include/etl/delegate_observable.h
Normal file
208
include/etl/delegate_observable.h
Normal file
@ -0,0 +1,208 @@
|
||||
///\file
|
||||
|
||||
/******************************************************************************
|
||||
The MIT License(MIT)
|
||||
|
||||
Embedded Template Library.
|
||||
https://github.com/ETLCPP/etl
|
||||
https://www.etlcpp.com
|
||||
|
||||
Copyright(c) 2023 John Wellbelove
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files(the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions :
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef ETL_DELEGATE_OBSERVABLE_INCLUDED
|
||||
#define ETL_DELEGATE_OBSERVABLE_INCLUDED
|
||||
|
||||
#include "platform.h"
|
||||
#include "delegate.h"
|
||||
#include "array.h"
|
||||
|
||||
namespace etl
|
||||
{
|
||||
//*********************************************************************
|
||||
/// An obserable type that uses delegates to notify observers.
|
||||
///\tparam TNotification The notification type sent to the observers.
|
||||
///\tparam Max_Observers The maximum number of observers that can be accommodated.
|
||||
///\ingroup observer
|
||||
//*********************************************************************
|
||||
template <typename TNotification, size_t Max_Observers>
|
||||
class delegate_observable
|
||||
{
|
||||
public:
|
||||
|
||||
/// The type of the observers.
|
||||
typedef etl::delegate<void(TNotification)> delegate_type;
|
||||
|
||||
private:
|
||||
|
||||
typedef etl::array<delegate_type, Max_Observers> DelegateList;
|
||||
|
||||
public:
|
||||
|
||||
/// The type for sizes.
|
||||
typedef size_t size_type;
|
||||
|
||||
/// The type of the notification.
|
||||
typedef TNotification notification_type;
|
||||
|
||||
//*****************************************************************
|
||||
/// Default constructor.
|
||||
//*****************************************************************
|
||||
ETL_CONSTEXPR14 delegate_observable()
|
||||
: delegate_list()
|
||||
, delegate_count(0)
|
||||
{
|
||||
}
|
||||
|
||||
#if ETL_USING_CPP11
|
||||
//*****************************************************************
|
||||
/// Construct from a list of observers.
|
||||
//*****************************************************************
|
||||
template <typename... TDelegate>
|
||||
ETL_CONSTEXPR14 delegate_observable(TDelegate&&... delegates)
|
||||
: delegate_list{ etl::forward<TDelegate>(delegates)... }
|
||||
, delegate_count(sizeof...(delegates))
|
||||
{
|
||||
ETL_STATIC_ASSERT(Max_Observers >= sizeof...(delegates), "Number of delegates exceeds maximum observers");
|
||||
ETL_STATIC_ASSERT((etl::are_all_same<delegate_type, etl::decay_t<TDelegate>...>::value), "All delegates must be delegate_type");
|
||||
}
|
||||
|
||||
//*****************************************************************
|
||||
/// Construct from notification type and a list of observers.
|
||||
/// Variant for template deduction guide.
|
||||
/// The notification value is ignored. It is just here to allow deduction
|
||||
/// of the notification type for the template deduction guide.
|
||||
//*****************************************************************
|
||||
template <typename... TDelegate>
|
||||
ETL_CONSTEXPR14 delegate_observable(notification_type, TDelegate&&... delegates)
|
||||
: delegate_observable(etl::forward<TDelegate>(delegates)...)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
//*****************************************************************
|
||||
/// Add an observer to the list.
|
||||
///\param observer A reference to the observer.
|
||||
///\return <b>true</b> if the observer was added or already exists, <b>false</b> if not.
|
||||
//*****************************************************************
|
||||
ETL_CONSTEXPR14 bool add_observer(delegate_type observer)
|
||||
{
|
||||
for (size_t i = 0; i < Max_Observers; ++i)
|
||||
{
|
||||
if (delegate_list[i] == observer)
|
||||
{
|
||||
// Already there, so just return.
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// If we get here, then we need to add it.
|
||||
for (size_t i = 0; i < Max_Observers; ++i)
|
||||
{
|
||||
if (!delegate_list[i].is_valid())
|
||||
{
|
||||
// Found an empty slot, so add it.
|
||||
delegate_list[i] = observer;
|
||||
++delegate_count;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//*****************************************************************
|
||||
/// Remove a particular observer from the list.
|
||||
///\param observer A reference to the observer.
|
||||
///\return <b>true</b> if the observer was removed, <b>false</b> if not.
|
||||
//*****************************************************************
|
||||
ETL_CONSTEXPR14 bool remove_observer(const delegate_type& observer)
|
||||
{
|
||||
for (size_t i = 0; i < Max_Observers; ++i)
|
||||
{
|
||||
if (delegate_list[i] == observer)
|
||||
{
|
||||
// Clear it.
|
||||
delegate_list[i].clear();
|
||||
--delegate_count;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//*****************************************************************
|
||||
/// Clear all observers.
|
||||
//*****************************************************************
|
||||
ETL_CONSTEXPR14 void clear_observers()
|
||||
{
|
||||
for (size_t i = 0; i < Max_Observers; ++i)
|
||||
{
|
||||
delegate_list[i].clear();
|
||||
}
|
||||
|
||||
delegate_count = 0;
|
||||
}
|
||||
|
||||
//*****************************************************************
|
||||
/// Returns the number of observers.
|
||||
//*****************************************************************
|
||||
ETL_CONSTEXPR14 size_type number_of_observers() const
|
||||
{
|
||||
return delegate_count;
|
||||
}
|
||||
|
||||
//*****************************************************************
|
||||
/// Notify all of the observers, sending them the notification.
|
||||
///\tparam TNotification The notification type.
|
||||
///\param n The notification.
|
||||
//*****************************************************************
|
||||
ETL_CONSTEXPR14 void notify_observers(notification_type n) const
|
||||
{
|
||||
if (delegate_count != 0)
|
||||
{
|
||||
for (size_t i = 0; i < Max_Observers; ++i)
|
||||
{
|
||||
delegate_list[i].call_if(n);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
/// The list of observers.
|
||||
DelegateList delegate_list;
|
||||
|
||||
/// The number of active delegates.
|
||||
size_t delegate_count;
|
||||
};
|
||||
|
||||
//*************************************************************************
|
||||
/// Template deduction guides.
|
||||
//*************************************************************************
|
||||
#if ETL_USING_CPP17
|
||||
template <typename TNotification, typename... TDelegates>
|
||||
delegate_observable(TNotification, TDelegates...) -> delegate_observable<TNotification, sizeof...(TDelegates)>;
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
@ -1,262 +0,0 @@
|
||||
///\file
|
||||
|
||||
/******************************************************************************
|
||||
The MIT License(MIT)
|
||||
|
||||
Embedded Template Library.
|
||||
https://github.com/ETLCPP/etl
|
||||
https://www.etlcpp.com
|
||||
|
||||
Copyright(c) 2023 John Wellbelove
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files(the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions :
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef ETL_DELEGATE_OBSERVER_INCLUDED
|
||||
#define ETL_DELEGATE_OBSERVER_INCLUDED
|
||||
|
||||
#include "algorithm.h"
|
||||
|
||||
#include "platform.h"
|
||||
#include "delegate.h"
|
||||
#include "vector.h"
|
||||
#include "exception.h"
|
||||
#include "error_handler.h"
|
||||
#include "utility.h"
|
||||
|
||||
namespace etl
|
||||
{
|
||||
//***************************************************************************
|
||||
///\ingroup observer
|
||||
/// The base class for delegate observer exceptions.
|
||||
//***************************************************************************
|
||||
class delegate_observer_exception : public exception
|
||||
{
|
||||
public:
|
||||
|
||||
delegate_observer_exception(string_type reason_, string_type file_name_, numeric_type line_number_)
|
||||
: exception(reason_, file_name_, line_number_)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
//***************************************************************************
|
||||
///\ingroup observer
|
||||
/// The exception thrown when the delegate observer list is full.
|
||||
//***************************************************************************
|
||||
class delegate_observer_list_full : public delegate_observer_exception
|
||||
{
|
||||
public:
|
||||
|
||||
delegate_observer_list_full(string_type file_name_, numeric_type line_number_)
|
||||
: delegate_observer_exception(ETL_ERROR_TEXT("delegate_observable:full", ETL_DELEGATE_OBSERVER_FILE_ID"A"), file_name_, line_number_)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
//*********************************************************************
|
||||
/// The object that is being observed.
|
||||
///\tparam MAX_OBSERVERS The maximum number of observers that can be accommodated.
|
||||
///\ingroup observer
|
||||
//*********************************************************************
|
||||
template <typename TNotification, const size_t MAX_OBSERVERS>
|
||||
class delegate_observable
|
||||
{
|
||||
public:
|
||||
|
||||
typedef etl::delegate<void(TNotification)> observer_type;
|
||||
|
||||
private:
|
||||
|
||||
//***********************************
|
||||
// Item stored in the observer list.
|
||||
//***********************************
|
||||
struct observer_item
|
||||
{
|
||||
observer_item(observer_type observer_)
|
||||
: observer(observer_)
|
||||
, enabled(true)
|
||||
{
|
||||
}
|
||||
|
||||
observer_type observer;
|
||||
bool enabled;
|
||||
};
|
||||
|
||||
//***********************************
|
||||
// How to compare an observer with an observer list item.
|
||||
//***********************************
|
||||
struct compare_observers
|
||||
{
|
||||
compare_observers(observer_type& observer_)
|
||||
: observer(&observer_)
|
||||
{
|
||||
}
|
||||
|
||||
bool operator ()(const observer_item& item) const
|
||||
{
|
||||
return observer == item.observer;
|
||||
}
|
||||
|
||||
observer_type observer;
|
||||
};
|
||||
|
||||
typedef etl::vector<observer_item, MAX_OBSERVERS> Observer_List;
|
||||
|
||||
public:
|
||||
|
||||
typedef size_t size_type;
|
||||
typedef TNotification notification_type;
|
||||
|
||||
//*****************************************************************
|
||||
/// Add an observer to the list.
|
||||
/// If asserts or exceptions are enabled then an etl::observable_observer_list_full
|
||||
/// is emitted if the observer list is already full.
|
||||
///\param observer A reference to the observer.
|
||||
//*****************************************************************
|
||||
void add_observer(observer_type& observer)
|
||||
{
|
||||
// See if we already have it in our list.
|
||||
typename Observer_List::iterator i_observer_item = find_observer(observer);
|
||||
|
||||
// Not there?
|
||||
if (i_observer_item == observer_list.end())
|
||||
{
|
||||
// Is there enough room?
|
||||
ETL_ASSERT_OR_RETURN(!observer_list.full(), ETL_ERROR(etl::observer_list_full));
|
||||
|
||||
// Add it.
|
||||
observer_list.push_back(observer_item(observer));
|
||||
}
|
||||
}
|
||||
|
||||
//*****************************************************************
|
||||
/// Remove a particular observer from the list.
|
||||
///\param observer A reference to the observer.
|
||||
///\return <b>true</b> if the observer was removed, <b>false</b> if not.
|
||||
//*****************************************************************
|
||||
bool remove_observer(observer_type& observer)
|
||||
{
|
||||
// See if we have it in our list.
|
||||
typename Observer_List::iterator i_observer_item = find_observer(observer);
|
||||
|
||||
// Found it?
|
||||
if (i_observer_item != observer_list.end())
|
||||
{
|
||||
// Erase it.
|
||||
observer_list.erase(i_observer_item);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
//*****************************************************************
|
||||
/// Enable an observer
|
||||
///\param observer A reference to the observer.
|
||||
///\param state <b>true</b> to enable, <b>false</b> to disable. Default is enable.
|
||||
//*****************************************************************
|
||||
void enable_observer(observer_type& observer, bool state = true)
|
||||
{
|
||||
// See if we have it in our list.
|
||||
typename Observer_List::iterator i_observer_item = find_observer(observer);
|
||||
|
||||
// Found it?
|
||||
if (i_observer_item != observer_list.end())
|
||||
{
|
||||
i_observer_item->enabled = state;
|
||||
}
|
||||
}
|
||||
|
||||
//*****************************************************************
|
||||
/// Disable an observer
|
||||
//*****************************************************************
|
||||
void disable_observer(observer_type& observer)
|
||||
{
|
||||
// See if we have it in our list.
|
||||
typename Observer_List::iterator i_observer_item = find_observer(observer);
|
||||
|
||||
// Found it?
|
||||
if (i_observer_item != observer_list.end())
|
||||
{
|
||||
i_observer_item->enabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
//*****************************************************************
|
||||
/// Clear all observers from the list.
|
||||
//*****************************************************************
|
||||
void clear_observers()
|
||||
{
|
||||
observer_list.clear();
|
||||
}
|
||||
|
||||
//*****************************************************************
|
||||
/// Returns the number of observers.
|
||||
//*****************************************************************
|
||||
size_type number_of_observers() const
|
||||
{
|
||||
return observer_list.size();
|
||||
}
|
||||
|
||||
//*****************************************************************
|
||||
/// Notify all of the observers, sending them the notification.
|
||||
///\tparam TNotification The notification type.
|
||||
///\param n The notification.
|
||||
//*****************************************************************
|
||||
void notify_observers(TNotification n)
|
||||
{
|
||||
typename Observer_List::iterator i_observer_item = observer_list.begin();
|
||||
|
||||
while (i_observer_item != observer_list.end())
|
||||
{
|
||||
if (i_observer_item->enabled)
|
||||
{
|
||||
i_observer_item->p_observer->notification(n);
|
||||
}
|
||||
|
||||
++i_observer_item;
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
~observable()
|
||||
{
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
//*****************************************************************
|
||||
/// Find an observer in the list.
|
||||
/// Returns the end of the list if not found.
|
||||
//*****************************************************************
|
||||
typename Observer_List::iterator find_observer(observer_type& observer_)
|
||||
{
|
||||
return etl::find_if(observer_list.begin(), observer_list.end(), compare_observers(observer_));
|
||||
}
|
||||
|
||||
/// The list of observers.
|
||||
Observer_List observer_list;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
@ -153,6 +153,7 @@ add_executable(etl_tests
|
||||
test_debounce.cpp
|
||||
test_delegate.cpp
|
||||
test_delegate_cpp03.cpp
|
||||
test_delegate_observable.cpp
|
||||
test_delegate_service.cpp
|
||||
test_delegate_service_compile_time.cpp
|
||||
test_delegate_service_cpp03.cpp
|
||||
|
||||
264
test/test_delegate_observable.cpp
Normal file
264
test/test_delegate_observable.cpp
Normal file
@ -0,0 +1,264 @@
|
||||
/******************************************************************************
|
||||
The MIT License(MIT)
|
||||
|
||||
Embedded Template Library.
|
||||
https://github.com/ETLCPP/etl
|
||||
https://www.etlcpp.com
|
||||
|
||||
Copyright(c) 2025 John Wellbelove
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files(the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions :
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
******************************************************************************/
|
||||
|
||||
#include "unit_test_framework.h"
|
||||
|
||||
#include "etl/delegate.h"
|
||||
#include "etl/delegate_observable.h"
|
||||
|
||||
#if !defined(ETL_DELEGATE_FORCE_CPP03_IMPLEMENTATION)
|
||||
|
||||
namespace
|
||||
{
|
||||
const size_t Max_Observers = 2UL;
|
||||
|
||||
using Notification = int;
|
||||
using Observable = etl::delegate_observable<Notification, Max_Observers>;
|
||||
using Delegate = Observable::delegate_type;
|
||||
|
||||
//*****************************************************************************
|
||||
bool global_called = false;
|
||||
bool member_called = false;
|
||||
int global_value = 0;
|
||||
int member_value = 0;
|
||||
|
||||
//*****************************************************************************
|
||||
// The global function taking no parameters.
|
||||
//*****************************************************************************
|
||||
static void global(int id)
|
||||
{
|
||||
global_called = true;
|
||||
global_value = id;
|
||||
}
|
||||
|
||||
//*****************************************************************************
|
||||
// The test class with member functions.
|
||||
//*****************************************************************************
|
||||
class Object
|
||||
{
|
||||
public:
|
||||
|
||||
ETL_CONSTEXPR14 Object()
|
||||
{
|
||||
}
|
||||
|
||||
void member(int id)
|
||||
{
|
||||
member_called = true;
|
||||
member_value = id;
|
||||
}
|
||||
};
|
||||
|
||||
Object object;
|
||||
|
||||
// Callback for 'member1'.
|
||||
ETL_CONSTEXPR14 Delegate member_callback = Delegate::create<Object, &Object::member, object>();
|
||||
|
||||
// Callback for 'global1'.
|
||||
ETL_CONSTEXPR14 Delegate global_callback = Delegate::create<global>();
|
||||
|
||||
//*****************************************************************************
|
||||
// Initialises the test results.
|
||||
//*****************************************************************************
|
||||
struct SetupFixture
|
||||
{
|
||||
SetupFixture()
|
||||
{
|
||||
global_called = false;
|
||||
member_called = false;
|
||||
global_value = 0;
|
||||
member_value = 0;
|
||||
}
|
||||
};
|
||||
|
||||
//*************************************************************************
|
||||
ETL_CONSTEXPR14 Observable CreateObservable()
|
||||
{
|
||||
Observable observable;
|
||||
|
||||
observable.add_observer(global_callback);
|
||||
observable.add_observer(member_callback);
|
||||
|
||||
observable.remove_observer(global_callback);
|
||||
|
||||
return observable;
|
||||
}
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
SUITE(test_delegate_service)
|
||||
{
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_constexpr_delegate_observable)
|
||||
{
|
||||
ETL_CONSTEXPR14 Observable observable(global_callback, member_callback);
|
||||
|
||||
CHECK_EQUAL(2, observable.number_of_observers());
|
||||
|
||||
observable.notify_observers(1);
|
||||
|
||||
CHECK_TRUE(global_called);
|
||||
CHECK_TRUE(member_called);
|
||||
CHECK_EQUAL(1, global_value);
|
||||
CHECK_EQUAL(1, member_value);
|
||||
|
||||
//*********************************
|
||||
global_called = false;
|
||||
member_called = false;
|
||||
|
||||
observable.notify_observers(2);
|
||||
|
||||
CHECK_TRUE(global_called);
|
||||
CHECK_TRUE(member_called);
|
||||
CHECK_EQUAL(2, global_value);
|
||||
CHECK_EQUAL(2, member_value);
|
||||
}
|
||||
|
||||
#if ETL_USING_CPP17
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_constexpr_delegate_observable_using_template_deduction_guide_cpp17)
|
||||
{
|
||||
ETL_CONSTEXPR14 etl::delegate_observable observable(int{}, global_callback, member_callback);
|
||||
|
||||
CHECK_EQUAL(2, observable.number_of_observers());
|
||||
|
||||
observable.notify_observers(1);
|
||||
|
||||
CHECK_TRUE(global_called);
|
||||
CHECK_TRUE(member_called);
|
||||
CHECK_EQUAL(1, global_value);
|
||||
CHECK_EQUAL(1, member_value);
|
||||
|
||||
//*********************************
|
||||
global_called = false;
|
||||
member_called = false;
|
||||
|
||||
observable.notify_observers(2);
|
||||
|
||||
CHECK_TRUE(global_called);
|
||||
CHECK_TRUE(member_called);
|
||||
CHECK_EQUAL(2, global_value);
|
||||
CHECK_EQUAL(2, member_value);
|
||||
}
|
||||
#endif
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_constexpr_delegate_observable_from_function)
|
||||
{
|
||||
ETL_CONSTEXPR14 Observable observable = CreateObservable();
|
||||
|
||||
CHECK_EQUAL(1, observable.number_of_observers());
|
||||
|
||||
observable.notify_observers(1);
|
||||
|
||||
CHECK_FALSE(global_called);
|
||||
CHECK_TRUE(member_called);
|
||||
CHECK_EQUAL(0, global_value);
|
||||
CHECK_EQUAL(1, member_value);
|
||||
|
||||
//*********************************
|
||||
global_called = false;
|
||||
member_called = false;
|
||||
|
||||
observable.notify_observers(2);
|
||||
|
||||
CHECK_FALSE(global_called);
|
||||
CHECK_TRUE(member_called);
|
||||
CHECK_EQUAL(0, global_value);
|
||||
CHECK_EQUAL(2, member_value);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_delegate_observable_add_and_remove)
|
||||
{
|
||||
Observable observable;
|
||||
CHECK_EQUAL(0, observable.number_of_observers());
|
||||
|
||||
observable.notify_observers(1);
|
||||
CHECK_FALSE(global_called);
|
||||
CHECK_FALSE(member_called);
|
||||
CHECK_EQUAL(0, global_value);
|
||||
CHECK_EQUAL(0, member_value);
|
||||
|
||||
//*********************************
|
||||
global_called = false;
|
||||
member_called = false;
|
||||
|
||||
observable.add_observer(global_callback);
|
||||
CHECK_EQUAL(1, observable.number_of_observers());
|
||||
|
||||
observable.notify_observers(2);
|
||||
CHECK_TRUE(global_called);
|
||||
CHECK_FALSE(member_called);
|
||||
CHECK_EQUAL(2, global_value);
|
||||
CHECK_EQUAL(0, member_value);
|
||||
|
||||
//*********************************
|
||||
global_called = false;
|
||||
member_called = false;
|
||||
|
||||
observable.add_observer(member_callback);
|
||||
CHECK_EQUAL(2, observable.number_of_observers());
|
||||
|
||||
observable.notify_observers(3);
|
||||
CHECK_TRUE(global_called);
|
||||
CHECK_TRUE(member_called);
|
||||
CHECK_EQUAL(3, global_value);
|
||||
CHECK_EQUAL(3, member_value);
|
||||
|
||||
//*********************************
|
||||
global_called = false;
|
||||
member_called = false;
|
||||
|
||||
observable.remove_observer(global_callback);
|
||||
CHECK_EQUAL(1, observable.number_of_observers());
|
||||
|
||||
observable.notify_observers(4);
|
||||
CHECK_FALSE(global_called);
|
||||
CHECK_TRUE(member_called);
|
||||
CHECK_EQUAL(3, global_value);
|
||||
CHECK_EQUAL(4, member_value);
|
||||
|
||||
//*********************************
|
||||
global_called = false;
|
||||
member_called = false;
|
||||
|
||||
observable.clear_observers();
|
||||
CHECK_EQUAL(0, observable.number_of_observers());
|
||||
|
||||
observable.notify_observers(5);
|
||||
CHECK_FALSE(global_called);
|
||||
CHECK_FALSE(member_called);
|
||||
CHECK_EQUAL(3, global_value);
|
||||
CHECK_EQUAL(4, member_value);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
@ -3353,6 +3353,7 @@
|
||||
<ClInclude Include="..\..\include\etl\crc8_opensafety.h" />
|
||||
<ClInclude Include="..\..\include\etl\crc8_rohc.h" />
|
||||
<ClInclude Include="..\..\include\etl\crc8_wcdma.h" />
|
||||
<ClInclude Include="..\..\include\etl\delegate_observable.h" />
|
||||
<ClInclude Include="..\..\include\etl\expected.h" />
|
||||
<ClInclude Include="..\..\include\etl\function_traits.h" />
|
||||
<ClInclude Include="..\..\include\etl\gcd.h" />
|
||||
@ -9387,6 +9388,7 @@
|
||||
<ClCompile Include="..\test_crc8_opensafety.cpp" />
|
||||
<ClCompile Include="..\test_crc8_rohc.cpp" />
|
||||
<ClCompile Include="..\test_crc8_wcdma.cpp" />
|
||||
<ClCompile Include="..\test_delegate_observable.cpp" />
|
||||
<ClCompile Include="..\test_expected.cpp" />
|
||||
<ClCompile Include="..\test_function_traits.cpp" />
|
||||
<ClCompile Include="..\test_hfsm_recurse_to_inner_state_on_start.cpp" />
|
||||
|
||||
@ -1530,6 +1530,9 @@
|
||||
<ClInclude Include="..\..\include\etl\callback_timer_deferred_locked.h">
|
||||
<Filter>UnitTest++\Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\include\etl\delegate_observable.h">
|
||||
<Filter>ETL\Utilities</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\test_string_char.cpp">
|
||||
@ -3689,6 +3692,9 @@
|
||||
<ClCompile Include="..\test_crc64_iso.cpp">
|
||||
<Filter>Tests\CRC</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\test_delegate_observable.cpp">
|
||||
<Filter>Tests\Callbacks & Delegates</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="..\..\library.properties">
|
||||
@ -3847,6 +3853,12 @@
|
||||
<None Include="..\..\CONTRIBUTING.md">
|
||||
<Filter>Resource Files</Filter>
|
||||
</None>
|
||||
<None Include="..\..\scripts\convert_headers_to_use_guards.bat">
|
||||
<Filter>Tests</Filter>
|
||||
</None>
|
||||
<None Include="..\..\scripts\convert_headers_to_use_once.bat">
|
||||
<Filter>Tests</Filter>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Text Include="..\..\support\Release notes.txt">
|
||||
@ -3885,6 +3897,7 @@
|
||||
<Text Include="..\syntax_check\CMakeLists.txt">
|
||||
<Filter>Tests\Syntax Checks</Filter>
|
||||
</Text>
|
||||
<Text Include="..\..\Converting header guards.txt" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Image Include="..\..\etl.ico">
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user