and unsubscribing during notification.
Change-Id: I84aa88271fd898c91427baeb27dea1a3a17a248a
Signed-off-by: Eugene Kurzberg <i.kurtsberg@samsung.com>
/**
* @see system_settings_unset_changed_cb()
*/
- EXPORT_API void removeCallback(system_settings_key_e key, CallbackManager::Callback callback);
+ EXPORT_API void removeCallback(system_settings_key_e key, void *subscriber);
};
}
#ifndef UTILS_CALLBACK_MANAGER_H
#define UTILS_CALLBACK_MANAGER_H
+#include <functional>
#include <vector>
namespace Utils
/**
* @brief Callback prototype.
*/
- typedef void(*CallbackType)(void *, Args...);
+ typedef std::function<void(Args...)> CallbackType;
/**
- * @brief Callback and data pair.
+ * @brief Callback and subscriber pair.
*/
typedef std::pair<CallbackType, void *> Callback;
+ CallbackManager();
+
/**
- * @return Whether there is no added callbacks.
+ * @return Whether there are any added callbacks.
*/
- bool isEmpty() const;
+ explicit operator bool() const;
/**
* @brief Add new callback.
- * @param[in] callback Callback and data pair.
+ * @param[in] callback Callback and subscriber pair.
+ * @remark Subscriber can be any value by which the callback can be
+ * identified when removing it. However it is most convenient
+ * to identify it by the pointer to the object that receives it.
*/
- void addCallback(Callback callback);
+ void operator+=(Callback callback);
/**
* @brief Remove added callback.
- * @param[in] callback Callback and data pair.
+ * @param[in] subscriber Callback subscriber.
*/
- void removeCallback(Callback callback);
+ void operator-=(void *subscriber);
/**
* @brief Invoke all added callbacks.
*/
- void invokeCallbacks(Args... args);
+ void operator()(Args... args);
private:
typedef std::vector<Callback> Callbacks;
Callbacks m_Callbacks;
+ int m_Index;
};
}
#define UTILS_CALLBACK_MANAGER_IMPL_H
#include "Utils/CallbackManager.h"
-#include <algorithm>
+
+/* -1 is a possible index if the first callback is removed during notification */
+#define INVALID_CALLBACK_INDEX -2
namespace Utils
{
template <typename... Args>
- bool CallbackManager<Args...>::isEmpty() const
+ CallbackManager<Args...>::CallbackManager()
+ : m_Index(INVALID_CALLBACK_INDEX)
+ { }
+
+ template <typename... Args>
+ CallbackManager<Args...>::operator bool() const
{
- return m_Callbacks.empty();
+ return !m_Callbacks.empty();
}
template <typename... Args>
- void CallbackManager<Args...>::addCallback(Callback callback)
+ void CallbackManager<Args...>::operator+=(Callback callback)
{
- m_Callbacks.push_back(callback);
+ m_Callbacks.push_back(std::move(callback));
}
template <typename... Args>
- void CallbackManager<Args...>::removeCallback(Callback callback)
+ void CallbackManager<Args...>::operator-=(void *subscriber)
{
- auto it = std::find(m_Callbacks.begin(), m_Callbacks.end(), callback);
- if (it != m_Callbacks.end()) {
- m_Callbacks.erase(it);
+ for (int i = 0; i < (int) m_Callbacks.size(); ++i) {
+ if (m_Callbacks[i].second == subscriber) {
+ if (i <= m_Index) {
+ --m_Index;
+ }
+ m_Callbacks.erase(m_Callbacks.begin() + i);
+ break;
+ }
}
}
template <typename... Args>
- void CallbackManager<Args...>::invokeCallbacks(Args... args)
+ void CallbackManager<Args...>::operator()(Args... args)
{
- /* FIXME: This might fail if removeCallback() or addCallback() is called during invocation */
- for (auto &&callback : m_Callbacks) {
- callback.first(callback.second, args...);
+ if (m_Index > INVALID_CALLBACK_INDEX) {
+ return;
+ }
+
+ for (m_Index = 0; m_Index < (int) m_Callbacks.size(); ++m_Index) {
+ Callback &callback = m_Callbacks[m_Index];
+ if (callback.first) {
+ callback.first(args...);
+ }
}
+ m_Index = INVALID_CALLBACK_INDEX;
}
}
#include "System/Settings.h"
#include "Utils/Callback.h"
+#include <algorithm>
#include <list>
using namespace System::Settings;
: m_Key(key)
{
system_settings_set_changed_cb(m_Key,
- makeCallbackWithLastParam(&KeyManager::invokeCallbacks), this);
+ makeCallbackWithLastParam(&KeyManager::operator()), this);
}
~KeyManager()
manager = --keyManagers.end();
}
- manager->addCallback(callback);
+ (*manager) += (callback);
}
-void System::Settings::removeCallback(system_settings_key_e key, KeyManager::Callback callback)
+void System::Settings::removeCallback(system_settings_key_e key, void *subscriber)
{
auto manager = std::find(keyManagers.begin(), keyManagers.end(), key);
if (manager == keyManagers.end()) {
return;
}
- manager->removeCallback(callback);
- if (manager->isEmpty()) {
+ (*manager) -= subscriber;
+ if (!*manager) {
keyManagers.erase(manager);
}
}
setCancelCallback(std::bind(&DetailsView::onCanceled, this));
Settings::addCallback(SYSTEM_SETTINGS_KEY_LOCALE_TIMEFORMAT_24HOUR,
- { makeCallback(&DetailsView::onTimeFormatChanged), this });
+ { std::bind(&DetailsView::onTimeFormatChanged, this, _1), this });
Settings::addCallback(SYSTEM_SETTINGS_KEY_LOCALE_COUNTRY,
- { makeCallback(&DetailsView::onTimeFormatChanged), this });
+ { std::bind(&DetailsView::onTimeFormatChanged, this, _1), this });
}
DetailsView::~DetailsView()
{
- Settings::removeCallback(SYSTEM_SETTINGS_KEY_LOCALE_TIMEFORMAT_24HOUR,
- { makeCallback(&DetailsView::onTimeFormatChanged), this });
- Settings::removeCallback(SYSTEM_SETTINGS_KEY_LOCALE_COUNTRY,
- { makeCallback(&DetailsView::onTimeFormatChanged), this });
+ Settings::removeCallback(SYSTEM_SETTINGS_KEY_LOCALE_TIMEFORMAT_24HOUR, this);
+ Settings::removeCallback(SYSTEM_SETTINGS_KEY_LOCALE_COUNTRY, this);
}
Evas_Object *DetailsView::onCreate(Evas_Object *parent)
setStrings(strings);
Settings::addCallback(SYSTEM_SETTINGS_KEY_LOCALE_TIMEFORMAT_24HOUR,
- { makeCallback(&LogsView::onSettingsChanged), this });
+ { std::bind(&LogsView::onSettingsChanged, this, _1), this });
Settings::addCallback(SYSTEM_SETTINGS_KEY_LOCALE_COUNTRY,
- { makeCallback(&LogsView::onSettingsChanged), this });
+ { std::bind(&LogsView::onSettingsChanged, this, _1), this });
Settings::addCallback(SYSTEM_SETTINGS_KEY_TIME_CHANGED,
- { makeCallback(&LogsView::onSettingsChanged), this });
+ { std::bind(&LogsView::onSettingsChanged, this, _1), this });
}
LogsView::~LogsView()
{
- Settings::removeCallback(SYSTEM_SETTINGS_KEY_LOCALE_TIMEFORMAT_24HOUR,
- { makeCallback(&LogsView::onSettingsChanged), this });
- Settings::removeCallback(SYSTEM_SETTINGS_KEY_LOCALE_COUNTRY,
- { makeCallback(&LogsView::onSettingsChanged), this });
- Settings::removeCallback(SYSTEM_SETTINGS_KEY_TIME_CHANGED,
- { makeCallback(&LogsView::onSettingsChanged), this });
+ Settings::removeCallback(SYSTEM_SETTINGS_KEY_LOCALE_TIMEFORMAT_24HOUR, this);
+ Settings::removeCallback(SYSTEM_SETTINGS_KEY_LOCALE_COUNTRY, this);
+ Settings::removeCallback(SYSTEM_SETTINGS_KEY_TIME_CHANGED, this);
}
LogsView::FilterType LogsView::getFilterType() const