From 97ade17d9b3eaaf0debe2671e7310536f6b75cb9 Mon Sep 17 00:00:00 2001 From: Tim Blechmann Date: Fri, 4 Jul 2008 18:19:58 +0200 Subject: [PATCH] [flyweight] implemented reader-writer locking for boost.flyweight based on boost::shared_mutex --- .../boost/flyweight/assoc_container_factory.hpp | 16 +++++++- .../boost/flyweight/detail/flyweight_core.hpp | 13 +++--- .../flyweight/detail/handle_factory_adaptor.hpp | 6 ++- flyweight/boost/flyweight/hashed_factory.hpp | 15 ++++++- flyweight/boost/flyweight/no_locking.hpp | 4 +- flyweight/boost/flyweight/rw_locking.hpp | 40 ++++++++++++++++++++ flyweight/boost/flyweight/rw_locking_fwd.hpp | 26 +++++++++++++ flyweight/boost/flyweight/simple_locking.hpp | 10 ++++- .../libs/flyweight/test/test_custom_factory.cpp | 9 +++- flyweight/libs/flyweight/test/test_rw_locking.cpp | 35 +++++++++++++++++ flyweight/libs/flyweight/test/test_rw_locking.hpp | 11 +++++ .../libs/flyweight/test/test_rw_locking_main.cpp | 18 +++++++++ 12 files changed, 187 insertions(+), 16 deletions(-) create mode 100644 flyweight/boost/flyweight/rw_locking.hpp create mode 100644 flyweight/boost/flyweight/rw_locking_fwd.hpp create mode 100644 flyweight/libs/flyweight/test/test_rw_locking.cpp create mode 100644 flyweight/libs/flyweight/test/test_rw_locking.hpp create mode 100644 flyweight/libs/flyweight/test/test_rw_locking_main.cpp diff --git a/flyweight/boost/flyweight/assoc_container_factory.hpp b/flyweight/boost/flyweight/assoc_container_factory.hpp index 9d66b50..5d63bad 100644 --- a/flyweight/boost/flyweight/assoc_container_factory.hpp +++ b/flyweight/boost/flyweight/assoc_container_factory.hpp @@ -33,13 +33,25 @@ public: typedef typename Container::iterator handle_type; typedef typename Container::value_type entry_type; - handle_type insert(const entry_type& x) + template + handle_type insert(const entry_type& x, mutex_type & mutex) { + upgrade_lock_type upgrade_lock(mutex); + handle_type it = cont.find(x); + + if (it != cont.end()) + return it; + + upgrade_to_unique_lock write_lock(upgrade_lock); + return cont.insert(x).first; } - void erase(handle_type h) + template + void erase(handle_type h, mutex_type & mutex) { + write_lock_type lock (mutex); cont.erase(h); } diff --git a/flyweight/boost/flyweight/detail/flyweight_core.hpp b/flyweight/boost/flyweight/detail/flyweight_core.hpp index 86c2c8a..a358e27 100644 --- a/flyweight/boost/flyweight/detail/flyweight_core.hpp +++ b/flyweight/boost/flyweight/detail/flyweight_core.hpp @@ -65,9 +65,8 @@ public: template static void erase(const handle_type& h,Checker check) { - typedef typename core::lock_type lock_type; - lock_type lock(core::mutex()); - if(check(h))core::factory().erase(h); + if(check(h)) + core::factory().erase(h, core::mutex()); } }; @@ -110,14 +109,16 @@ public: handle_type,entry_type > factory_type; typedef typename LockingPolicy::mutex_type mutex_type; - typedef typename LockingPolicy::lock_type lock_type; + typedef typename LockingPolicy::upgrade_lock_type upgrade_lock_type; + typedef typename LockingPolicy::upgrade_to_unique_lock_type upgrade_to_unique_lock_type; + typedef typename LockingPolicy::write_lock_type write_lock_type; static bool init(){return &(factory())!=0;} static handle_type insert(const Value& x) { - lock_type lock(mutex()); - return handle_type(factory().insert(entry_type(x))); + return handle_type(factory().template insert(entry_type(x), mutex())); } static const Value& value(const handle_type& h) diff --git a/flyweight/boost/flyweight/detail/handle_factory_adaptor.hpp b/flyweight/boost/flyweight/detail/handle_factory_adaptor.hpp index 3ff030d..ddc4b1f 100644 --- a/flyweight/boost/flyweight/detail/handle_factory_adaptor.hpp +++ b/flyweight/boost/flyweight/detail/handle_factory_adaptor.hpp @@ -30,9 +30,11 @@ struct handle_factory_adaptor:Factory public: typedef Handle handle_type; - handle_type insert(const Entry& x) + template + handle_type insert(const Entry& x, mutex_type & mutex) { - return static_cast(base().insert(x)); + return static_cast(base().template insert(x, mutex)); } private: diff --git a/flyweight/boost/flyweight/hashed_factory.hpp b/flyweight/boost/flyweight/hashed_factory.hpp index 135d813..4e93ab8 100644 --- a/flyweight/boost/flyweight/hashed_factory.hpp +++ b/flyweight/boost/flyweight/hashed_factory.hpp @@ -67,13 +67,24 @@ class hashed_factory_class:public factory_marker public: typedef const Entry* handle_type; - handle_type insert(const Entry& x) + template + handle_type insert(const Entry& x, mutex_type & mutex) { + upgrade_lock_type upgrade_lock(mutex); + typename container_type::const_iterator it = cont.find(x); + + if (it != cont.end()) + return &*it; + + upgrade_to_unique_lock write_lock(upgrade_lock); return &*cont.insert(x).first; } - void erase(handle_type h) + template + void erase(handle_type h, mutex_type & mutex) { + write_lock_type lock (mutex); cont.erase(cont.iterator_to(*h)); } diff --git a/flyweight/boost/flyweight/no_locking.hpp b/flyweight/boost/flyweight/no_locking.hpp index a5ec8b4..56a65cf 100644 --- a/flyweight/boost/flyweight/no_locking.hpp +++ b/flyweight/boost/flyweight/no_locking.hpp @@ -26,7 +26,9 @@ namespace flyweights{ struct no_locking:locking_marker { struct mutex_type{}; - typedef mutex_type lock_type; + typedef mutex_type upgrade_lock_type; + typedef mutex_type upgrade_to_unique_lock_type; + typedef mutex_type write_lock_type; }; } /* namespace flyweights */ diff --git a/flyweight/boost/flyweight/rw_locking.hpp b/flyweight/boost/flyweight/rw_locking.hpp new file mode 100644 index 0000000..7556e7d --- /dev/null +++ b/flyweight/boost/flyweight/rw_locking.hpp @@ -0,0 +1,40 @@ +/* Copyright 2006-2007 Joaquín M López Muñoz. + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + * + * See http://www.boost.org/libs/flyweight for library home page. + */ + +#ifndef BOOST_FLYWEIGHT_RW_LOCKING_HPP +#define BOOST_FLYWEIGHT_RW_LOCKING_HPP + +#if defined(_MSC_VER)&&(_MSC_VER>=1200) +#pragma once +#endif + +#include /* keep it first to prevent nasty warns in MSVC */ +#include +#include + +#include + +/* recursive locking policy based on boost::shared_mutex */ + +namespace boost{ + +namespace flyweights{ + +struct rw_locking:locking_marker +{ + typedef boost::shared_mutex mutex_type; + typedef boost::upgrade_lock upgrade_lock_type; + typedef boost::upgrade_to_unique_lock upgrade_to_unique_lock_type; + typedef boost::unique_lock write_lock_type; +}; + +} /* namespace flyweights */ + +} /* namespace boost */ + +#endif diff --git a/flyweight/boost/flyweight/rw_locking_fwd.hpp b/flyweight/boost/flyweight/rw_locking_fwd.hpp new file mode 100644 index 0000000..50d0685 --- /dev/null +++ b/flyweight/boost/flyweight/rw_locking_fwd.hpp @@ -0,0 +1,26 @@ +/* Copyright 2006-2007 Joaquín M López Muñoz. + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + * + * See http://www.boost.org/libs/flyweight for library home page. + */ + +#ifndef BOOST_FLYWEIGHT_RW_LOCKING_FWD_HPP +#define BOOST_FLYWEIGHT_RW_LOCKING_FWD_HPP + +#if defined(_MSC_VER)&&(_MSC_VER>=1200) +#pragma once +#endif + +namespace boost{ + +namespace flyweights{ + +struct rw_locking; + +} /* namespace flyweights */ + +} /* namespace boost */ + +#endif diff --git a/flyweight/boost/flyweight/simple_locking.hpp b/flyweight/boost/flyweight/simple_locking.hpp index 2e6aba6..0acbeb0 100644 --- a/flyweight/boost/flyweight/simple_locking.hpp +++ b/flyweight/boost/flyweight/simple_locking.hpp @@ -27,7 +27,15 @@ namespace flyweights{ struct simple_locking:locking_marker { typedef detail::recursive_lightweight_mutex mutex_type; - typedef mutex_type::scoped_lock lock_type; + typedef mutex_type::scoped_lock upgrade_lock_type; + + struct upgrade_to_unique_lock_type + { + upgrade_to_unique_lock_type(upgrade_lock_type const &) + {} + }; + typedef mutex_type::scoped_lock write_lock_type; + }; } /* namespace flyweights */ diff --git a/flyweight/libs/flyweight/test/test_custom_factory.cpp b/flyweight/libs/flyweight/test/test_custom_factory.cpp index 76fb3c7..b4bae2f 100644 --- a/flyweight/libs/flyweight/test/test_custom_factory.cpp +++ b/flyweight/libs/flyweight/test/test_custom_factory.cpp @@ -41,8 +41,11 @@ class lu_factory_class:public factory_marker public: typedef typename container_type::iterator handle_type; - handle_type insert(const Entry& x) + template + handle_type insert(const Entry& x, mutex_type & mutex) { + upgrade_lock_type lock(mutex); + upgrade_to_unique_lock_type ulock(lock); handle_type h; for(h=cont.begin();h!=cont.end();++h){ if(static_cast(h->x)==static_cast(x)){ @@ -59,8 +62,10 @@ public: return h; } - void erase(handle_type h) + template + void erase(handle_type h, mutex_type & mutex) { + write_lock_type lock(mutex); cont.erase(h); } diff --git a/flyweight/libs/flyweight/test/test_rw_locking.cpp b/flyweight/libs/flyweight/test/test_rw_locking.cpp new file mode 100644 index 0000000..cc2ff17 --- /dev/null +++ b/flyweight/libs/flyweight/test/test_rw_locking.cpp @@ -0,0 +1,35 @@ +/* Boost.Flyweight test of no_locking. + * + * Copyright 2006-2007 Joaquín M López Muñoz. + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + * + * See http://www.boost.org/libs/flyweight for library home page. + */ + +#include "test_no_locking.hpp" + +#include /* keep it first to prevent nasty warns in MSVC */ +#include +#include +#include +#include +#include +#include "test_basic_template.hpp" + +using namespace boost::flyweights; + +struct rw_locking_flyweight_specifier +{ + template + struct apply + { + typedef flyweight type; + }; +}; + +void test_rw_locking() +{ + BOOST_FLYWEIGHT_TEST_BASIC(rw_locking_flyweight_specifier) +} diff --git a/flyweight/libs/flyweight/test/test_rw_locking.hpp b/flyweight/libs/flyweight/test/test_rw_locking.hpp new file mode 100644 index 0000000..ed57c24 --- /dev/null +++ b/flyweight/libs/flyweight/test/test_rw_locking.hpp @@ -0,0 +1,11 @@ +/* Boost.Flyweight test of no_locking. + * + * Copyright 2006-2007 Joaquín M López Muñoz. + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + * + * See http://www.boost.org/libs/flyweight for library home page. + */ + +void test_rw_locking(); diff --git a/flyweight/libs/flyweight/test/test_rw_locking_main.cpp b/flyweight/libs/flyweight/test/test_rw_locking_main.cpp new file mode 100644 index 0000000..ffbefe5 --- /dev/null +++ b/flyweight/libs/flyweight/test/test_rw_locking_main.cpp @@ -0,0 +1,18 @@ +/* Boost.Flyweight test of no_locking. + * + * Copyright 2006-2007 Joaquín M López Muñoz. + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + * + * See http://www.boost.org/libs/flyweight for library home page. + */ + +#include +#include "test_rw_locking.hpp" + +int main() +{ + test_rw_locking(); + return boost::report_errors(); +} -- 1.5.6