erlang各种有用的函数包括一些有用nif封装,还有一些性能测试case。
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

266 line
5.2 KiB

5 年之前
  1. #include "btree_map.h"
  2. #include <algorithm>
  3. #include <iostream>
  4. #include "murmurhash2.h"
  5. #include "binary.h"
  6. #include "erl_nif.h"
  7. // extend std::hash to understand Binary type
  8. namespace std {
  9. template <>
  10. struct hash<Binary>
  11. {
  12. size_t operator()(const Binary& b) const
  13. {
  14. return MurmurHash2(b.bin, b.size, 4242);
  15. }
  16. };
  17. }
  18. template <typename K, typename V>
  19. struct LRUNode
  20. {
  21. K key;
  22. V data;
  23. void *kvenv;
  24. LRUNode<K,V> *prev;
  25. LRUNode<K,V> *next;
  26. size_t size;
  27. LRUNode(void *kvenv = NULL, size_t size=0) : kvenv(kvenv), prev(NULL), next(NULL), size(size) { }
  28. /*
  29. static void *LRUNode<ErlTerm,ErlTerm>::operator new(size_t size) {
  30. return enif_alloc(size);
  31. }
  32. static void operator delete(void *block) {
  33. enif_free(block);
  34. }
  35. */
  36. void printChain() {
  37. LRUNode<K,V>* node;
  38. int i=11;
  39. std::cout << "(";
  40. for(node = this; node && i; node = node->next, i--) {
  41. std::cout << node->key << " -> ";
  42. }
  43. if (node) {
  44. std::cout << " loop detection end ";
  45. } else {
  46. std::cout << " end ";
  47. }
  48. std::cout << ")" << std::endl;
  49. }
  50. void printNextPrevKey() {
  51. std::cout << "(";
  52. printNextKey();
  53. printPrevKey();
  54. std::cout << ")";
  55. }
  56. void printNextKey() {
  57. if (next) {
  58. std::cout << "next key " << next->key << " ";
  59. }
  60. }
  61. void printPrevKey() {
  62. if (prev) {
  63. std::cout << "prev key " << prev->key << " ";
  64. }
  65. }
  66. };
  67. template <class K,class V>
  68. class LRUBtree {
  69. private:
  70. LRUNode<K,V> *oldest;
  71. LRUNode<K,V> *latest;
  72. unsigned long size;
  73. unsigned long max_size;
  74. void (*node_free)(LRUBtree<K,V> *lru, LRUNode<K,V> *node);
  75. void (*node_kickout)(LRUBtree<K,V> *lru, LRUNode<K,V> *node, void *call_env);
  76. typedef btree::btree_map<K, LRUNode<K,V>*> LRUBtree_map;
  77. public:
  78. LRUBtree_map bmap;
  79. bool pid_set = false;
  80. ErlNifPid pid;
  81. typedef typename LRUBtree_map::iterator iterator;
  82. typedef typename LRUBtree_map::reverse_iterator reverse_iterator;
  83. void printLatest() {
  84. if (latest) {
  85. std::cout << " latest " << latest->key;
  86. } else {
  87. std::cout << " no data in lru ";
  88. }
  89. }
  90. private:
  91. LRUNode<K,V>* erase(LRUNode<K,V> *node) {
  92. if (node->next) {
  93. node->next->prev = node->prev;
  94. }
  95. if (node->prev) {
  96. node->prev->next = node->next;
  97. }
  98. if (node == oldest) {
  99. oldest = node->prev;
  100. }
  101. if (node == latest) {
  102. latest = node->next;
  103. }
  104. if (node_free) {
  105. node_free(this, node);
  106. }
  107. node->next = NULL;
  108. node->prev = NULL;
  109. return node;
  110. }
  111. void printOldest() {
  112. if(oldest) {
  113. std::cout << " oldest " << oldest->key;
  114. } else {
  115. std::cout << " no data in lru ";
  116. }
  117. }
  118. void check_size(void *call_env) {
  119. if (size > max_size) {
  120. if (oldest) { // remove check if oldest exist and rely on max_size always being positive
  121. if (node_kickout)
  122. node_kickout(this, oldest, call_env);
  123. erase(oldest->key);
  124. }
  125. }
  126. }
  127. #define SIZE_100MB 100*1024*1024
  128. public:
  129. LRUBtree(unsigned long max_size = SIZE_100MB,
  130. void (*node_free)(LRUBtree<K,V> *lru, LRUNode<K,V> *node) = NULL,
  131. void (*node_kickout)(LRUBtree<K,V> *lru, LRUNode<K,V> *node, void *call_env) = NULL)
  132. : oldest(NULL), latest(NULL), size(0), max_size(max_size), node_free(node_free),
  133. node_kickout(node_kickout) { }
  134. ~LRUBtree() {
  135. LRUNode<K,V> *node;
  136. LRUNode<K,V> *next;
  137. node = latest;
  138. while(node) {
  139. if (node_free) {
  140. node_free(this, node);
  141. }
  142. next = node->next;
  143. delete node;
  144. node = next;
  145. }
  146. }
  147. void printSize() {
  148. std::cout << "size " << size << std::endl;
  149. }
  150. unsigned long getSize() {
  151. return size;
  152. }
  153. unsigned long getMaxSize() {
  154. return max_size;
  155. }
  156. void setMaxSize(unsigned long max_size) {
  157. this->max_size = max_size;
  158. }
  159. void erase(K key) {
  160. LRUNode<K,V> *node;
  161. if ((node = bmap[key])) {
  162. erase(node);
  163. bmap.erase(key);
  164. size -= node->size;
  165. delete node;
  166. }
  167. }
  168. inline void put(K key, V data,
  169. void *kvenv = NULL, void *call_env = NULL,
  170. size_t size = 1) {
  171. LRUNode<K,V> *node;
  172. this->size += size;
  173. check_size(call_env);
  174. // overwrite already existing key
  175. if ((node = bmap[key])) {
  176. this->size -= node->size;
  177. erase(node);
  178. node->kvenv = kvenv;
  179. node->next = latest;
  180. node->size = size;
  181. if (node->next) {
  182. node->next->prev = node;
  183. }
  184. if (!oldest) {
  185. oldest = node;
  186. }
  187. latest = node;
  188. node->key = key;
  189. node->data = data;
  190. }
  191. else if (!oldest) {
  192. node = new LRUNode<K,V>;
  193. node->key = key;
  194. node->data = data;
  195. node->kvenv = kvenv;
  196. node->size = size;
  197. oldest = node;
  198. latest = node;
  199. bmap[node->key] = node;
  200. }
  201. else {
  202. node = new LRUNode<K,V>;
  203. node->key = key;
  204. node->data = data;
  205. node->kvenv = kvenv;
  206. node->size = size;
  207. latest->prev = node;
  208. node->next = latest;
  209. latest = node;
  210. bmap[node->key] = node;
  211. }
  212. }
  213. LRUNode<K,V>* get(K key) {
  214. return bmap[key];
  215. }
  216. LRUNode<K,V>* getOldest() {
  217. return oldest;
  218. }
  219. LRUNode<K,V>* getLatest() {
  220. return latest;
  221. }
  222. LRUNode<K,V>* getNext(LRUNode<K,V> *node) {
  223. return node->next;
  224. }
  225. LRUNode<K,V>* getPrev(LRUNode<K,V> *node) {
  226. return node->prev;
  227. }
  228. };