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 >= 1800L || (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(T const& obj, size_t lock_count) { return (reinterpret_cast<size_t>(&obj) / sizeof(T)) % lock_count; } template<typename pool_type, bool read> class pool_guard_one : public pool_guard_base { 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; } void unlock() const { pool_.unlock(hash_); owns_lock_ = false; } public: 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_type, bool read, size_t H> class pool_guard_many : public pool_guard_base { template<typename t_lock, size_t lock_count> 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]); } } void unlock() { while(hash_count_) { pool_.unlock(hashes_[--hash_count_]); } } public: #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 t_lock, size_t lock_count> class lock_pool { typedef lock_pool<t_lock, lock_count> pool_type; mutable t_lock locks_[lock_count]; 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 lock_pool(const char* name) : name_(name) {} template<typename T> static size_t hash(const T& obj) { using namespace syncope; return lock_hash(obj, lock_count); } void lock(size_t hash) const { std::cout << name_ << " lock " << hash << std::endl; locks_[hash].lock(); } void rdlock(size_t hash) const { std::cout << name_ << " read lock " << hash << std::endl; using namespace syncope; lock_for_reading(locks_[hash]); } void unlock(size_t hash) const { std::cout << name_ << " unlock " << hash << std::endl; locks_[hash].unlock(); } #ifdef COMPILER_HAS_CPP11_SUPPORT template<typename T> pool_guard_one<pool_type, false> synchronize(T const& arg) { return std::move(pool_guard_one<pool_type, false, T>(*this, arg)); } template<typename T> pool_guard_one<pool_type, true> synchronize_read(T const& arg) { return std::move(pool_guard_one<pool_type, true, T>(*this, arg)); } template<typename... T> pool_guard_many<pool_type, false, sizeof...(T)> synchronize(T const&... args) { return std::move(pool_guard_many<pool_type, false, sizeof...(T)>(*this, args...)); } template<typename... T> pool_guard_many<pool_type, true, sizeof...(T)> synchronize_read(T const&... args) { return std::move(pool_guard_many<pool_type, true, sizeof...(T)>(*this, args...)); } #else template<typename T> pool_guard_one<pool_type, false> synchronize(T const& arg) { return pool_guard_one<pool_type, false>(*this, arg); } template<typename T1, typename T2> pool_guard_many<pool_type, false, 2> synchronize(T1 const& a1, T2 const& a2) { return pool_guard_many<pool_type, false, 2>(*this) .add_hash(a1).add_hash(a2).sort_hashes_and_lock(); } template<typename T1, typename T2, typename T3> pool_guard_many<pool_type, false, 3> synchronize(T1 const& a1, T2 const& a2, T3 const& a3) { return pool_guard_many<pool_type, 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<pool_type, false, 4> synchronize(T1 const& a1, T2 const& a2, T3 const& a3, T4 const& a4) { return pool_guard_many<pool_type, 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<pool_type, true> synchronize_read(T const& arg) { return pool_guard_one<pool_type, true>(*this, arg); } template<typename T1, typename T2> pool_guard_many<pool_type, true, 2> synchronize_read(T1 const& a1, T2 const& a2) { return pool_guard_many<pool_type, true, 2>(*this) .add_hash(a1).add_hash(a2).sort_hashes_and_lock(); } template<typename T1, typename T2, typename T3> pool_guard_many<pool_type, true, 3> synchronize_read(T1 const& a1, T2 const& a2, T3 const& a3) { return pool_guard_many<pool_type, 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<pool_type, true, 4> synchronize(T1 const& a1, T2 const& a2, T3 const& a3, T4 const& a4) { return pool_guard_many<pool_type, 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() {} }; inline void lock_for_reading(my_rwlock& mtx) { mtx.rdlock(); } 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, size_t lock_count) { return obj.id%lock_count; } 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