erlang各种有用的函数包括一些有用nif封装,还有一些性能测试case。
Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

121 рядки
4.5 KiB

5 роки тому
  1. #ifndef NEURALTABLE_H
  2. #define NEURALTABLE_H
  3. #include "erl_nif.h"
  4. #include "neural_utils.h"
  5. #include <string>
  6. #include <stdio.h>
  7. #include <string.h>
  8. #include <unordered_map>
  9. #include <queue>
  10. #include <atomic>
  11. #ifdef _WIN32
  12. #include <windows.h>
  13. #include <io.h>
  14. #include <process.h>
  15. #else
  16. #include <unistd.h>
  17. #endif
  18. #define BUCKET_COUNT 64
  19. #define BUCKET_MASK (BUCKET_COUNT - 1)
  20. #define GET_BUCKET(key) key & BUCKET_MASK
  21. #define GET_LOCK(key) key & BUCKET_MASK
  22. #define RECLAIM_THRESHOLD 1048576
  23. using namespace std;
  24. class NeuralTable;
  25. typedef unordered_map<string, NeuralTable*> table_set;
  26. typedef unordered_map<unsigned long int, ERL_NIF_TERM> hash_table;
  27. typedef void (NeuralTable::*BatchFunction)(ErlNifPid pid);
  28. class NeuralTable {
  29. public:
  30. static ERL_NIF_TERM MakeTable(ErlNifEnv *env, ERL_NIF_TERM name, ERL_NIF_TERM keypos);
  31. static ERL_NIF_TERM Insert(ErlNifEnv *env, ERL_NIF_TERM table, ERL_NIF_TERM key, ERL_NIF_TERM object);
  32. static ERL_NIF_TERM InsertNew(ErlNifEnv *env, ERL_NIF_TERM table, ERL_NIF_TERM key, ERL_NIF_TERM object);
  33. static ERL_NIF_TERM Delete(ErlNifEnv *env, ERL_NIF_TERM table, ERL_NIF_TERM key);
  34. static ERL_NIF_TERM Empty(ErlNifEnv *env, ERL_NIF_TERM table);
  35. static ERL_NIF_TERM Get(ErlNifEnv *env, ERL_NIF_TERM table, ERL_NIF_TERM key);
  36. static ERL_NIF_TERM Increment(ErlNifEnv *env, ERL_NIF_TERM table, ERL_NIF_TERM key, ERL_NIF_TERM ops);
  37. static ERL_NIF_TERM Shift(ErlNifEnv *env, ERL_NIF_TERM table, ERL_NIF_TERM key, ERL_NIF_TERM ops);
  38. static ERL_NIF_TERM Unshift(ErlNifEnv *env, ERL_NIF_TERM table, ERL_NIF_TERM key, ERL_NIF_TERM ops);
  39. static ERL_NIF_TERM Swap(ErlNifEnv *env, ERL_NIF_TERM table, ERL_NIF_TERM key, ERL_NIF_TERM ops);
  40. static ERL_NIF_TERM Dump(ErlNifEnv *env, ERL_NIF_TERM table);
  41. static ERL_NIF_TERM Drain(ErlNifEnv *env, ERL_NIF_TERM table);
  42. static ERL_NIF_TERM GetKeyPosition(ErlNifEnv *env, ERL_NIF_TERM table);
  43. static ERL_NIF_TERM GarbageCollect(ErlNifEnv *env, ERL_NIF_TERM table);
  44. static ERL_NIF_TERM GarbageSize(ErlNifEnv *env, ERL_NIF_TERM table);
  45. static NeuralTable* GetTable(ErlNifEnv *env, ERL_NIF_TERM name);
  46. static void* DoGarbageCollection(void *table);
  47. static void* DoBatchOperations(void *table);
  48. static void* DoReclamation(void *table);
  49. static void Initialize() {
  50. table_mutex = enif_mutex_create("neural_table_maker");
  51. }
  52. static void Shutdown() {
  53. running = false;
  54. table_set::iterator it(tables.begin());
  55. while (it != tables.end()) {
  56. delete it->second;
  57. tables.erase(it);
  58. it = tables.begin();
  59. }
  60. enif_mutex_destroy(table_mutex);
  61. }
  62. void rlock(unsigned long int key) { enif_rwlock_rlock(locks[GET_LOCK(key)]); }
  63. void runlock(unsigned long int key) { enif_rwlock_runlock(locks[GET_LOCK(key)]); }
  64. void rwlock(unsigned long int key) { enif_rwlock_rwlock(locks[GET_LOCK(key)]); }
  65. void rwunlock(unsigned long int key) { enif_rwlock_rwunlock(locks[GET_LOCK(key)]); }
  66. ErlNifEnv *get_env(unsigned long int key);
  67. bool erase(unsigned long int key, ERL_NIF_TERM &ret);
  68. bool find(unsigned long int key, ERL_NIF_TERM &ret);
  69. void put(unsigned long int key, ERL_NIF_TERM tuple);
  70. void batch_dump(ErlNifPid pid);
  71. void batch_drain(ErlNifPid pid);
  72. void start_gc();
  73. void stop_gc();
  74. void start_batch();
  75. void stop_batch();
  76. void gc();
  77. void reclaim(unsigned long int key, ERL_NIF_TERM reclaim);
  78. unsigned long int garbage_size();
  79. void add_batch_job(ErlNifPid pid, BatchFunction fun);
  80. protected:
  81. static table_set tables;
  82. static atomic<bool> running;
  83. static ErlNifMutex *table_mutex;
  84. struct BatchJob {
  85. ErlNifPid pid;
  86. BatchFunction fun;
  87. };
  88. NeuralTable(unsigned int kp);
  89. ~NeuralTable();
  90. unsigned int garbage_cans[BUCKET_COUNT];
  91. hash_table hash_buckets[BUCKET_COUNT];
  92. ErlNifEnv *env_buckets[BUCKET_COUNT];
  93. ERL_NIF_TERM reclaimable[BUCKET_COUNT];
  94. ErlNifRWLock *locks[BUCKET_COUNT];
  95. ErlNifCond *gc_cond;
  96. ErlNifMutex *gc_mutex;
  97. ErlNifTid gc_tid;
  98. ErlNifTid rc_tid;
  99. ErlNifCond *batch_cond;
  100. ErlNifMutex *batch_mutex;
  101. queue<BatchJob> batch_jobs;
  102. ErlNifTid batch_tid;
  103. unsigned int key_pos;
  104. };
  105. #endif