2011-02-15 02:57:19 +00:00
|
|
|
/**
|
2009-10-19 21:55:25 +00:00
|
|
|
* concurrentHash.h
|
|
|
|
*
|
2011-02-15 02:57:19 +00:00
|
|
|
* @file A concurrent, fixed-size hashtable that allows users to obtain latches
|
|
|
|
* on its keys.
|
|
|
|
*
|
|
|
|
* Operations against this hashtable proceed in two phases. In the first phase,
|
|
|
|
* the bucket that contains (or will contain) the requested key is located. At
|
|
|
|
* this point, the implementation optionally returns control to the caller,
|
|
|
|
* which may examine the bucket, and decide to complete or cancel the operation.
|
|
|
|
*
|
|
|
|
* Of course, like any other mutex, bucket latches allow you to write code that
|
|
|
|
* will deadlock. Initiating an operation against a hashtable while holding a
|
|
|
|
* latch on one of its buckets is unsafe, and will lead to deadlocks and other
|
|
|
|
* bad behavior.
|
|
|
|
*
|
|
|
|
* Notes:
|
|
|
|
*
|
|
|
|
* It would be trivial to implement an insert_begin, _finish, and _remove, but
|
|
|
|
* the need for such things has never come up. (See hashtable_test_and_set instead)
|
|
|
|
*
|
2009-10-19 21:55:25 +00:00
|
|
|
* Created on: Oct 15, 2009
|
|
|
|
* Author: sears
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef CONCURRENTHASH_H_
|
|
|
|
#define CONCURRENTHASH_H_
|
|
|
|
#include <stasis/common.h>
|
|
|
|
|
|
|
|
typedef struct hashtable_t hashtable_t;
|
2009-11-09 19:50:00 +00:00
|
|
|
typedef struct bucket_t bucket_t;
|
2009-10-19 21:55:25 +00:00
|
|
|
|
2009-11-09 19:50:00 +00:00
|
|
|
typedef struct hashtable_bucket_handle_t {
|
|
|
|
bucket_t * b1;
|
|
|
|
pageid_t key;
|
|
|
|
pageid_t idx;
|
|
|
|
void * ret;
|
|
|
|
} hashtable_bucket_handle_t;
|
|
|
|
|
|
|
|
hashtable_t * hashtable_init(pageid_t size);
|
2009-10-19 21:55:25 +00:00
|
|
|
void hashtable_deinit(hashtable_t * ht);
|
|
|
|
void * hashtable_insert(hashtable_t *ht, pageid_t p, void * val);
|
|
|
|
/** Atomically insert a value if the key was not already defined
|
|
|
|
* @return NULL if val was inserted
|
|
|
|
*/
|
|
|
|
void * hashtable_test_and_set(hashtable_t *ht, pageid_t p, void * val);
|
|
|
|
void * hashtable_lookup(hashtable_t *ht, pageid_t p);
|
|
|
|
void * hashtable_remove(hashtable_t *ht, pageid_t p);
|
|
|
|
|
2009-11-09 19:50:00 +00:00
|
|
|
|
|
|
|
void * hashtable_test_and_set_lock(hashtable_t *ht, pageid_t p, void * val, hashtable_bucket_handle_t *h);
|
|
|
|
void * hashtable_lookup_lock(hashtable_t *ht, pageid_t p, hashtable_bucket_handle_t *h);
|
|
|
|
void * hashtable_remove_begin(hashtable_t *ht, pageid_t p, hashtable_bucket_handle_t *h);
|
|
|
|
void hashtable_remove_finish(hashtable_t *ht, hashtable_bucket_handle_t *h);
|
|
|
|
void hashtable_remove_cancel(hashtable_t *ht, hashtable_bucket_handle_t *h);
|
|
|
|
|
2011-02-15 02:57:19 +00:00
|
|
|
/** Be sure to call this immediately after calling an methods whose names end in "_lock()" */
|
|
|
|
void hashtable_unlock(hashtable_bucket_handle_t *h);
|
|
|
|
|
2010-09-30 19:27:18 +00:00
|
|
|
/**
|
|
|
|
* @return -0 if key not found, 1 if the key exists, >1 if the hashtable is corrupt, and the key appears multiple times..
|
|
|
|
*/
|
|
|
|
int hashtable_debug_number_of_key_copies(hashtable_t *ht, pageid_t pageied);
|
|
|
|
|
2009-11-09 19:50:00 +00:00
|
|
|
|
2009-10-19 21:55:25 +00:00
|
|
|
#endif /* CONCURRENTHASH_H_ */
|