From 772a6bef0de2dcf0b7d9d596ce86f1def4d1f03e Mon Sep 17 00:00:00 2001 From: Mike Buland Date: Tue, 26 Feb 2013 04:54:45 +0000 Subject: Added auto-lock classes to the Bu::ReadWriteMutex, I think I like that type of encapsulation, at least for the read/write guy. Also started work on a thread-safe wrapper for the standard hash. There is a lot of functionality we just have to leave out in this, it's just too dangerous in a thread-safe class. --- src/tests/synchrohash.cpp | 7 ++ src/unstable/readwritemutex.h | 36 +++++++ src/unstable/synchrohash.cpp | 0 src/unstable/synchrohash.h | 224 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 267 insertions(+) create mode 100644 src/tests/synchrohash.cpp create mode 100644 src/unstable/synchrohash.cpp create mode 100644 src/unstable/synchrohash.h diff --git a/src/tests/synchrohash.cpp b/src/tests/synchrohash.cpp new file mode 100644 index 0000000..7f6dbd1 --- /dev/null +++ b/src/tests/synchrohash.cpp @@ -0,0 +1,7 @@ +#include + +int main() +{ + Bu::SynchroHash Things; +} + diff --git a/src/unstable/readwritemutex.h b/src/unstable/readwritemutex.h index 8641e3f..eb159ca 100644 --- a/src/unstable/readwritemutex.h +++ b/src/unstable/readwritemutex.h @@ -69,6 +69,42 @@ namespace Bu */ void unlockWrite(); + class ReadLocker + { + public: + ReadLocker( ReadWriteMutex &m ) : + m( m ) + { + m.lockRead(); + } + + ~ReadLocker() + { + m.unlockRead(); + } + + private: + ReadWriteMutex &m; + }; + + class WriteLocker + { + public: + WriteLocker( ReadWriteMutex &m ) : + m( m ) + { + m.lockWrite(); + } + + ~WriteLocker() + { + m.unlockWrite(); + } + + private: + ReadWriteMutex &m; + }; + private: Bu::Mutex mRead; int iCounter; diff --git a/src/unstable/synchrohash.cpp b/src/unstable/synchrohash.cpp new file mode 100644 index 0000000..e69de29 diff --git a/src/unstable/synchrohash.h b/src/unstable/synchrohash.h new file mode 100644 index 0000000..45572c2 --- /dev/null +++ b/src/unstable/synchrohash.h @@ -0,0 +1,224 @@ +/* + * Copyright (C) 2007-2013 Xagasoft, All rights reserved. + * + * This file is part of the libbu++ library and is released under the + * terms of the license contained in the file LICENSE. + */ + +#ifndef BU_SYNCHRO_HASH_H +#define BU_SYNCHRO_HASH_H + +#include +#include "bu/hash.h" +#include "bu/readwritemutex.h" + +namespace Bu +{ + /** + * Libbu++ Thread Safe Template Hash Table. This is your average hash + * table, that uses + * template functions in order to do fast, efficient, generalized hashing. + * It's pretty easy to use, and works well with all other libbu++ types so + * far. + * + * In order to use it, I recommend the following for all basic usage: + *@code + // Define a Hash typedef with strings as keys and ints as values. + typedef Bu::SynchroHash StrIntHash; + + // Create one + StrIntHash hInts; + + // Insert some integers + hInts["one"] = 1; + hInts["forty-two"] = 42; + hInts.insert("forty two", 42 ); + + // Get values out of the hash, the last two options are the most explicit, + // and must be used if the hash's value type does not match what you're + // comparing to exactly. + if( hInts["one"] == 1 ) doSomething(); + if( hInts["forty-two"].value() == 42 ) doSomething(); + if( hInts.get("forty two") == 42 ) doSomething(); + + // Iterate through the Hash + for( StrIntHash::iterator i = hInts.begin(); i != hInts.end(); i++ ) + { + // i.getValue() works too + print("'%s' = %d\n", i.getKey().getStr(), (*i) ); + } + + @endcode + *@param key (typename) The datatype of the hashtable keys + *@param value (typename) The datatype of the hashtable data + *@param sizecalc (typename) Functor to compute new table size on rehash + *@param keyalloc (typename) Memory allocator for hashtable keys + *@param valuealloc (typename) Memory allocator for hashtable values + *@param challoc (typename) Byte allocator for bitflags + *@ingroup Containers + */ + template, + typename valuealloc = std::allocator, + typename challoc = std::allocator + > + class SynchroHash + { + private: + typedef class SynchroHash MyType; + typedef class Hash HashType; + + public: + SynchroHash() + { + } + + virtual ~SynchroHash() + { + } + + /** + * Get the current hash table capacity. (Changes at re-hash) + *@returns (uint32_t) The current capacity. + */ + uint32_t getCapacity() const + { + ReadWriteMutex::ReadLocker rl( mCore ); + return hCore.getCapacity(); + } + + /** + * Get the number of hash locations spoken for. (Including + * not-yet-cleaned-up deleted items.) + *@returns (uint32_t) The current fill state. + */ + uint32_t getFill() const + { + ReadWriteMutex::ReadLocker rl( mCore ); + return; hCore.getFill(); + } + + /** + * Get the number of items stored in the hash table. + *@returns (uint32_t) The number of items stored in the hash table. + */ + uint32_t getSize() const + { + ReadWriteMutex::ReadLocker rl( mCore ); + return hCore.getSize(); + } + + bool isEmpty() const + { + ReadWriteMutex::ReadLocker rl( mCore ); + return hCore.isEmpty(); + } + + /** + * Get the number of items which have been deleted, but not yet + * cleaned up. + *@returns (uint32_t) The number of deleted items. + */ + uint32_t getDeleted() const + { + ReadWriteMutex::ReadLocker rl( mCore ); + return hCore.getDeleted(); + } + + /** + * Insert a value (v) under key (k) into the hash table + *@param k (key_type) Key to list the value under. + *@param v (value_type) Value to store in the hash table. + */ + void insert( const key &k, const value &v ) + { + ReadWriteMutex::WriteLocker wl( mCore ); + hCore.insert( k, v ); + } + + /** + * Remove a value from the hash table. + *@param k (key_type) The data under this key will be erased. + */ + void erase( const key &k ) + { + ReadWriteMutex::WriteLocker wl( mCore ); + hCore.erase( k ); + } + + /** + * Remove all data from the hash table. + */ + virtual void clear() + { + ReadWriteMutex::WriteLocker wl( mCore ); + hCore.clear(); + } + + /** + * Get a const item of data from the hash table. + *@param k (key_type) Key pointing to the data to be retrieved. + *@returns (const value_type &) A const version of the data pointed + * to by (k). + */ + value get( const key &k ) const + { + ReadWriteMutex::WriteLocker wl( mCore ); + return hCore.get( k ); + } + + /** + * Does the hash table contain an item under key (k). + *@param k (key_type) The key to check. + *@returns (bool) Whether there was an item in the hash under key (k). + */ + bool has( const key &k ) const + { + ReadWriteMutex::ReadLocker rl( mCore ); + return hCore.has( k ); + } + + /** + * Get a list of all the keys in the hash table. + *@returns (std::list) The list of keys in the hash table. + */ + Bu::List getKeys() const + { + ReadWriteMutex::ReadLocker rl( mCore ); + return hCore.getKeys(); + } + + Bu::List getValues() const + { + ReadWriteMutex::ReadLocker rl( mCore ); + return hCore.getValues(); + } + + bool operator==( const MyType &rhs ) const + { + ReadWriteMutex::ReadLocker rl( mCore ); + ReadWriteMutex::ReadLocker rl2( rhs.mCore ); + return hCore == rhs.hCore; + } + + bool operator!=( const MyType &rhs ) const + { + return !(*this == rhs); + } + + MyType &operator+=( const MyType &rhs ) + { + ReadWriteMutex::WriteLocker wl( mCore ); + ReadWriteMutex::ReadLocker rl( rhs.mCore ); + hCore += rhs.hCore; + return *this; + } + + private: + HashType hCore; + ReadWriteMutex mCore; + }; +} + +#endif -- cgit v1.2.3