Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mapsme/omim.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/base
diff options
context:
space:
mode:
authorYuri Gorshenin <y@maps.me>2015-03-20 18:59:02 +0300
committerAlex Zolotarev <alex@maps.me>2015-09-23 02:41:33 +0300
commit725aab207201f4b55bb0b8529b8731d0adfcd5cc (patch)
tree92273e0d2160883871e3d8dff2158153dd8dfb6c /base
parentefaeab8e7b3b8cc863f601f29f98d4ff860955ce (diff)
Added Observers interface to Index.
Diffstat (limited to 'base')
-rw-r--r--base/base.pro1
-rw-r--r--base/base_tests/base_tests.pro1
-rw-r--r--base/base_tests/observer_list_test.cpp68
-rw-r--r--base/observer_list.hpp47
4 files changed, 117 insertions, 0 deletions
diff --git a/base/base.pro b/base/base.pro
index c8c2287523..317ea6467d 100644
--- a/base/base.pro
+++ b/base/base.pro
@@ -59,6 +59,7 @@ HEADERS += \
mru_cache.hpp \
mutex.hpp \
object_tracker.hpp \
+ observer_list.hpp \
pseudo_random.hpp \
regexp.hpp \
resource_pool.hpp \
diff --git a/base/base_tests/base_tests.pro b/base/base_tests/base_tests.pro
index b1e8ae8a89..6b2bcb923a 100644
--- a/base/base_tests/base_tests.pro
+++ b/base/base_tests/base_tests.pro
@@ -28,6 +28,7 @@ SOURCES += \
matrix_test.cpp \
mem_trie_test.cpp \
mru_cache_test.cpp \
+ observer_list_test.cpp \
regexp_test.cpp \
rolling_hash_test.cpp \
scheduled_task_test.cpp \
diff --git a/base/base_tests/observer_list_test.cpp b/base/base_tests/observer_list_test.cpp
new file mode 100644
index 0000000000..6e3a4ba48f
--- /dev/null
+++ b/base/base_tests/observer_list_test.cpp
@@ -0,0 +1,68 @@
+#include "../../testing/testing.hpp"
+
+#include "../observer_list.hpp"
+
+#include "../../std/string.hpp"
+
+namespace
+{
+struct Observer
+{
+ Observer() : status(0) {}
+
+ void OnOperationCompleted(string const & message, int status)
+ {
+ this->message = message;
+ this->status = status;
+ }
+
+ string message;
+ int status;
+};
+} // namespace
+
+UNIT_TEST(ObserverList_Basic)
+{
+ Observer observer0;
+ Observer observer1;
+ Observer observer2;
+
+ my::ObserverList<Observer> observers;
+
+ // Register all observers in a list. Also check that it's not
+ // possible to add the same observer twice.
+ TEST(observers.Add(observer0), ());
+ TEST(!observers.Add(observer0), ());
+
+ TEST(observers.Add(observer1), ());
+ TEST(!observers.Add(observer1), ());
+
+ TEST(observers.Add(observer2), ());
+ TEST(!observers.Add(observer2), ());
+
+ TEST(!observers.Add(observer1), ());
+ TEST(!observers.Add(observer2), ());
+
+ string const message = "HTTP OK";
+ observers.ForEach(&Observer::OnOperationCompleted, message, 204);
+
+ // Check observers internal state.
+ TEST_EQUAL(message, observer0.message, ());
+ TEST_EQUAL(204, observer0.status, ());
+
+ TEST_EQUAL(message, observer1.message, ());
+ TEST_EQUAL(204, observer1.status, ());
+
+ TEST_EQUAL(message, observer2.message, ());
+ TEST_EQUAL(204, observer2.status, ());
+
+ // Remove all observers from a list.
+ TEST(observers.Remove(observer0), ());
+ TEST(!observers.Remove(observer0), ());
+
+ TEST(observers.Remove(observer1), ());
+ TEST(!observers.Remove(observer1), ());
+
+ TEST(observers.Remove(observer2), ());
+ TEST(!observers.Remove(observer2), ());
+}
diff --git a/base/observer_list.hpp b/base/observer_list.hpp
new file mode 100644
index 0000000000..915c78f1d8
--- /dev/null
+++ b/base/observer_list.hpp
@@ -0,0 +1,47 @@
+#pragma once
+
+#include "../std/algorithm.hpp"
+#include "../std/mutex.hpp"
+#include "../std/vector.hpp"
+
+namespace my
+{
+/// This class represents a thread-safe observers list. It allows to
+/// add/remove observers as well as trigger them all.
+template <typename TObserver>
+class ObserverList
+{
+public:
+ bool Add(TObserver & observer)
+ {
+ lock_guard<mutex> lock(m_observersLock);
+ auto it = find(m_observers.begin(), m_observers.end(), &observer);
+ if (it != m_observers.end())
+ return false;
+ m_observers.push_back(&observer);
+ return true;
+ }
+
+ bool Remove(TObserver & observer)
+ {
+ lock_guard<mutex> lock(m_observersLock);
+ auto it = find(m_observers.begin(), m_observers.end(), &observer);
+ if (it == m_observers.end())
+ return false;
+ m_observers.erase(it);
+ return true;
+ }
+
+ template <typename F, typename... Args>
+ void ForEach(F fn, Args const &... args)
+ {
+ lock_guard<mutex> lock(m_observersLock);
+ for (TObserver * observer : m_observers)
+ (observer->*fn)(args...);
+ }
+
+private:
+ vector<TObserver *> m_observers;
+ mutex m_observersLock;
+};
+} // namespace my