/* * Copyright (C) 2007-2014 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; mutable ReadWriteMutex mCore; }; } #endif