36 // A CALLBACK_FUNC and LOOKUP_FUNC needs to be provided for get and insert. |
36 // A CALLBACK_FUNC and LOOKUP_FUNC needs to be provided for get and insert. |
37 |
37 |
38 class Thread; |
38 class Thread; |
39 class Mutex; |
39 class Mutex; |
40 |
40 |
41 template <typename VALUE, typename CONFIG, MEMFLAGS F> |
41 template <typename CONFIG, MEMFLAGS F> |
42 class ConcurrentHashTable : public CHeapObj<F> { |
42 class ConcurrentHashTable : public CHeapObj<F> { |
|
43 typedef typename CONFIG::Value VALUE; |
43 private: |
44 private: |
44 // This is the internal node structure. |
45 // This is the internal node structure. |
45 // Only constructed with placement new from memory allocated with MEMFLAGS of |
46 // Only constructed with placement new from memory allocated with MEMFLAGS of |
46 // the InternalTable or user-defined memory. |
47 // the InternalTable or user-defined memory. |
47 class Node { |
48 class Node { |
250 // Scoped critical section, which also handles the invisible epochs. |
251 // Scoped critical section, which also handles the invisible epochs. |
251 // An invisible epoch/version do not need a write_synchronize(). |
252 // An invisible epoch/version do not need a write_synchronize(). |
252 class ScopedCS: public StackObj { |
253 class ScopedCS: public StackObj { |
253 protected: |
254 protected: |
254 Thread* _thread; |
255 Thread* _thread; |
255 ConcurrentHashTable<VALUE, CONFIG, F>* _cht; |
256 ConcurrentHashTable<CONFIG, F>* _cht; |
256 GlobalCounter::CSContext _cs_context; |
257 GlobalCounter::CSContext _cs_context; |
257 public: |
258 public: |
258 ScopedCS(Thread* thread, ConcurrentHashTable<VALUE, CONFIG, F>* cht); |
259 ScopedCS(Thread* thread, ConcurrentHashTable<CONFIG, F>* cht); |
259 ~ScopedCS(); |
260 ~ScopedCS(); |
260 }; |
261 }; |
261 |
262 |
262 |
263 |
263 // Max number of deletes in one bucket chain during bulk delete. |
264 // Max number of deletes in one bucket chain during bulk delete. |
471 template <typename VALUE_SIZE_FUNC> |
472 template <typename VALUE_SIZE_FUNC> |
472 void statistics_to(Thread* thread, VALUE_SIZE_FUNC& vs_f, outputStream* st, |
473 void statistics_to(Thread* thread, VALUE_SIZE_FUNC& vs_f, outputStream* st, |
473 const char* table_name); |
474 const char* table_name); |
474 |
475 |
475 // Moves all nodes from this table to to_cht |
476 // Moves all nodes from this table to to_cht |
476 bool try_move_nodes_to(Thread* thread, ConcurrentHashTable<VALUE, CONFIG, F>* to_cht); |
477 bool try_move_nodes_to(Thread* thread, ConcurrentHashTable<CONFIG, F>* to_cht); |
477 |
|
478 // This is a Curiously Recurring Template Pattern (CRPT) interface for the |
|
479 // specialization. |
|
480 struct BaseConfig { |
|
481 public: |
|
482 // Called when the hash table needs the hash for a VALUE. |
|
483 static uintx get_hash(const VALUE& value, bool* dead) { |
|
484 return CONFIG::get_hash(value, dead); |
|
485 } |
|
486 // Default node allocation. |
|
487 static void* allocate_node(size_t size, const VALUE& value); |
|
488 // Default node reclamation. |
|
489 static void free_node(void* memory, const VALUE& value); |
|
490 }; |
|
491 |
478 |
492 // Scoped multi getter. |
479 // Scoped multi getter. |
493 class MultiGetHandle : private ScopedCS { |
480 class MultiGetHandle : private ScopedCS { |
494 public: |
481 public: |
495 MultiGetHandle(Thread* thread, ConcurrentHashTable<VALUE, CONFIG, F>* cht) |
482 MultiGetHandle(Thread* thread, ConcurrentHashTable<CONFIG, F>* cht) |
496 : ScopedCS(thread, cht) {} |
483 : ScopedCS(thread, cht) {} |
497 // In the MultiGetHandle scope you can lookup items matching LOOKUP_FUNC. |
484 // In the MultiGetHandle scope you can lookup items matching LOOKUP_FUNC. |
498 // The VALUEs are safe as long as you never save the VALUEs outside the |
485 // The VALUEs are safe as long as you never save the VALUEs outside the |
499 // scope, e.g. after ~MultiGetHandle(). |
486 // scope, e.g. after ~MultiGetHandle(). |
500 template <typename LOOKUP_FUNC> |
487 template <typename LOOKUP_FUNC> |