00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #ifndef util_h
00023 #define util_h
00024
00025 #ifndef _REENTRANT
00026 #define _REENTRANT
00027 #endif
00028
00029 #include "config.h"
00030 #include <stdlib.h>
00031 #include <string.h>
00032 #include <netinet/in.h>
00033 #include <iostream>
00034 #include <vector>
00035 #include <list>
00036 using std::vector;
00037 using std::list;
00038 #include <map>
00039 using std::pair;
00040 using std::ostream;
00041
00042 #include <semaphore.h>
00043
00044 #define COND_INIT(sem) sem_init(&sem, 0, 0)
00045 #define COND_TIMED_WAIT(sem,ts) sem_timedwait(&sem, &ts)
00046 #define COND_WAIT(sem) sem_wait(&sem)
00047 #define COND_NOTIFY(sem) ({int c; sem_getvalue(&sem, &c); if (c == 0) sem_post(&sem);})
00048 #define COND_DESTROY(sem) sem_destroy(&sem)
00049
00050 typedef sem_t karoo_cond;
00051
00052
00053
00054
00055
00056
00057 #define KAROO_MUTEX_SEMAPHORE
00058 #ifdef KAROO_MUTEX_SEMAPHORE
00059
00060 #define MUTEX_INIT(mut) sem_init(&mut, 0, 1)
00061 #define MUTEX_DESTROY(mut) sem_destroy(&mut)
00062 #define MUTEX_LOCK(mut) sem_wait(&mut)
00063 #define MUTEX_UNLOCK(mut) sem_post(&mut)
00064
00065 typedef sem_t karoo_mutex;
00066
00067 #else
00068
00069 #include <pthread.h>
00070
00071 #define MUTEX_INIT(mut) pthread_mutex_init(&mut, NULL)
00072 #define MUTEX_DESTROY(mut) pthread_mutex_destroy(&mut)
00073 #define MUTEX_LOCK(mut) pthread_mutex_lock(&mut)
00074 #define MUTEX_UNLOCK(mut) pthread_mutex_unlock(&mut)
00075
00076 typedef pthread_mutex_t karoo_mutex;
00077
00078 #endif
00079
00080 #define TEMP_STRING(str) ({text::clonea _temp_string_c = str.c_str_clonea(); strdupa(_temp_string_c);})
00081
00165 inline bool strings_equal(const char* s1, const char* s2, size_t sz)
00166 {
00167 if (sz == 0)
00168 return false;
00169 for (size_t i = 0; i < sz; i++) {
00170 if (*s1 != *s2)
00171 return false;
00172 s1++;
00173 s2++;
00174 }
00175 return true;
00176 }
00177
00178
00179 namespace karoo {
00180 enum db_data_type {
00181 DB_DATA_TYPE_NULL = 0,
00182 DB_DATA_TYPE_UNSIGNED_8,
00183 DB_DATA_TYPE_BOOL,
00184 DB_DATA_TYPE_CHAR,
00185 DB_DATA_TYPE_UNSIGNED_16,
00186 DB_DATA_TYPE_UNSIGNED_32,
00187 DB_DATA_TYPE_UNSIGNED_64,
00188 DB_DATA_TYPE_INT_8,
00189 DB_DATA_TYPE_INT_16,
00190 DB_DATA_TYPE_INT_32,
00191 DB_DATA_TYPE_INT_64,
00192 DB_DATA_TYPE_FLOAT,
00193 DB_DATA_TYPE_DOUBLE,
00194 DB_DATA_TYPE_LONG_DOUBLE,
00195 DB_DATA_TYPE_STRING,
00196 DB_DATA_TYPE_BYTEA,
00197 };
00198
00221 class referable
00222 {
00223 private:
00224 unsigned reference_count;
00225 mutable karoo_mutex reference_count_sem;
00226 protected:
00227 public:
00228 referable()
00229 {
00230 reference_count = 0;
00231 MUTEX_INIT(reference_count_sem);
00232 }
00233 virtual ~referable()
00234 {
00235 MUTEX_DESTROY(reference_count_sem);
00236 }
00241 unsigned reference()
00242 {
00243 MUTEX_LOCK(reference_count_sem);
00244 reference_count++;
00245 unsigned c = reference_count;
00246 MUTEX_UNLOCK(reference_count_sem);
00247 return c;
00248 }
00255 unsigned dereference()
00256 {
00257 MUTEX_LOCK(reference_count_sem);
00258 reference_count--;
00259 unsigned c = reference_count;
00260 MUTEX_UNLOCK(reference_count_sem);
00261
00262 if (c == 0) {
00263 delete this;
00264 }
00265 return c;
00266 }
00267
00268 unsigned getReferenceCount() const
00269 {
00270 MUTEX_LOCK(reference_count_sem);
00271 unsigned c = reference_count;
00272 MUTEX_UNLOCK(reference_count_sem);
00273 return c;
00274 }
00275 };
00276
00277
00278 extern uint32_t hashint(uint32_t a);
00279
00280 enum hashable_type {
00281 HASHABLE_TYPE_UNKNOWN = 0,
00282 HASHABLE_TYPE_TIMEKEY,
00283 HASHABLE_TYPE_TEXT,
00284 HASHABLE_TYPE_INT32KEY,
00285 HASHABLE_TYPE_INT64KEY,
00286 };
00287
00288 class hashable {
00289 protected:
00290 hashable_type type;
00291 public:
00292 hashable() { type = HASHABLE_TYPE_UNKNOWN; }
00293 hashable(hashable_type type) { this->type = type; }
00294 hashable(const hashable& ref) { this->type = ref.type; }
00295 virtual ~hashable() {}
00296
00297 hashable_type getType() const { return type; }
00298
00299 virtual bool operator==(const hashable& ref) const = 0;
00300 virtual bool operator!=(const hashable& ref) const = 0;
00301 virtual bool operator>=(const hashable& ref) const = 0;
00302 virtual bool operator<=(const hashable& ref) const = 0;
00303 virtual bool operator>(const hashable& ref) const = 0;
00304 virtual bool operator<(const hashable& ref) const = 0;
00305 virtual uint32_t getHash() const = 0;
00306 virtual hashable* clone() const = 0;
00307 };
00308
00309 #define INV_NANOS 1000000000
00310
00311
00312 extern int compareTime(const struct timespec& ts, const struct timespec& val);
00313
00314 class timekey : public hashable {
00315 protected:
00316 struct timespec ts;
00317 public:
00318 timekey();
00319 timekey(const struct timespec& ref);
00320 virtual ~timekey();
00321
00322 void after(int after_seconds, long after_nano_seconds = 0);
00323
00324 const timekey& operator=(const timekey& ref);
00325 const timekey& operator=(const struct timespec& ref);
00326
00327 bool operator==(const timekey& ref) const;
00328 bool operator!=(const timekey& ref) const;
00329 bool operator>=(const timekey& ref) const;
00330 bool operator<=(const timekey& ref) const;
00331 bool operator>(const timekey& ref) const;
00332 bool operator<(const timekey& ref) const;
00333 bool operator==(const hashable& ref) const;
00334 bool operator!=(const hashable& ref) const;
00335 bool operator>=(const hashable& ref) const;
00336 bool operator<=(const hashable& ref) const;
00337 bool operator>(const hashable& ref) const;
00338 bool operator<(const hashable& ref) const;
00339 uint32_t getHash() const;
00340 hashable* clone() const;
00341 };
00342
00343 class int32key : public hashable {
00344 protected:
00345 uint32_t val;
00346 public:
00347 int32key();
00348 int32key(uint32_t ref);
00349 virtual ~int32key();
00350
00351 const int32key& operator=(uint32_t ref);
00352 const int32key& operator=(const int32key& ref);
00353
00354 bool operator==(const int32key& ref) const;
00355 bool operator!=(const int32key& ref) const;
00356 bool operator>=(const int32key& ref) const;
00357 bool operator<=(const int32key& ref) const;
00358 bool operator>(const int32key& ref) const;
00359 bool operator<(const int32key& ref) const;
00360 bool operator==(const hashable& ref) const;
00361 bool operator!=(const hashable& ref) const;
00362 bool operator>=(const hashable& ref) const;
00363 bool operator<=(const hashable& ref) const;
00364 bool operator>(const hashable& ref) const;
00365 bool operator<(const hashable& ref) const;
00366 uint32_t getHash() const;
00367 hashable* clone() const;
00368 };
00369
00370 class int64key : public hashable {
00371 protected:
00372 uint64_t val;
00373 public:
00374 int64key();
00375 int64key(uint64_t ref);
00376 virtual ~int64key();
00377
00378 const int64key& operator=(uint64_t ref);
00379 const int64key& operator=(const int64key& ref);
00380
00381 bool operator==(const int64key& ref) const;
00382 bool operator!=(const int64key& ref) const;
00383 bool operator>=(const int64key& ref) const;
00384 bool operator<=(const int64key& ref) const;
00385 bool operator>(const int64key& ref) const;
00386 bool operator<(const int64key& ref) const;
00387 bool operator==(const hashable& ref) const;
00388 bool operator!=(const hashable& ref) const;
00389 bool operator>=(const hashable& ref) const;
00390 bool operator<=(const hashable& ref) const;
00391 bool operator>(const hashable& ref) const;
00392 bool operator<(const hashable& ref) const;
00393 uint32_t getHash() const;
00394 hashable* clone() const;
00395 };
00396
00400 class text : public hashable {
00401 private:
00410 class text_data: public referable {
00411 protected:
00412 friend class text;
00414 char* str;
00416 size_t sz;
00418 size_t alloc_sz;
00420 mutable uint32_t hash;
00422 mutable bool hashed;
00423
00427 void sdbm() const;
00428 public:
00432 text_data();
00437 text_data(char c);
00441 text_data(const text_data& s);
00447 text_data(size_t length, char ch);
00452 text_data(const char* str);
00458 text_data(const char* str, size_t length);
00465 text_data(const text_data& str, size_t index, ssize_t length);
00466 virtual ~text_data();
00467
00474 void accommodate(size_t sz);
00475
00476 bool operator==(const text_data& c2) const;
00477 bool operator!=(const text_data& c2) const { return !((*this) == c2); }
00478 bool operator<(const text_data& c2) const;
00479 bool operator>(const text_data& c2) const;
00480 bool operator<=(const text_data& c2) const;
00481 bool operator>=(const text_data& c2) const;
00482
00489 bool substringCompare(const char* s, size_t ssz, size_t from) const;
00490
00497 static text_data* plus(const text_data& s1, const text_data& s2);
00504 static text_data* plus(const char* s, const text_data& s2);
00511 static text_data* plus(char c, const text_data& s2);
00518 static text_data* plus(const text_data& s1, const char* s);
00525 static text_data* plus(const text_data& s1, char c );
00531 char at(size_t index) const;
00540 char set(size_t index, char ch);
00541
00547 char* c_str_clone(size_t* bytes = NULL) const;
00548
00554 char* new_clone(size_t* bytes = NULL) const;
00555
00562 ssize_t find(const text_data& str, size_t index = 0) const;
00570 ssize_t find(const char* str, size_t index = 0, ssize_t length = -1) const;
00578 ssize_t find(char ch, size_t index = 0, char respect_quote = '\0') const;
00579
00586 ssize_t rfind(char ch, ssize_t from = -1) const;
00587
00592 int atoi() const {return (int)strtol(str,NULL,10); }
00593
00598 size_t length() const { return sz; }
00599
00604 size_t capacity() const { return alloc_sz; }
00605
00611 void erase(size_t from = 0, ssize_t len = -1);
00612
00618 uint32_t getHash() const;
00619
00625 time_t parseDate() const;
00630 time_t parseRFC850Date() const;
00635 time_t parseRFC1123Date() const;
00640 time_t parseasctimeDate() const;
00641 };
00642
00643 protected:
00647 mutable karoo_mutex sem;
00649 text_data* data;
00653 void lock() const { MUTEX_LOCK(sem); }
00657 void unlock() const { MUTEX_UNLOCK(sem); }
00658
00659 public:
00663 text();
00668 text(text_data* s);
00672 text(const text& s);
00678 text(size_t length, char ch);
00683 text(const char* str);
00689 text(const char* str, size_t length);
00697 text(const text& str, size_t index, ssize_t length = -1);
00698 virtual ~text();
00699
00700 bool operator==(const text& c2) const;
00701 bool operator!=(const text& c2) const;
00702 bool operator<(const text& c2) const;
00703 bool operator>(const text& c2) const;
00704 bool operator<=(const text& c2) const;
00705 bool operator>=(const text& c2) const;
00706 friend text operator+(const text& s1, const text& s2);
00707 friend text operator+(const char* s, const text& s2);
00708 friend text operator+(char c, const text& s2);
00709 friend text operator+(const text& s1, const char* s);
00710 friend text operator+(const text& s1, char c );
00711 const text& operator+=(const text& append);
00712 const text& operator+=(const char* append);
00713 const text& operator+=(const char append);
00714 const text& operator=(const text& s);
00715 const text& operator=(const char* s);
00716 const text& operator=(char ch);
00717 bool operator==(const hashable& ref) const;
00718 bool operator!=(const hashable& ref) const;
00719 bool operator>=(const hashable& ref) const;
00720 bool operator<=(const hashable& ref) const;
00721 bool operator>(const hashable& ref) const;
00722 bool operator<(const hashable& ref) const;
00723
00730 bool substringCompare(const char* s, size_t ssz, size_t from) const;
00736 bool substringCompare(const char* s, size_t from) const;
00742 bool substringCompare(const text& s, size_t from) const;
00743
00748 char operator[](size_t index) const { return at(index); }
00753 char at(size_t index) const;
00762 char set(size_t index, char ch);
00763
00768 const text& append(const text& str) { return (*this) += str; }
00773 const text& append(const char* str) { return (*this) += str; }
00781 const text& append(const text& str, size_t index, ssize_t len = -1);
00787 const text& append(const char* str, size_t num);
00793 const text& append(size_t num, char ch);
00794
00800 const text& assign(const text& str) { return (*this) = str; }
00805 const text& assign(const char* str) { return (*this) = str; }
00811 const text& assign(const char* str, size_t num);
00819 const text& assign(const text& str, size_t index, ssize_t len = -1);
00825 const text& assign(size_t num, char ch);
00826
00850 class clonea {
00851 public:
00852 class clonea_data: public referable {
00853 public:
00854 char* str;
00855 size_t sz;
00856 clonea_data(const text* ref)
00857 {
00858 if (ref->data && ref->data->str) {
00859 sz = ref->data->sz;
00860 str = new char[sz+1];
00861 memcpy(str, ref->data->str, sz);
00862 str[sz] = 0;
00863 }
00864 else {
00865 str = new char[1];
00866 sz = 0;
00867 str[0] = 0;
00868 }
00869 }
00870 virtual ~clonea_data()
00871 {
00872 delete [] str;
00873 }
00874 };
00875 clonea_data* data;
00876 clonea()
00877 {
00878 data = NULL;
00879 }
00880 clonea(const text* ref)
00881 {
00882 data = new clonea_data(ref);
00883 data->reference();
00884 }
00885 clonea(const clonea& ref)
00886 {
00887 data = ref.data;
00888 if (data)
00889 data->reference();
00890 }
00891 ~clonea()
00892 {
00893 if (data)
00894 data->dereference();
00895 }
00896 const clonea& operator=(const clonea& ref)
00897 {
00898 if (ref.data)
00899 ref.data->reference();
00900 if (data)
00901 data->dereference();
00902 data = ref.data;
00903 return *this;
00904 }
00905 operator const char*() const
00906 {
00907 if (data)
00908 return data->str;
00909 else
00910 return NULL;
00911 }
00912 operator size_t() const
00913 {
00914 if (data)
00915 return data->sz;
00916 else
00917 return 0;
00918 }
00919 };
00920
00941 clonea c_str_clonea(size_t* bytes = NULL) const;
00942
00948 char* c_str_clone(size_t* bytes = NULL) const;
00949
00955 char* new_clone(size_t* bytes = NULL) const;
00956
00961 int atoi() const;
00962
00966 void clear();
00967
00972 bool empty() const;
00973
00980 ssize_t find(const text& str, size_t index = 0) const;
00988 ssize_t find(const char* str, size_t index = 0, ssize_t length = -1) const;
00996 ssize_t find(char ch, size_t index = 0, char respect_quote = '\0') const;
00997
01004 ssize_t rfind(char ch, ssize_t from = -1) const;
01005
01010 size_t length() const;
01015 size_t capacity() const;
01016
01023 text substr(size_t index, ssize_t length = -1);
01024
01029 void writeOut(ostream& out) const;
01030
01036 void erase(size_t from = 0, ssize_t len = -1);
01037
01043 void write(const char* buf, size_t sz);
01048 void write(const char* val);
01053 void write(const text& val);
01058 void write(char val);
01063 void write(bool val);
01068 void write(uint32_t val);
01073 void write(uint64_t val);
01078 void write(int32_t val);
01083 void write(int64_t val);
01088 void write(double val);
01093 void write(long double val);
01094
01095 text& operator<<(const text& str);
01096 text& operator<<(const char* str);
01097 text& operator<<(char val);
01098 text& operator<<(bool val);
01099 text& operator<<(uint16_t val);
01100 text& operator<<(uint32_t val);
01101 text& operator<<(uint64_t val);
01102 text& operator<<(int16_t val);
01103 text& operator<<(int32_t val);
01104 text& operator<<(int64_t val);
01105 text& operator<<(float val);
01106 text& operator<<(double val);
01107 text& operator<<(long double val);
01108
01109
01115 text& appendDateString(time_t secs);
01116
01117
01123 uint32_t getHash() const;
01124
01130 time_t parseDate() const;
01135 time_t parseRFC850Date() const;
01140 time_t parseRFC1123Date() const;
01145 time_t parseasctimeDate() const;
01146
01147
01151 hashable* clone() const;
01152
01160 text replace(char c, const char* s, size_t num) const;
01161 };
01162
01163 extern const text null_string;
01164
01165 extern text operator+(const text& s1, const text& s2);
01166 extern text operator+(const char* s, const text& s2);
01167 extern text operator+(char c, const text& s2);
01168 extern text operator+(const text& s1, const char* s);
01169 extern text operator+(const text& s1, char c );
01170
01178 class stream_buffer {
01179 private:
01180 mutable karoo_mutex sem;
01181
01182 class packet {
01183 public:
01184 packet() { data = NULL; size = 0; offs = 0; }
01185 packet(const char* data, size_t offs, size_t size)
01186 {
01187 this->data = new char[size];
01188 memcpy(this->data, data, size);
01189 this->size = size;
01190 this->offs = offs;
01191 }
01192 packet(const packet& ref)
01193 {
01194 this->data = new char[ref.size];
01195 memcpy(this->data, ref.data, ref.size);
01196 this->size = ref.size;
01197 this->offs = ref.offs;
01198 }
01199 virtual ~packet()
01200 {
01201 if (this->data)
01202 delete [] this->data;
01203 }
01204 const packet& operator=(const packet& ref)
01205 {
01206 if (this->data)
01207 delete [] this->data;
01208 this->data = new char[ref.size];
01209 memcpy(this->data, ref.data, ref.size);
01210 this->size = ref.size;
01211 this->offs = ref.offs;
01212 return *this;
01213 }
01214 char* data;
01215 size_t size;
01216 size_t offs;
01217 };
01218 list<packet*> buffer;
01219 size_t current_size;
01220 ssize_t _dump(int fh);
01221 size_t _read(char* data, size_t sz);
01222 size_t _peek(char* data, size_t sz) const;
01223 ssize_t _find(char c, size_t from) const;
01224 ssize_t _find(const text& boundary, size_t from) const;
01225 size_t _read_URL_encoded(char* data, size_t sz);
01226 public:
01227 stream_buffer();
01236 stream_buffer(char* buf, size_t buf_length);
01237 virtual ~stream_buffer();
01238
01243 size_t size() const;
01244
01250 size_t write(const text& str);
01257 size_t write(const char* data, size_t sz);
01264 size_t read(char* data, size_t sz);
01270 void putBack(char* data, size_t sz);
01271
01277 ssize_t dump(int fh);
01278
01285 size_t write_URL_encoded(const char* data, size_t sz);
01292 size_t read_URL_encoded(char* data, size_t sz);
01293
01300 ssize_t find(char c, size_t from) const;
01301 void read_URL_params(vector<pair<text,text> >& params);
01302
01310 ssize_t find(const text& boundary, size_t from) const;
01316 ssize_t skip_to_multipart_form_data(const text& boundary);
01317
01322 void write_to_ostream(ostream& out) const;
01327 void write_to_ostream(text& out) const;
01328 };
01329
01330 extern ostream& operator<<(ostream& out, const text& str);
01331 extern ostream& operator<<(ostream& out, const stream_buffer& buf);
01332 extern text& operator<<(text& out, const stream_buffer& buf);
01333 extern text& operator<<(text& out, const std::string& str);
01334
01339 class pass {
01340 private:
01341 mutable karoo_mutex read_sem;
01342 mutable karoo_mutex write_sem;
01343 mutable unsigned reads;
01344 public:
01345 pass()
01346 {
01347 MUTEX_INIT(read_sem);
01348 MUTEX_INIT(write_sem);
01349 reads = 0;
01350 }
01351 virtual ~pass()
01352 {
01353 MUTEX_DESTROY(read_sem);
01354 MUTEX_DESTROY(write_sem);
01355 }
01356
01357 void start_reading() const
01358 {
01359 MUTEX_LOCK(write_sem);
01360 MUTEX_LOCK(read_sem);
01361 if (reads) {
01362 MUTEX_UNLOCK(write_sem);
01363 }
01364 reads++;
01365 MUTEX_UNLOCK(read_sem);
01366 }
01367
01368 void done_reading() const
01369 {
01370 MUTEX_LOCK(read_sem);
01371 reads--;
01372 if (!reads) {
01373 MUTEX_UNLOCK(write_sem);
01374 }
01375 MUTEX_UNLOCK(read_sem);
01376 }
01377
01378 void start_writing()
01379 {
01380 MUTEX_LOCK(write_sem);
01381 MUTEX_LOCK(read_sem);
01382 }
01383
01384 void done_writing()
01385 {
01386 MUTEX_UNLOCK(read_sem);
01387 MUTEX_UNLOCK(write_sem);
01388 }
01389 };
01390
01391 class khashe {
01392 public:
01393 class stash {
01394 public:
01395 hashable* key;
01396 referable* ref;
01397 stash()
01398 {
01399 key = NULL;
01400 ref = NULL;
01401 }
01402 stash(const hashable& key, referable* ref)
01403 {
01404 this->key = key.clone();
01405 this->ref = ref;
01406 if (ref)
01407 ref->reference();
01408 }
01409 virtual ~stash()
01410 {
01411 if (key)
01412 delete key;
01413 if (ref)
01414 ref->dereference();
01415 }
01416 stash(const stash& r)
01417 {
01418 key = r.key->clone();
01419 ref = r.ref;
01420 if (ref)
01421 ref->reference();
01422 }
01423 const stash& operator=(const stash& r)
01424 {
01425 if (key)
01426 delete key;
01427 key = r.key->clone();
01428 if (r.ref)
01429 r.ref->reference();
01430 if (ref)
01431 ref->dereference();
01432 ref = r.ref;
01433 return *this;
01434 }
01435 };
01436 class iterator {
01437 private:
01438 khashe* parent;
01439 size_t p;
01440 size_t it;
01441 public:
01442 iterator()
01443 {
01444 parent = NULL;
01445 p = 0;
01446 it = 0;
01447 }
01448
01449 iterator(khashe& parent)
01450 {
01451 this->parent = &parent;
01452 p = 0;
01453 it = 0;
01454 }
01455
01456 iterator(const iterator& ref)
01457 {
01458 parent = ref.parent;
01459 it = ref.it;
01460 p = ref.p;
01461 }
01462
01463 ~iterator() {}
01464
01465 const iterator& operator=(const iterator& ref)
01466 {
01467 this->parent = ref.parent;
01468 this->it = ref.it;
01469 this->p = ref.p;
01470 return *this;
01471 }
01472
01473 bool at_end() const
01474 {
01475 if (!parent)
01476 return true;
01477 bool ret;
01478 parent->bucket_lock.start_reading();
01479 if (p < parent->actual_sz) {
01480 khashe::bucket& slot = parent->buckets[p];
01481 MUTEX_LOCK(slot.lock);
01482 if (it < slot.chain.size()) {
01483 ret = false;
01484 }
01485 else {
01486 ret = p == parent->actual_sz-1;
01487 }
01488 MUTEX_UNLOCK(slot.lock);
01489 }
01490 else {
01491 ret = true;
01492 }
01493 parent->bucket_lock.done_reading();
01494 return ret;
01495 }
01496
01497 const iterator& operator++()
01498 {
01499 if (!parent)
01500 return *this;
01501
01502 parent->bucket_lock.start_reading();
01503 if (p < parent->actual_sz) {
01504 khashe::bucket& slot = parent->buckets[p];
01505 MUTEX_LOCK(slot.lock);
01506 size_t psz = slot.chain.size();
01507 if (psz != 0 && it < (psz-1)) {
01508 it++;
01509 }
01510 else {
01511 it = 0;
01512 p++;
01513 }
01514 MUTEX_UNLOCK(slot.lock);
01515 }
01516 parent->bucket_lock.done_reading();
01517
01518 return *this;
01519 }
01520
01521 referable* operator*()
01522 {
01523 referable* ret = NULL;
01524 parent->bucket_lock.start_reading();
01525 if (p < parent->actual_sz) {
01526 khashe::bucket& slot = parent->buckets[p];
01527 MUTEX_LOCK(slot.lock);
01528 size_t psz = slot.chain.size();
01529 if (psz != 0 && it < psz) {
01530 ret = slot.chain[it].ref;
01531 MUTEX_UNLOCK(slot.lock);
01532 }
01533 else {
01534 MUTEX_UNLOCK(slot.lock);
01535 it = 0;
01536 while ((p+1) < parent->actual_sz) {
01537 p++;
01538 khashe::bucket& slot = parent->buckets[p];
01539 MUTEX_LOCK(slot.lock);
01540 size_t psz = slot.chain.size();
01541 if (psz != 0) {
01542 ret = slot.chain[0].ref;
01543 MUTEX_UNLOCK(slot.lock);
01544 break;
01545 }
01546 MUTEX_UNLOCK(slot.lock);
01547 }
01548 }
01549 }
01550 parent->bucket_lock.done_reading();
01551 return ret;
01552 }
01553 };
01554
01555 class bucket {
01556 public:
01557 karoo_mutex lock;
01558 vector<stash> chain;
01559 bucket() { MUTEX_INIT(lock); }
01560 ~bucket() { MUTEX_DESTROY(lock); }
01561 };
01562
01563 private:
01564 size_t min_actual;
01565 size_t max_actual;
01566 size_t mask;
01567 mutable sem_t sz;
01568 bucket* buckets;
01569 size_t actual_sz;
01570 size_t min_sz;
01571 pass bucket_lock;
01572
01573 void _realloc();
01574 void realloc();
01575 public:
01576 khashe(size_t min_sz = 10);
01577 virtual ~khashe();
01578
01579 void insert(const hashable& key, referable* ref);
01580 void erase(const hashable& key);
01581 referable* find(const hashable& key);
01582 void clear();
01583 size_t size() const;
01584 };
01585 }
01586
01587 #endif