diff options
author | Mike Buland <eichlan@xagasoft.com> | 2013-02-26 04:54:45 +0000 |
---|---|---|
committer | Mike Buland <eichlan@xagasoft.com> | 2013-02-26 04:54:45 +0000 |
commit | 772a6bef0de2dcf0b7d9d596ce86f1def4d1f03e (patch) | |
tree | a9e3be8f50309fe06c8c1d01092e6fc0d9c5b82d /src/unstable | |
parent | f342b82c4bf125c7cb478160bf011e571c317726 (diff) | |
download | libbu++-772a6bef0de2dcf0b7d9d596ce86f1def4d1f03e.tar.gz libbu++-772a6bef0de2dcf0b7d9d596ce86f1def4d1f03e.tar.bz2 libbu++-772a6bef0de2dcf0b7d9d596ce86f1def4d1f03e.tar.xz libbu++-772a6bef0de2dcf0b7d9d596ce86f1def4d1f03e.zip |
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.
Diffstat (limited to 'src/unstable')
-rw-r--r-- | src/unstable/readwritemutex.h | 36 | ||||
-rw-r--r-- | src/unstable/synchrohash.cpp | 0 | ||||
-rw-r--r-- | src/unstable/synchrohash.h | 224 |
3 files changed, 260 insertions, 0 deletions
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 | |||
69 | */ | 69 | */ |
70 | void unlockWrite(); | 70 | void unlockWrite(); |
71 | 71 | ||
72 | class ReadLocker | ||
73 | { | ||
74 | public: | ||
75 | ReadLocker( ReadWriteMutex &m ) : | ||
76 | m( m ) | ||
77 | { | ||
78 | m.lockRead(); | ||
79 | } | ||
80 | |||
81 | ~ReadLocker() | ||
82 | { | ||
83 | m.unlockRead(); | ||
84 | } | ||
85 | |||
86 | private: | ||
87 | ReadWriteMutex &m; | ||
88 | }; | ||
89 | |||
90 | class WriteLocker | ||
91 | { | ||
92 | public: | ||
93 | WriteLocker( ReadWriteMutex &m ) : | ||
94 | m( m ) | ||
95 | { | ||
96 | m.lockWrite(); | ||
97 | } | ||
98 | |||
99 | ~WriteLocker() | ||
100 | { | ||
101 | m.unlockWrite(); | ||
102 | } | ||
103 | |||
104 | private: | ||
105 | ReadWriteMutex &m; | ||
106 | }; | ||
107 | |||
72 | private: | 108 | private: |
73 | Bu::Mutex mRead; | 109 | Bu::Mutex mRead; |
74 | int iCounter; | 110 | int iCounter; |
diff --git a/src/unstable/synchrohash.cpp b/src/unstable/synchrohash.cpp new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/src/unstable/synchrohash.cpp | |||
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 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2007-2013 Xagasoft, All rights reserved. | ||
3 | * | ||
4 | * This file is part of the libbu++ library and is released under the | ||
5 | * terms of the license contained in the file LICENSE. | ||
6 | */ | ||
7 | |||
8 | #ifndef BU_SYNCHRO_HASH_H | ||
9 | #define BU_SYNCHRO_HASH_H | ||
10 | |||
11 | #include <memory> | ||
12 | #include "bu/hash.h" | ||
13 | #include "bu/readwritemutex.h" | ||
14 | |||
15 | namespace Bu | ||
16 | { | ||
17 | /** | ||
18 | * Libbu++ Thread Safe Template Hash Table. This is your average hash | ||
19 | * table, that uses | ||
20 | * template functions in order to do fast, efficient, generalized hashing. | ||
21 | * It's pretty easy to use, and works well with all other libbu++ types so | ||
22 | * far. | ||
23 | * | ||
24 | * In order to use it, I recommend the following for all basic usage: | ||
25 | *@code | ||
26 | // Define a Hash typedef with strings as keys and ints as values. | ||
27 | typedef Bu::SynchroHash<Bu::String, int> StrIntHash; | ||
28 | |||
29 | // Create one | ||
30 | StrIntHash hInts; | ||
31 | |||
32 | // Insert some integers | ||
33 | hInts["one"] = 1; | ||
34 | hInts["forty-two"] = 42; | ||
35 | hInts.insert("forty two", 42 ); | ||
36 | |||
37 | // Get values out of the hash, the last two options are the most explicit, | ||
38 | // and must be used if the hash's value type does not match what you're | ||
39 | // comparing to exactly. | ||
40 | if( hInts["one"] == 1 ) doSomething(); | ||
41 | if( hInts["forty-two"].value() == 42 ) doSomething(); | ||
42 | if( hInts.get("forty two") == 42 ) doSomething(); | ||
43 | |||
44 | // Iterate through the Hash | ||
45 | for( StrIntHash::iterator i = hInts.begin(); i != hInts.end(); i++ ) | ||
46 | { | ||
47 | // i.getValue() works too | ||
48 | print("'%s' = %d\n", i.getKey().getStr(), (*i) ); | ||
49 | } | ||
50 | |||
51 | @endcode | ||
52 | *@param key (typename) The datatype of the hashtable keys | ||
53 | *@param value (typename) The datatype of the hashtable data | ||
54 | *@param sizecalc (typename) Functor to compute new table size on rehash | ||
55 | *@param keyalloc (typename) Memory allocator for hashtable keys | ||
56 | *@param valuealloc (typename) Memory allocator for hashtable values | ||
57 | *@param challoc (typename) Byte allocator for bitflags | ||
58 | *@ingroup Containers | ||
59 | */ | ||
60 | template<typename key, typename value, | ||
61 | typename sizecalc = __calcNextTSize_fast, | ||
62 | typename keyalloc = std::allocator<key>, | ||
63 | typename valuealloc = std::allocator<value>, | ||
64 | typename challoc = std::allocator<uint32_t> | ||
65 | > | ||
66 | class SynchroHash | ||
67 | { | ||
68 | private: | ||
69 | typedef class SynchroHash<key, value, sizecalc, keyalloc, valuealloc, challoc> MyType; | ||
70 | typedef class Hash<key, value, sizecalc, keyalloc, valuealloc, challoc> HashType; | ||
71 | |||
72 | public: | ||
73 | SynchroHash() | ||
74 | { | ||
75 | } | ||
76 | |||
77 | virtual ~SynchroHash() | ||
78 | { | ||
79 | } | ||
80 | |||
81 | /** | ||
82 | * Get the current hash table capacity. (Changes at re-hash) | ||
83 | *@returns (uint32_t) The current capacity. | ||
84 | */ | ||
85 | uint32_t getCapacity() const | ||
86 | { | ||
87 | ReadWriteMutex::ReadLocker rl( mCore ); | ||
88 | return hCore.getCapacity(); | ||
89 | } | ||
90 | |||
91 | /** | ||
92 | * Get the number of hash locations spoken for. (Including | ||
93 | * not-yet-cleaned-up deleted items.) | ||
94 | *@returns (uint32_t) The current fill state. | ||
95 | */ | ||
96 | uint32_t getFill() const | ||
97 | { | ||
98 | ReadWriteMutex::ReadLocker rl( mCore ); | ||
99 | return; hCore.getFill(); | ||
100 | } | ||
101 | |||
102 | /** | ||
103 | * Get the number of items stored in the hash table. | ||
104 | *@returns (uint32_t) The number of items stored in the hash table. | ||
105 | */ | ||
106 | uint32_t getSize() const | ||
107 | { | ||
108 | ReadWriteMutex::ReadLocker rl( mCore ); | ||
109 | return hCore.getSize(); | ||
110 | } | ||
111 | |||
112 | bool isEmpty() const | ||
113 | { | ||
114 | ReadWriteMutex::ReadLocker rl( mCore ); | ||
115 | return hCore.isEmpty(); | ||
116 | } | ||
117 | |||
118 | /** | ||
119 | * Get the number of items which have been deleted, but not yet | ||
120 | * cleaned up. | ||
121 | *@returns (uint32_t) The number of deleted items. | ||
122 | */ | ||
123 | uint32_t getDeleted() const | ||
124 | { | ||
125 | ReadWriteMutex::ReadLocker rl( mCore ); | ||
126 | return hCore.getDeleted(); | ||
127 | } | ||
128 | |||
129 | /** | ||
130 | * Insert a value (v) under key (k) into the hash table | ||
131 | *@param k (key_type) Key to list the value under. | ||
132 | *@param v (value_type) Value to store in the hash table. | ||
133 | */ | ||
134 | void insert( const key &k, const value &v ) | ||
135 | { | ||
136 | ReadWriteMutex::WriteLocker wl( mCore ); | ||
137 | hCore.insert( k, v ); | ||
138 | } | ||
139 | |||
140 | /** | ||
141 | * Remove a value from the hash table. | ||
142 | *@param k (key_type) The data under this key will be erased. | ||
143 | */ | ||
144 | void erase( const key &k ) | ||
145 | { | ||
146 | ReadWriteMutex::WriteLocker wl( mCore ); | ||
147 | hCore.erase( k ); | ||
148 | } | ||
149 | |||
150 | /** | ||
151 | * Remove all data from the hash table. | ||
152 | */ | ||
153 | virtual void clear() | ||
154 | { | ||
155 | ReadWriteMutex::WriteLocker wl( mCore ); | ||
156 | hCore.clear(); | ||
157 | } | ||
158 | |||
159 | /** | ||
160 | * Get a const item of data from the hash table. | ||
161 | *@param k (key_type) Key pointing to the data to be retrieved. | ||
162 | *@returns (const value_type &) A const version of the data pointed | ||
163 | * to by (k). | ||
164 | */ | ||
165 | value get( const key &k ) const | ||
166 | { | ||
167 | ReadWriteMutex::WriteLocker wl( mCore ); | ||
168 | return hCore.get( k ); | ||
169 | } | ||
170 | |||
171 | /** | ||
172 | * Does the hash table contain an item under key (k). | ||
173 | *@param k (key_type) The key to check. | ||
174 | *@returns (bool) Whether there was an item in the hash under key (k). | ||
175 | */ | ||
176 | bool has( const key &k ) const | ||
177 | { | ||
178 | ReadWriteMutex::ReadLocker rl( mCore ); | ||
179 | return hCore.has( k ); | ||
180 | } | ||
181 | |||
182 | /** | ||
183 | * Get a list of all the keys in the hash table. | ||
184 | *@returns (std::list<key_type>) The list of keys in the hash table. | ||
185 | */ | ||
186 | Bu::List<key> getKeys() const | ||
187 | { | ||
188 | ReadWriteMutex::ReadLocker rl( mCore ); | ||
189 | return hCore.getKeys(); | ||
190 | } | ||
191 | |||
192 | Bu::List<value> getValues() const | ||
193 | { | ||
194 | ReadWriteMutex::ReadLocker rl( mCore ); | ||
195 | return hCore.getValues(); | ||
196 | } | ||
197 | |||
198 | bool operator==( const MyType &rhs ) const | ||
199 | { | ||
200 | ReadWriteMutex::ReadLocker rl( mCore ); | ||
201 | ReadWriteMutex::ReadLocker rl2( rhs.mCore ); | ||
202 | return hCore == rhs.hCore; | ||
203 | } | ||
204 | |||
205 | bool operator!=( const MyType &rhs ) const | ||
206 | { | ||
207 | return !(*this == rhs); | ||
208 | } | ||
209 | |||
210 | MyType &operator+=( const MyType &rhs ) | ||
211 | { | ||
212 | ReadWriteMutex::WriteLocker wl( mCore ); | ||
213 | ReadWriteMutex::ReadLocker rl( rhs.mCore ); | ||
214 | hCore += rhs.hCore; | ||
215 | return *this; | ||
216 | } | ||
217 | |||
218 | private: | ||
219 | HashType hCore; | ||
220 | ReadWriteMutex mCore; | ||
221 | }; | ||
222 | } | ||
223 | |||
224 | #endif | ||