// -*- 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. #pragma once #ifdef WITH_THREADS #include #include #include #endif #include #include // #include "thread_safe_container.h" namespace Moses { class ContextScope { protected: typedef std::map > scratchpad_t; typedef scratchpad_t::iterator iter_t; typedef scratchpad_t::value_type entry_t; typedef scratchpad_t::const_iterator const_iter_t; scratchpad_t m_scratchpad; mutable boost::shared_mutex m_lock; public: // class write_access // { // boost::unique_lock m_lock; // public: // write_access(boost::shared_mutex& lock) // : m_lock(lock) // { } // write_access(write_access& other) // { // swap(m_lock, other.m_lock); // } // }; // write_access lock() const // { // return write_access(m_lock); // } template boost::shared_ptr const& set(void const* const key, boost::shared_ptr const& val) { boost::unique_lock lock(m_lock); return (m_scratchpad[key] = val); } template boost::shared_ptr const get(void const* key, bool CreateNewIfNecessary=false) { using boost::shared_mutex; using boost::upgrade_lock; // T const* key = reinterpret_cast(xkey); upgrade_lock lock(m_lock); iter_t m = m_scratchpad.find(key); boost::shared_ptr< T > ret; if (m != m_scratchpad.end()) { if (m->second == NULL && CreateNewIfNecessary) { boost::upgrade_to_unique_lock xlock(lock); m->second.reset(new T); } ret = boost::static_pointer_cast< T >(m->second); return ret; } if (!CreateNewIfNecessary) return ret; boost::upgrade_to_unique_lock xlock(lock); ret.reset(new T); m_scratchpad[key] = ret; return ret; } ContextScope() { } ContextScope(ContextScope const& other) { boost::unique_lock lock1(this->m_lock); boost::unique_lock lock2(other.m_lock); m_scratchpad = other.m_scratchpad; } }; };