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

github.com/moses-smt/mosesdecoder.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/moses
diff options
context:
space:
mode:
authorUlrich Germann <Ulrich.Germann@gmail.com>2015-03-28 17:43:21 +0300
committerUlrich Germann <Ulrich.Germann@gmail.com>2015-03-28 17:44:40 +0300
commita706569844ea38154d02c2607908842244f7a6b2 (patch)
tree1b1375b3ddd79d3ae088b42f84bf9393348821fe /moses
parent1b23edf62f4f390fc0d7c155d2b27158362f8f3d (diff)
Thread-safe classes for storing context-specific information.
Diffstat (limited to 'moses')
-rw-r--r--moses/ContextScope.h57
-rw-r--r--moses/thread_safe_container.h122
2 files changed, 179 insertions, 0 deletions
diff --git a/moses/ContextScope.h b/moses/ContextScope.h
new file mode 100644
index 000000000..78940e575
--- /dev/null
+++ b/moses/ContextScope.h
@@ -0,0 +1,57 @@
+// -*- c++ -*-
+// A class to store "local" information (such as task-specific caches).
+// The idea is for each translation task to have a scope, which stores
+// shared pointers to task-specific objects such as caches and priors.
+// Since these objects are referenced via shared pointers, sopes can
+// share information.
+
+#ifdef WITH_THREADS
+#include <boost/thread/shared_mutex.hpp>
+#include <boost/thread/locks.hpp>
+#include <boost/foreach.hpp>
+#endif
+
+#include "thread_safe_container.h"
+
+namespace Moses
+{
+ class ContextScope
+ {
+ protected:
+ typedef ThreadSafeContainer<void*,boost::shared_ptr<void> >scratchpad_t;
+ scratchpad_t m_scratchpad;
+ boost::shared_mutex m_lock;
+ public:
+
+ template<typename T>
+ boost::shared_ptr<T>
+ get(T* key, bool CreateNewIfNecessary) const
+ {
+ using boost::shared_mutex;
+ boost::shared_pointer<void>* x;
+ {
+ boost::shared_lock<shared_mutex> lock(m_lock);
+ x = m_scratchpad.get(key);
+ if (x) return static_cast< boost::shared_pointer< T > >(*x);
+ }
+ boost::unique_lock<shared_mutex> lock(m_lock);
+ boost::shared_ptr<T> ret;
+ if (!CrateNewIfNecessary) return ret;
+ ret.reset(new T);
+ x = m_scratchpad.get(key, ret);
+ return static_cast< boost::shared_pointer< T > >(*x);
+ }
+
+ ContextScope(ContextScope const& other)
+ {
+ boost::unique_lock<boost::shared_mutex> lock2(this->m_lock);
+ scratchpad_t::locking iterator m;
+ for (m = other.begin(); m != other.end(); ++m)
+ {
+ m_scratchpad.set(m->first, m->second);
+ }
+ }
+
+ };
+
+};
diff --git a/moses/thread_safe_container.h b/moses/thread_safe_container.h
new file mode 100644
index 000000000..aca965373
--- /dev/null
+++ b/moses/thread_safe_container.h
@@ -0,0 +1,122 @@
+// -*- c++ -*-
+#pragma once
+#include "moses/Util.h"
+#ifdef WITH_THREADS
+
+#include <time.h>
+#include <boost/thread.hpp>
+#include <boost/scoped_ptr.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/weak_ptr.hpp>
+
+#include "moses/TargetPhrase.h"
+#include <boost/thread/shared_mutex.hpp>
+#include <boost/thread/locks.hpp>
+#endif
+
+namespace Moses
+{
+
+ // todo: replace this with thread lock-free containers, if a stable library can
+ // be found somewhere
+
+ template<typename KEY, typename VAL, typename CONTAINER=map>
+ ThreadSafeContainer
+ {
+ protected:
+ mutable boost::shared_mutex m_lock;
+ CONTAINER<KEY,VAL> m_container;
+ typedef CONTAINER<KEY,VAL>::iterator iter_t;
+ typedef CONTAINER<KEY,VAL>::const_iterator const_iter_t;
+ typedef CONTAINER<KEY,VAL>::value_type entry_t;
+ public:
+
+ class locking_iterator
+ {
+ boost::unique_lock<boost::shared_mutes> m_lock;
+ CONTAINER<KEY,VAL> const* m_container;
+ const_iter_t m_iter;
+
+ locking_iterator(locking_iterator const& other); // no copies!
+ public:
+ locking_iterator() : m_container(NULL) { }
+
+ locking_iterator(boost::shared_mutex& lock,
+ CONTAINER<KEY,VAL> const* container,
+ const_iter_ const& iter)
+ : m_lock(lock), m_container(container), m_iter(iter)
+ { }
+
+ entry_t const& operator->()
+ {
+ UTIL_THROW_IF2(m_container == NULL, "This locking iterator is invalid "
+ << "or has not been assigned.");
+ return m_iter.operator->();
+ }
+
+ // locking operators transfer the lock upon assignment and become invalid
+ locking_iterator const&
+ operator=(locking_iterator& other)
+ {
+ m_lock.swap(other.m_lock);
+ m_iter = other.m_iter;
+ other.m_iter = other.m_container.end();
+ }
+
+ bool
+ operator==(const_itert_t const& other)
+ {
+ return m_iter == other;
+ }
+
+ locking_iterator const&
+ operator++() { ++m_iter; return *this; }
+
+ // DO NOT DEFINE THE POST-INCREMENT OPERATOR!
+ // locking_operators are non-copyable,
+ // so we can't simply make a copy before incrementing and return
+ // the copy after incrementing
+ locking_iterator const&
+ operator++(int);
+ };
+
+ CONTAINER<KEY,VAL>::const_iterator const& end() const
+ { return m_container.end(); }
+
+ locking_iterator begin() const
+ {
+ return locking_iterator(m_lock, this, m_container.begin());
+ }
+
+ VAL const& set(KEY const& key, VAL const& val)
+ {
+ boost::unique_lock< boost::shared_mutex > lock(m_lock);
+ CONTAINER<KEY,VAL>::value_type entry(key,val);
+ iter foo = m_container.insert(entry).first;
+ return (foo->second = val);
+ }
+
+ VAL const* get(KEY const& key, VAL const& default_val)
+ {
+ boost::shared_lock< boost::shared_mutex > lock(m_lock);
+ CONTAINER<KEY,VAL>::value_type entry(key,val);
+ pair<iter,bool> foo = m_container.insert(entry);
+ return &(foo->second);
+ }
+
+ VAL const* get(KEY const& key) const
+ {
+ boost::shared_lock< boost::shared_mutex > lock(m_lock);
+ CONTAINER<KEY,VAL>::const_iterator m = m_container.find(key);
+ if (m == m_container.end()) return NULL;
+ return &m->second;
+ }
+
+ size_t erase(Key const& key)
+ {
+ boost::unique_lock< boost::shared_mutex > lock(m_lock);
+ return m_container.erase(key);
+ }
+ };
+}
+#endif