/c_src/erlv8.hh

http://github.com/beamjs/erlv8 · C++ Header · 221 lines · 165 code · 48 blank · 8 comment · 0 complexity · d386446658352e2a96c2404bdb370f82 MD5 · raw file

  1. #include "v8.h"
  2. #include "erl_nif.h"
  3. #include <pthread.h>
  4. #include <iostream>
  5. #include <cstring>
  6. #include <cmath>
  7. #include <map>
  8. #include <queue>
  9. #include <zmq.h>
  10. // Debugging
  11. #ifdef ERLV8_DEBUG
  12. #define DEBUG(pid,name,code) SEND(pid, enif_make_tuple3(env, enif_make_atom(env,"DEBUG"), name, code))
  13. #define TRACE printf
  14. #else
  15. #define DEBUG(pid,name,code)
  16. #define TRACE(...)
  17. #endif
  18. // Debugging end
  19. using namespace std;
  20. using namespace __gnu_cxx;
  21. // This should be enough for our tags:
  22. #define MAX_ATOM_LEN 32
  23. class VM; // fwd
  24. typedef struct _vm_res_t {
  25. VM * vm;
  26. } vm_res_t;
  27. typedef struct _val_res_t {
  28. v8::Persistent<v8::Context> ctx;
  29. v8::Persistent<v8::Value> val;
  30. } val_res_t;
  31. typedef struct _term_ref_t {
  32. ErlNifEnv *env;
  33. ERL_NIF_TERM term;
  34. } term_ref_t;
  35. typedef struct _ctx_res_t {
  36. v8::Persistent<v8::Context> ctx;
  37. } ctx_res_t;
  38. // Helpers
  39. #define LHCS(iso, ctx) \
  40. TRACE("(%p) LHCS - 1\n", iso); \
  41. v8::Locker locker(iso); \
  42. TRACE("(%p) LHCS - 2\n", iso); \
  43. v8::Isolate::Scope iscope(iso); \
  44. TRACE("(%p) LHCS - 3\n", iso); \
  45. v8::HandleScope handle_scope; \
  46. TRACE("(%p) LHCS - 4\n", iso); \
  47. v8::Context::Scope context_scope(ctx); \
  48. TRACE("(%p) LHCS - 1\n", iso)
  49. #define SEND(pid, code)\
  50. {\
  51. Send send = Send(pid);\
  52. ErlNifEnv * env = send.env;\
  53. send.send(code);\
  54. }
  55. //
  56. struct cmp_erl_nif_term
  57. {
  58. bool operator()(ERL_NIF_TERM a, ERL_NIF_TERM b)
  59. {
  60. return enif_compare(a,b) < 0;
  61. }
  62. };
  63. // Statics
  64. extern ErlNifResourceType * vm_resource;
  65. extern ErlNifResourceType * val_resource;
  66. extern ErlNifResourceType * ctx_resource;
  67. extern void *zmq_context;
  68. //
  69. struct Tick {
  70. ErlNifEnv * env;
  71. ERL_NIF_TERM tick;
  72. ERL_NIF_TERM ref;
  73. };
  74. // VM
  75. class VM {
  76. public:
  77. v8::Persistent<v8::ObjectTemplate> global_template;
  78. v8::Persistent<v8::ObjectTemplate> external_template;
  79. v8::Persistent<v8::FunctionTemplate> empty_constructor;
  80. v8::Persistent<v8::String> string__erlv8__;
  81. v8::Persistent<v8::Context> context;
  82. v8::Persistent<v8::Object> external_proto_num;
  83. v8::Persistent<v8::Object> external_proto_atom;
  84. v8::Persistent<v8::Object> external_proto_bin;
  85. v8::Persistent<v8::Object> external_proto_ref;
  86. v8::Persistent<v8::Object> external_proto_fun;
  87. v8::Persistent<v8::Object> external_proto_port;
  88. v8::Persistent<v8::Object> external_proto_pid;
  89. v8::Persistent<v8::Object> external_proto_tuple;
  90. v8::Persistent<v8::Object> external_proto_list;
  91. ErlNifPid *server;
  92. ErlNifEnv *env;
  93. ErlNifMutex *mutex;
  94. void * push_socket;
  95. void * ticker_push_socket;
  96. void * pull_socket;
  97. queue<Tick> pop_ticks;
  98. ErlNifTid tid;
  99. vm_res_t * resource;
  100. map<ERL_NIF_TERM, v8::Handle<v8::FunctionTemplate>, cmp_erl_nif_term> fun_map;
  101. map<ERL_NIF_TERM, v8::Handle<v8::Object>, cmp_erl_nif_term> extern_map;
  102. VM();
  103. ~VM();
  104. void run();
  105. void terminate();
  106. v8::Handle<v8::Value> ticker(ERL_NIF_TERM ref);
  107. v8::Isolate* isolate;
  108. };
  109. enum TickHandlerResolutionType { DONE, RETURN, NEXT };
  110. typedef struct {
  111. v8::Handle<v8::Value> value;
  112. TickHandlerResolutionType type;
  113. } TickHandlerResolution;
  114. #define TickHandler(name) extern TickHandlerResolution name(VM * vm, char * tick_name, ERL_NIF_TERM tick, ERL_NIF_TERM tick_ref, ERL_NIF_TERM ref, int arity, const ERL_NIF_TERM * array)
  115. TickHandler(StopTickHandler);
  116. TickHandler(ResultTickHandler);
  117. TickHandler(CallTickHandler);
  118. TickHandler(InstantiateTickHandler);
  119. TickHandler(DeleteTickHandler);
  120. TickHandler(TaintTickHandler);
  121. TickHandler(EqualsTickHandler);
  122. TickHandler(StrictEqualsTickHandler);
  123. TickHandler(GetTickHandler);
  124. TickHandler(GetProtoTickHandler);
  125. TickHandler(GetHiddenTickHandler);
  126. TickHandler(SetTickHandler);
  127. TickHandler(SetProtoTickHandler);
  128. TickHandler(SetHiddenTickHandler);
  129. TickHandler(SetAccessorTickHandler);
  130. TickHandler(ProplistTickHandler);
  131. TickHandler(ListTickHandler);
  132. TickHandler(ScriptTickHandler);
  133. TickHandler(GCTickHandler);
  134. TickHandler(TerminateTickHandler);
  135. TickHandler(ToStringTickHandler);
  136. TickHandler(ToDetailStringTickHandler);
  137. TickHandler(ExternProtoTickHandler);
  138. TickHandler(ExternalizeTickHandler);
  139. TickHandler(UnknownTickHandler);
  140. TickHandler(InternalCountTickHandler);
  141. TickHandler(SetInternalTickHandler);
  142. TickHandler(GetInternalTickHandler);
  143. class Send {
  144. public:
  145. ErlNifPid * pid;
  146. ErlNifEnv * env;
  147. Send(ErlNifPid *a_pid) : pid(a_pid) {
  148. env = enif_alloc_env();
  149. };
  150. ~Send() {
  151. enif_free_env(env);
  152. };
  153. void send(ERL_NIF_TERM term) {
  154. enif_send(NULL, pid, env, term);
  155. enif_clear_env(env);
  156. };
  157. };
  158. #define __ERLV8__(O) v8::Local<v8::External>::Cast(O->GetHiddenValue(v8::String::New("__erlv8__")))->Value()
  159. v8::Handle<v8::Value> term_to_js(v8::Handle<v8::Context> ctx, v8::Isolate* isolate, ErlNifEnv *env, ERL_NIF_TERM term);
  160. ERL_NIF_TERM js_to_term(v8::Handle<v8::Context> ctx, v8::Isolate* isolate, ErlNifEnv *env, v8::Handle<v8::Value> val);
  161. ERL_NIF_TERM external_to_term(v8::Handle<v8::Value> val);
  162. v8::Handle<v8::Value> term_to_external(ERL_NIF_TERM term);
  163. v8::PropertyAttribute term_to_property_attribute(ErlNifEnv * env, ERL_NIF_TERM term);
  164. int enif_is_proplist(ErlNifEnv * env, ERL_NIF_TERM term);
  165. v8::PropertyAttribute term_to_property_attribute(ErlNifEnv * env, ERL_NIF_TERM term);
  166. v8::Handle<v8::Value> term_to_external(ERL_NIF_TERM term);
  167. ERL_NIF_TERM external_to_term(v8::Handle<v8::Value> val);
  168. v8::Handle<v8::Object> externalize_term(map<ERL_NIF_TERM, v8::Handle<v8::Object>, cmp_erl_nif_term> cache, v8::Handle<v8::Object> proto, ERL_NIF_TERM term);
  169. v8::Handle<v8::Value> term_to_js(ErlNifEnv *env, v8::Isolate* isolat, ERL_NIF_TERM term);
  170. ERL_NIF_TERM js_to_term(ErlNifEnv *env, v8::Isolate* isolat, v8::Handle<v8::Value> val);
  171. v8::Handle<v8::Value> WrapFun(const v8::Arguments &arguments);
  172. v8::Handle<v8::Value> EmptyFun(const v8::Arguments &arguments);
  173. v8::Handle<v8::Object> extern_name_to_proto(VM * vm, char *name);