erlang各种有用的函数包括一些有用nif封装,还有一些性能测试case。
25개 이상의 토픽을 선택하실 수 없습니다. Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

172 lines
4.3 KiB

  1. #include "etsq.h"
  2. ErlNifRWLock *qinfo_map_rwlock;
  3. QInfoMap qinfo_map;
  4. // Function finds the queue from map and returns QueueInfo
  5. // Not thread safe.
  6. QueueInfo* get_q_info(char* name)
  7. {
  8. //std::cout<<"Info: "<< name<<std::endl;
  9. QInfoMap::iterator iter = qinfo_map.find(name);
  10. if (iter != qinfo_map.end())
  11. {
  12. //std::cout<<" Fetched ";
  13. return iter->second;
  14. }
  15. return NULL;
  16. }
  17. void new_q(char* name)
  18. {
  19. //std::cout<<"Create: " << name<<std::endl;
  20. WriteLock write_lock(qinfo_map_rwlock);
  21. QueueInfo *queue_info = new QueueInfo(name);
  22. qinfo_map.insert(QInfoMapPair(name, queue_info));
  23. //std::cout<<"Created: " << name<<std::endl;
  24. }
  25. bool push(char* name, ErlTerm *erl_term)
  26. {
  27. QueueInfo *pqueue_info = NULL;
  28. ReadLock read_lock(qinfo_map_rwlock);
  29. if (NULL != (pqueue_info = get_q_info(name)))
  30. {
  31. Mutex mutex(pqueue_info->pmutex);
  32. pqueue_info->queue.push(erl_term);
  33. return true;
  34. }
  35. return false;
  36. }
  37. // Returns new ErlTerm. Caller should delete it
  38. ErlTerm* pop(char* name, bool read_only)
  39. {
  40. QueueInfo *pqueue_info = NULL;
  41. ReadLock read_lock(qinfo_map_rwlock);
  42. if (NULL != (pqueue_info = get_q_info(name)))
  43. {
  44. Mutex mutex(pqueue_info->pmutex);
  45. if (!pqueue_info->queue.empty())
  46. {
  47. ErlTerm *erl_term = pqueue_info->queue.front();
  48. if(read_only)
  49. {
  50. return new ErlTerm(erl_term);
  51. }
  52. pqueue_info->queue.pop();
  53. return erl_term;
  54. }
  55. return new ErlTerm("empty");
  56. }
  57. return NULL;
  58. }
  59. static ERL_NIF_TERM new_queue(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
  60. {
  61. int size = 100;
  62. char *name = new char(size);
  63. enif_get_atom(env, argv[0], name, size, ERL_NIF_LATIN1);
  64. {
  65. QueueInfo *pqueue_info = NULL;
  66. ReadLock read_lock(qinfo_map_rwlock);
  67. if (NULL != (pqueue_info = get_q_info(name)))
  68. {
  69. return enif_make_error(env, "already_exists");
  70. }
  71. }
  72. new_q(name);
  73. return enif_make_atom(env, "ok");
  74. }
  75. static ERL_NIF_TERM info(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
  76. {
  77. int size = 100;
  78. char name[100];
  79. enif_get_atom(env, argv[0], name, size, ERL_NIF_LATIN1);
  80. int queue_size = 0;
  81. {
  82. QueueInfo *pqueue_info = NULL;
  83. ReadLock read_lock(qinfo_map_rwlock);
  84. if (NULL == (pqueue_info = get_q_info(name)))
  85. return enif_make_badarg(env);
  86. queue_size = pqueue_info->queue.size();
  87. }
  88. return enif_make_list2(env,
  89. enif_make_tuple2(env, enif_make_atom(env, "name"), enif_make_atom(env, name)),
  90. enif_make_tuple2(env, enif_make_atom(env, "size"), enif_make_int(env, queue_size)));
  91. }
  92. static ERL_NIF_TERM push_back(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
  93. {
  94. int size = 100;
  95. char name[100];
  96. enif_get_atom(env, argv[0], name, size, ERL_NIF_LATIN1);
  97. ErlTerm *erl_term = new ErlTerm(argv[1]);
  98. if (push(name, erl_term))
  99. return enif_make_atom(env, "ok");
  100. delete erl_term;
  101. return enif_make_badarg(env);
  102. }
  103. static ERL_NIF_TERM pop_front(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
  104. {
  105. int size = 100;
  106. char name[100];
  107. enif_get_atom(env, argv[0], name, size, ERL_NIF_LATIN1);
  108. ErlTerm *erl_term = NULL;
  109. if (NULL == (erl_term = pop(name, false)))
  110. return enif_make_badarg(env);
  111. ERL_NIF_TERM return_term = enif_make_copy(env, erl_term->term);
  112. delete erl_term;
  113. return return_term;
  114. }
  115. static ERL_NIF_TERM get_front(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
  116. {
  117. int size = 100;
  118. char name[100];
  119. enif_get_atom(env, argv[0], name, size, ERL_NIF_LATIN1);
  120. ErlTerm *erl_term = NULL;
  121. if (NULL == (erl_term = pop(name, true)))
  122. return enif_make_badarg(env);
  123. ERL_NIF_TERM return_term = enif_make_copy(env, erl_term->term);
  124. delete erl_term;
  125. return return_term;
  126. }
  127. static int is_ok_load_info(ErlNifEnv* env, ERL_NIF_TERM load_info)
  128. {
  129. int i;
  130. return enif_get_int(env, load_info, &i) && i == 1;
  131. }
  132. static int load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info)
  133. {
  134. if (!is_ok_load_info(env, load_info))
  135. return -1;
  136. qinfo_map_rwlock = enif_rwlock_create((char*)"qinfo");
  137. return 0;
  138. }
  139. static int upgrade(ErlNifEnv* env, void** priv_data, void** old_priv_data, ERL_NIF_TERM load_info)
  140. {
  141. if (!is_ok_load_info(env, load_info))
  142. return -1;
  143. return 0;
  144. }
  145. static void unload(ErlNifEnv* env, void* priv_data)
  146. {
  147. enif_rwlock_destroy(qinfo_map_rwlock);
  148. }
  149. static ErlNifFunc nif_funcs[] = {
  150. {"new", 1, new_queue},
  151. {"info", 1, info},
  152. {"push_back", 2, push_back},
  153. {"pop_front", 1, pop_front},
  154. {"get_front", 1, get_front}
  155. };
  156. ERL_NIF_INIT(etsq, nif_funcs, load, NULL, upgrade, unload)