codepad
[
create a new paste
]
login
|
about
Language:
C
C++
D
Haskell
Lua
OCaml
PHP
Perl
Plain Text
Python
Ruby
Scheme
Tcl
#if defined _MSC_VER && _MSC_VER >= 1700L || (defined(__cplusplus) && __cplusplus >= 201103L) # define COMPILER_HAS_CPP11_SUPPORT #endif #define __STDC_LIMIT_MACROS #include <iostream> #include <memory> #include <functional> #include <algorithm> #ifdef COMPILER_HAS_CPP11_SUPPORT #include <array> #endif namespace syncope { class pool_guard_base {}; typedef const pool_guard_base& pool_guard; // default hash function template<typename T> inline size_t lock_hash(const T& obj) { return (reinterpret_cast<size_t>(&obj) / sizeof(T)); } template<bool> class t_bool {}; typedef t_bool<true> t_true; typedef t_bool<false> t_false; template<typename T> class has_rdlock { private: typedef char Yes; typedef char No[2]; template <typename U, U> struct really_has; template <typename C> static Yes& Test(really_has <void(C::*)() const, &C::rdlock>*); template <typename C> static Yes& Test(really_has <void(C::*)(), &C::rdlock>*); template <typename> static No& Test(...); public: static bool const value = sizeof(Test<T>(0)) == sizeof(Yes); }; template<typename Pool, bool Read> class pool_guard_one : public pool_guard_base { typedef Pool pool_type; pool_type& pool_; const size_t hash_; mutable bool owns_lock_; void lock() const { if(Read) pool_.rdlock(hash_); else pool_.lock(hash_); owns_lock_ = true; } public: void unlock() const { pool_.unlock(hash_); owns_lock_ = false; } template<typename T> pool_guard_one(pool_type& pool, T const& obj) : pool_(pool) , hash_(pool_type::hash(obj)) , owns_lock_(false) { lock(); } #ifdef COMPILER_HAS_CPP11_SUPPORT pool_guard_one(pool_guard_one const&) = delete; pool_guard_one& operator = (pool_guard_one const&) = delete; pool_guard_one(pool_guard_one&& other) : pool_(other.pool_) , hash_(other.hash_) , owns_lock_(other.owns_lock_) { other.owns_lock_ = false; } pool_guard_one& operator = (pool_guard_one&& other) { hash_ = other.hash_; other.owns_lock_ = false; assert(&pool_ == &other.pool_); } #else pool_guard_one(pool_guard_one const& other) : pool_(other.pool_) , hash_(other.hash_) , owns_lock_(other.owns_lock_) { other.owns_lock_ = false; } pool_guard_one& operator = (pool_guard_one const& other) { hash_ = other.hash_; other.owns_lock_ = false; assert(&pool_ == &other.pool_); } #endif ~pool_guard_one() { if(owns_lock_) { unlock(); } } }; template<class Pool, bool Read, size_t H> class pool_guard_many : public pool_guard_base { typedef Pool pool_type; template<typename Lock, size_t LockCount> friend class lock_pool; pool_type& pool_; size_t hashes_[H]; mutable size_t hash_count_; #ifdef COMPILER_HAS_CPP11_SUPPORT template<size_t I, typename ...T> typename std::enable_if<I < H, void>::type add_hashes(std::tuple<T const&...> const& items) { add_hash(std::get<I>(items)); add_hashes<I + 1>(items); }; template<size_t I, typename ...T> typename std::enable_if < I == H, void>::type add_hashes(std::tuple<T const&...> const& items) { }; #endif template<typename T> pool_guard_many& add_hash(const T& obj) { hashes_[hash_count_] = pool_type::hash(obj); ++hash_count_; return *this; } pool_guard_many& sort_hashes_and_lock() { std::sort(&hashes_[0], &hashes_[hash_count_]); size_t* it = std::unique(&hashes_[0], &hashes_[hash_count_]); hash_count_ = it - &hashes_[0]; lock(); return *this; } void lock() { for(size_t i = 0; i < hash_count_; ++i) { if(Read) pool_.rdlock(hashes_[i]); else pool_.lock(hashes_[i]); } } public: void unlock() { while(hash_count_) { pool_.unlock(hashes_[--hash_count_]); } } #ifdef COMPILER_HAS_CPP11_SUPPORT template<typename ...T> pool_guard_many(pool_type& pool, T const&... objects) : pool_(pool) , hash_count_(0) { add_hashes<0>(std::tie(objects...)); sort_hashes_and_lock(); } pool_guard_many(pool_guard_many const&) = delete; pool_guard_many& operator = (pool_guard_many const&) = delete; pool_guard_many(pool_guard_many&& other) : pool_(other.pool_) , hash_count_(other.hash_count_) { std::copy(&other.hashes_[0], &other.hashes_[hash_count_], hashes_); other.hash_count_ = 0; } pool_guard_many& operator = (pool_guard_many&& other) { assert(&other.pool_ == &pool_); hash_count_ = other.hash_count_; std::copy(&other.hashes_[0], &other.hashes_[hash_count_], hashes_); other.hash_count_ = 0; } #else pool_guard_many(pool_type& pool) : pool_(pool) , hash_count_(0) {} pool_guard_many(pool_guard_many const& other) : pool_(other.pool_) , hash_count_(other.hash_count_) { std::copy(&other.hashes_[0], &other.hashes_[hash_count_], hashes_); other.hash_count_ = 0; } pool_guard_many& operator = (pool_guard_many const& other) { assert(&other.pool_ == &pool_); hash_count_ = other.hash_count_; std::copy(&other.hashes_[0], &other.hashes_[hash_count_], hashes_); other.hash_count_ = 0; } #endif ~pool_guard_many() { if(hash_count_) { unlock(); } } }; template<typename Lock, size_t LockCount> class lock_pool { typedef Lock lock_type; mutable lock_type locks_[LockCount]; const char* name_; #ifdef COMPILER_HAS_CPP11_SUPPORT public: lock_pool(lock_pool const&) = delete; lock_pool& operator = (lock_pool const&) = delete; #else lock_pool(lock_pool const&); lock_pool& operator = (lock_pool const&); public: #endif const static size_t lock_count = LockCount; lock_pool(const char* name) : name_(name) {} template<typename T> static size_t hash(const T& obj) { using namespace syncope; return lock_hash(obj) % LockCount; } void lock(size_t ix) const { std::cout << name_ << " lock " << ix << std::endl; locks_[ix].lock(); } void rdlock(size_t ix, t_true) const { std::cout << name_ << " read lock " << ix << std::endl; locks_[ix].rdlock(); } void rdlock(size_t ix, t_false) const { std::cout << name_ << " lock " << ix << std::endl; locks_[ix].lock(); } void rdlock(size_t ix) const { rdlock(ix, t_bool<has_rdlock<Lock>::value>()); } void unlock(size_t hash) const { std::cout << name_ << " unlock " << hash << std::endl; locks_[hash].unlock(); } typedef pool_guard_one<lock_pool, false> write_guard; typedef pool_guard_one<lock_pool, true> read_guard; #ifdef COMPILER_HAS_CPP11_SUPPORT template<typename T> pool_guard_one<lock_pool, false> synchronize(T const& arg) { return std::move(pool_guard_one<lock_pool, false, T>(*this, arg)); } template<typename T> pool_guard_one<lock_pool, true> synchronize_read(T const& arg) { return std::move(pool_guard_one<lock_pool, true, T>(*this, arg)); } template<typename... T> pool_guard_many<lock_pool, false, sizeof...(T)> synchronize(T const&... args) { return std::move(pool_guard_many<lock_pool, false, sizeof...(T)>(*this, args...)); } template<typename... T> pool_guard_many<lock_pool, true, sizeof...(T)> synchronize_read(T const&... args) { return std::move(pool_guard_many<lock_pool, true, sizeof...(T)>(*this, args...)); } #else template<typename T> pool_guard_one<lock_pool, false> synchronize(T const& arg) { return pool_guard_one<lock_pool, false>(*this, arg); } template<typename T1, typename T2> pool_guard_many<lock_pool, false, 2> synchronize(T1 const& a1, T2 const& a2) { return pool_guard_many<lock_pool, false, 2>(*this) .add_hash(a1).add_hash(a2).sort_hashes_and_lock(); } template<typename T1, typename T2, typename T3> pool_guard_many<lock_pool, false, 3> synchronize(T1 const& a1, T2 const& a2, T3 const& a3) { return pool_guard_many<lock_pool, false, 3>(*this) .add_hash(a1).add_hash(a2).add_hash(a3).sort_hashes_and_lock(); } template<typename T1, typename T2, typename T3, typename T4> pool_guard_many<lock_pool, false, 4> synchronize(T1 const& a1, T2 const& a2, T3 const& a3, T4 const& a4) { return pool_guard_many<lock_pool, false, 4>(*this) .add_hash(a1).add_hash(a2).add_hash(a3).add_hash(a4).sort_hashes_and_lock(); } template<typename T> pool_guard_one<lock_pool, true> synchronize_read(T const& arg) { return pool_guard_one<lock_pool, true>(*this, arg); } template<typename T1, typename T2> pool_guard_many<lock_pool, true, 2> synchronize_read(T1 const& a1, T2 const& a2) { return pool_guard_many<lock_pool, true, 2>(*this) .add_hash(a1).add_hash(a2).sort_hashes_and_lock(); } template<typename T1, typename T2, typename T3> pool_guard_many<lock_pool, true, 3> synchronize_read(T1 const& a1, T2 const& a2, T3 const& a3) { return pool_guard_many<lock_pool, true, 3>(*this) .add_hash(a1).add_hash(a2).add_hash(a3).sort_hashes_and_lock(); } template<typename T1, typename T2, typename T3, typename T4> pool_guard_many<lock_pool, true, 4> synchronize(T1 const& a1, T2 const& a2, T3 const& a3, T4 const& a4) { return pool_guard_many<lock_pool, true, 4>(*this) .add_hash(a1).add_hash(a2).add_hash(a3).add_hash(a4).sort_hashes_and_lock(); } #endif }; } // namespace syncope struct my_rwlock { void rdlock() {}; void lock() {} void unlock() {} }; typedef syncope::lock_pool<my_rwlock, 256> test_pool; test_pool foo_sync("foo sync"); struct foo { foo(int id) : id(id) {} int id; }; inline size_t lock_hash(const foo& obj) { return obj.id; } int main() { #ifdef COMPILER_HAS_CPP11_SUPPORT std::cout << "C++11" << std::endl; #endif foo a(1), b(2), c(3); { syncope::pool_guard guard1 = foo_sync.synchronize_read(a, b); std::cout << "read locked 1" << std::endl; } { syncope::pool_guard guard = foo_sync.synchronize(a, b, c); std::cout << "write locked" << std::endl; } return 0; }
Private
[
?
]
Run code
Submit