00001
00002 #pragma once
00003 #include "moses/Util.h"
00004 #ifdef WITH_THREADS
00005
00006 #include <time.h>
00007 #include <boost/thread.hpp>
00008 #include <boost/scoped_ptr.hpp>
00009 #include <boost/shared_ptr.hpp>
00010 #include <boost/weak_ptr.hpp>
00011
00012 #include "moses/TargetPhrase.h"
00013 #include <boost/thread/shared_mutex.hpp>
00014 #include <boost/thread/locks.hpp>
00015
00016 #include <map>
00017
00018 namespace Moses
00019 {
00020
00021
00022
00023
00024 template<typename KEY, typename VAL, class CONTAINER = std::map<KEY,VAL> >
00025 class
00026 ThreadSafeContainer
00027 {
00028 protected:
00029 mutable boost::shared_mutex m_lock;
00030 CONTAINER m_container;
00031 typedef typename CONTAINER::iterator iter_t;
00032 typedef typename CONTAINER::const_iterator const_iter_t;
00033 typedef typename CONTAINER::value_type entry_t;
00034 public:
00035
00036 class locking_iterator
00037 {
00038 boost::unique_lock<boost::shared_mutex> m_lock;
00039 CONTAINER const* m_container;
00040 const_iter_t m_iter;
00041
00042 locking_iterator(locking_iterator const& other);
00043 public:
00044 locking_iterator() : m_container(NULL) { }
00045
00046 locking_iterator(boost::shared_mutex& lock,
00047 CONTAINER const* container,
00048 const_iter_t const& iter)
00049 : m_lock(lock), m_container(container), m_iter(iter)
00050 { }
00051
00052 entry_t const& operator->()
00053 {
00054 UTIL_THROW_IF2(m_container == NULL, "This locking iterator is invalid "
00055 << "or has not been assigned.");
00056 return m_iter.operator->();
00057 }
00058
00059
00060
00061 locking_iterator const&
00062 operator=(locking_iterator& other)
00063 {
00064 m_lock.swap(other.m_lock);
00065 m_iter = other.m_iter;
00066 other.m_iter = other.m_container.end();
00067 }
00068
00069 bool
00070 operator==(const_iter_t const& other)
00071 {
00072 return m_iter == other;
00073 }
00074
00075 locking_iterator const&
00076 operator++()
00077 {
00078 ++m_iter;
00079 return *this;
00080 }
00081
00082
00083
00084
00085
00086 locking_iterator const&
00087 operator++(int);
00088 };
00089
00090 const_iter_t const&
00091 end() const
00092 {
00093 return m_container.end();
00094 }
00095
00096 locking_iterator
00097 begin() const
00098 {
00099 return locking_iterator(m_lock, this, m_container.begin());
00100 }
00101
00102 VAL const&
00103 set(KEY const& key, VAL const& val)
00104 {
00105 boost::unique_lock< boost::shared_mutex > lock(m_lock);
00106 entry_t entry(key,val);
00107 iter_t foo = m_container.insert(entry).first;
00108 foo->second = val;
00109 return foo->second;
00110 }
00111
00112 VAL const*
00113 get(KEY const& key, VAL const& default_val)
00114 {
00115 boost::unique_lock< boost::shared_mutex > lock(m_lock);
00116 entry_t entry(key, default_val);
00117 iter_t foo = m_container.insert(entry).first;
00118 return &(foo->second);
00119 }
00120
00121 VAL const*
00122 get(KEY const& key) const
00123 {
00124 boost::shared_lock< boost::shared_mutex > lock(m_lock);
00125 const_iter_t m = m_container.find(key);
00126 if (m == m_container.end()) return NULL;
00127 return &m->second;
00128 }
00129
00130 size_t
00131 erase(KEY const& key)
00132 {
00133 boost::unique_lock< boost::shared_mutex > lock(m_lock);
00134 return m_container.erase(key);
00135 }
00136 };
00137 }
00138 #endif