Print this page
joyent/v8plus#7 v8plus should not hold the event loop open forever
Split |
Close |
Expand all |
Collapse all |
--- old/./v8plus_glue.h
+++ new/./v8plus_glue.h
1 1 /*
2 2 * Copyright (c) 2012 Joyent, Inc. All rights reserved.
3 3 */
4 4
5 5 #ifndef _V8PLUS_GLUE_H
6 6 #define _V8PLUS_GLUE_H
7 7
8 8 #include <stdarg.h>
9 9 #include <libnvpair.h>
10 10 #include "v8plus_errno.h"
11 11
12 12 #ifdef __cplusplus
13 13 extern "C" {
14 14 #endif /* __cplusplus */
15 15
16 16 #define __UNUSED __attribute__((__unused__))
17 17
18 18 #define V8PLUS_ARG_F_NOEXTRA 0x01
19 19
20 20 #define V8PLUS_ERRMSG_LEN 512
21 21 #define V8PLUS_JSF_COOKIE ".__v8plus_jsfunc_cookie"
22 22
23 23 typedef enum v8plus_type {
24 24 V8PLUS_TYPE_NONE = 0, /* N/A */
25 25 V8PLUS_TYPE_STRING, /* char * */
26 26 V8PLUS_TYPE_NUMBER, /* double */
27 27 V8PLUS_TYPE_BOOLEAN, /* boolean_t */
28 28 V8PLUS_TYPE_JSFUNC, /* v8plus_jsfunc_t */
29 29 V8PLUS_TYPE_OBJECT, /* nvlist_t * */
30 30 V8PLUS_TYPE_NULL, /* -- */
31 31 V8PLUS_TYPE_UNDEFINED, /* -- */
32 32 V8PLUS_TYPE_INVALID, /* data_type_t */
33 33 V8PLUS_TYPE_ANY, /* nvpair_t * */
34 34 V8PLUS_TYPE_STRNUMBER64, /* uint64_t */
35 35 V8PLUS_TYPE_INL_OBJECT /* ... */
36 36 } v8plus_type_t;
37 37
38 38 typedef uint64_t v8plus_jsfunc_t;
39 39
40 40 /*
41 41 * C constructor, destructor, and method prototypes. See README.md.
42 42 */
43 43 typedef nvlist_t *(*v8plus_c_ctor_f)(const nvlist_t *, void **);
44 44 typedef nvlist_t *(*v8plus_c_static_f)(const nvlist_t *);
45 45 typedef nvlist_t *(*v8plus_c_method_f)(void *, const nvlist_t *);
46 46 typedef void (*v8plus_c_dtor_f)(void *);
47 47
48 48 typedef struct v8plus_method_descr {
49 49 const char *md_name;
50 50 v8plus_c_method_f md_c_func;
51 51 } v8plus_method_descr_t;
52 52
53 53 typedef struct v8plus_static_descr {
54 54 const char *sd_name;
55 55 v8plus_c_static_f sd_c_func;
56 56 } v8plus_static_descr_t;
57 57
58 58 extern __thread v8plus_errno_t _v8plus_errno;
59 59 extern __thread char _v8plus_errmsg[V8PLUS_ERRMSG_LEN];
60 60
61 61 /*
62 62 * Set the errno and message, indicating an error. The code and
63 63 * printf-formatted message, if one is given, will be used in constructing
64 64 * an exception to be thrown in JavaScript if your method later returns NULL
65 65 * or an nvlist with an "err" member.
66 66 */
67 67 extern nvlist_t *v8plus_verror(v8plus_errno_t, const char *, va_list);
68 68 extern nvlist_t *v8plus_error(v8plus_errno_t, const char *, ...);
69 69
70 70 /*
71 71 * Suicide. It's always an option. Try to avoid using this as it's not
72 72 * very nice to kill the entire node process; if at all possible we need
73 73 * to throw a JavaScript exception instead.
74 74 */
75 75 extern void v8plus_panic(const char *, ...) __PRINTFLIKE(1) __NORETURN;
76 76
77 77 /*
78 78 * As above, this convenience function sets the error code and message based
79 79 * on the nvlist-generated error code in its first argument. The second
80 80 * argument, which may be NULL, should contain the name of the member on
81 81 * which the error occurred.
82 82 */
83 83 extern nvlist_t *v8plus_nverr(int, const char *);
84 84
85 85 /*
86 86 * Similarly, for system errors. Not all possible errno values are handled.
87 87 */
88 88 extern nvlist_t *v8plus_syserr(int, const char *, ...);
89 89
90 90 /*
91 91 * Clear the errno and message. This is needed only when one wishes to return
92 92 * NULL from a C method whose return type is effectively void. The idiom is
93 93 *
94 94 * return (v8plus_void());
95 95 */
96 96 extern nvlist_t *v8plus_void(void);
97 97
98 98 /*
99 99 * Find the named V8 function in the nvlist. Analogous to other lookup
100 100 * routines; see libnvpair(3lib), with an important exception: the
101 101 * nvlist_lookup_v8plus_jsfunc() and nvpair_value_v8plus_jsfunc() functions
102 102 * place a hold on the underlying function object, which must be released by C
103 103 * code when it is no longer needed. See the documentation to understand how
104 104 * this works. The add routine is of very limited utility because there is no
105 105 * mechanism for creating a JS function from C. It can however be used to
106 106 * return a function (or object containing one, etc.) from a deferred
107 107 * completion routine in which a JS function has been invoked that returned
108 108 * such a thing to us.
109 109 */
110 110 extern int nvlist_lookup_v8plus_jsfunc(const nvlist_t *, const char *,
111 111 v8plus_jsfunc_t *);
112 112 extern int nvpair_value_v8plus_jsfunc(const nvpair_t *, v8plus_jsfunc_t *);
113 113 extern void v8plus_jsfunc_hold(v8plus_jsfunc_t);
114 114 extern void v8plus_jsfunc_rele(v8plus_jsfunc_t);
115 115 extern void v8plus_jsfunc_rele_direct(v8plus_jsfunc_t);
116 116
117 117 /*
118 118 * Place or release a hold on the V8 representation of the specified C object.
119 119 * This is rarely necessary; v8plus_defer() performs this action for you, but
120 120 * other asynchronous mechanisms may require it. If you are returning from
121 121 * a method call but have stashed a reference to the object somewhere and are
122 122 * not calling v8plus_defer(), you must call this first. Holds and releases
123 123 * must be balanced. Use of the object within a thread after releasing is a
124 124 * bug.
125 125 */
126 126 extern void v8plus_obj_hold(const void *);
127 127 extern void v8plus_obj_rele(const void *);
128 128 extern void v8plus_obj_rele_direct(const void *);
129 129
130 130 /*
131 131 * Convenience functions for dealing with JS arguments.
132 132 */
133 133 extern v8plus_type_t v8plus_typeof(const nvpair_t *);
134 134 extern int v8plus_args(const nvlist_t *, uint_t, v8plus_type_t t, ...);
135 135 extern nvlist_t *v8plus_obj(v8plus_type_t, ...);
136 136 extern int v8plus_obj_setprops(nvlist_t *, v8plus_type_t, ...);
137 137
138 138 /*
139 139 * Perform a background, possibly blocking and/or expensive, task. First,
140 140 * the worker function will be enqueued for execution on another thread; its
141 141 * first argument is a pointer to the C object on which to operate, and the
142 142 * second is arbitrary per-call context, arguments, etc. defined by the caller.
143 143 * When that worker function has completed execution, the completion function
144 144 * will be invoked in the main thread. Its arguments are the C object, the
145 145 * original context pointer, and the return value from the worker function.
146 146 * See the documentation for a typical use case.
147 147 */
148 148 typedef void *(*v8plus_worker_f)(void *, void *);
149 149 typedef void (*v8plus_completion_f)(void *, void *, void *);
150 150
151 151 extern void v8plus_defer(void *, void *, v8plus_worker_f, v8plus_completion_f);
152 152
153 153 /*
154 154 * Call an opaque JavaScript function from C. The caller is responsible for
155 155 * freeing the returned list. The first argument is not const because it is
156 156 * possible for the JS code to modify the function represented by the cookie.
157 157 */
158 158 extern nvlist_t *v8plus_call(v8plus_jsfunc_t, const nvlist_t *);
159 159 extern nvlist_t *v8plus_call_direct(v8plus_jsfunc_t, const nvlist_t *);
160 160
161 161 /*
162 162 * Call the named JavaScript function in the context of the JS object
163 163 * represented by the native object. Calling and return conventions are the
164 164 * same as for the C interfaces; i.e., the nvlist will be converted into JS
165 165 * objects and the return value or exception will be in the "res" or "err"
166 166 * members of the nvlist that is returned, respectively. If an internal
167 167 * error occurs, NULL is returned and _v8plus_errno set accordingly. The
168 168 * results of calling a method implemented in C via this interface are
169 169 * undefined.
170 170 *
171 171 * These methods can be used in concert with JS code to emit events
172 172 * asynchronously; see the documentation.
173 173 *
174 174 * Note: As JavaScript functions must be called from the event loop thread,
175 175 * v8plus_method_call() contains logic to determine whether we are in the
176 176 * correct context or not. If we are running on some other thread we will
↓ open down ↓ |
176 lines elided |
↑ open up ↑ |
177 177 * queue the request and sleep, waiting for the event loop thread to make the
178 178 * call. In the simple case, where we are already in the correct thread,
179 179 * we make the call directly. v8plus_method_call_direct() assumes we are
180 180 * on the correct thread and always makes the call directly.
181 181 */
182 182 extern nvlist_t *v8plus_method_call(void *, const char *, const nvlist_t *);
183 183 extern nvlist_t *v8plus_method_call_direct(void *, const char *,
184 184 const nvlist_t *);
185 185
186 186 /*
187 + * These functions allow the consumer to hold the V8 event loop open for
188 + * potential input from other threads. If your process blocks in another
189 + * thread, e.g. an event subscription thread, you must signal to v8plus
190 + * that the event loop should remain active. Calls to v8plus_eventloop_hold()
191 + * and v8plus_eventloop_rele() should be balanced. It is safe to call
192 + * v8plus_eventloop_rele() from outside the event loop thread.
193 + *
194 + * Note: Holds obtained via v8plus_obj_hold() and v8plus_jsfunc_hold() will
195 + * also automatically hold the event loop, removing the need to use this
196 + * interface explicitly.
197 + */
198 +extern void v8plus_eventloop_hold(void);
199 +extern void v8plus_eventloop_rele(void);
200 +extern void v8plus_eventloop_rele_direct(void);
201 +
202 +/*
187 203 * These methods are analogous to strerror(3c) and similar functions; they
188 204 * translate among error names, codes, and default messages. There is
189 205 * normally little need for these functions in C methods, as everything
190 206 * necessary to construct a JavaScript exception is done by v8+, but these
191 207 * may be useful in the construction of supplementary exception decorations
192 208 * for debugging purposes.
193 209 */
194 210 extern const char *v8plus_strerror(v8plus_errno_t);
195 211 extern const char *v8plus_errname(v8plus_errno_t);
196 212 extern const char *v8plus_excptype(v8plus_errno_t);
197 213
198 214 /*
199 215 * Provided by C code. See README.md.
200 216 */
201 217 extern const v8plus_c_ctor_f v8plus_ctor;
202 218 extern const v8plus_c_dtor_f v8plus_dtor;
203 219 extern const char *v8plus_js_factory_name;
204 220 extern const char *v8plus_js_class_name;
205 221 extern const v8plus_method_descr_t v8plus_methods[];
206 222 extern const uint_t v8plus_method_count;
207 223 extern const v8plus_static_descr_t v8plus_static_methods[];
208 224 extern const uint_t v8plus_static_method_count;
209 225
210 226 /*
211 227 * Private methods.
212 228 */
213 229 extern boolean_t v8plus_in_event_thread(void);
214 230 extern void v8plus_crossthread_init(void);
215 231
216 232 #ifdef __cplusplus
217 233 }
218 234 #endif /* __cplusplus */
219 235
220 236 #endif /* _V8PLUS_GLUE_H */
↓ open down ↓ |
24 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX