1 /*
2    +----------------------------------------------------------------------+
3    | PHP Version 5                                                        |
4    +----------------------------------------------------------------------+
5    | Copyright (c) 1997-2021 The PHP Group                                |
6    +----------------------------------------------------------------------+
7    | This source file is subject to version 3.01 of the PHP license,      |
8    | that is bundled with this package in the file LICENSE, and is        |
9    | available through the world-wide-web at the following url:           |
10    | http://www.php.net/license/3_01.txt                                  |
11    | If you did not receive a copy of the PHP license and are unable to   |
12    | obtain it through the world-wide-web, please send a note to          |
13    | license@php.net so we can mail you a copy immediately.               |
14    +----------------------------------------------------------------------+
15    | Author: Ruslan Osmanov <osmanov@php.net>                             |
16    +----------------------------------------------------------------------+
17 */
18 
19 /* {{{ php_ev_loop_object_ctor
20  * Creates an instance of EvLoop class and puts it in retval
21  * in_ctor: whether called from constructor of a loop class
22  * default_loop: whether to return/create the default loop */
php_ev_loop_object_ctor(INTERNAL_FUNCTION_PARAMETERS,const zend_bool in_ctor,const zend_bool is_default_loop)23 static void php_ev_loop_object_ctor(INTERNAL_FUNCTION_PARAMETERS, const zend_bool in_ctor, const zend_bool is_default_loop)
24 {
25 	php_ev_object          *ev_obj;
26 	ev_loop                *loop;
27 	zval                  **default_loop_ptr_ptr     = NULL;
28 
29 	long                    flags                    = EVFLAG_AUTO;
30 	double                  io_collect_interval      = 0.;
31 	double                  timeout_collect_interval = 0.;
32 	zval                   *data                     = NULL;
33 
34 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|lz!dd",
35 				&flags, &data,
36 				&io_collect_interval, &timeout_collect_interval) == FAILURE) {
37 		return;
38 	}
39 
40 	default_loop_ptr_ptr = &MyG(default_loop);
41 
42 	if (!in_ctor) {
43 		/* Factory method mode */
44 		if (is_default_loop) {
45 			if (!*default_loop_ptr_ptr) {
46 				loop = ev_default_loop(flags);
47 			} else {
48 				RETURN_ZVAL(*default_loop_ptr_ptr, /* copy */ 1, /* dtor*/ 0);
49 			}
50 		} else {
51 			loop = ev_loop_new(flags);
52 		}
53 
54 		if (!loop) {
55 			php_error_docref(NULL TSRMLS_CC, E_ERROR,
56 					"Failed to instanciate default loop, "
57 					"bad $LIBEV_FLAGS in environment?");
58 			return;
59 		}
60 
61 		PHP_EV_INIT_CLASS_OBJECT(return_value, ev_loop_class_entry_ptr);
62 
63 		ev_obj = (php_ev_object *) zend_object_store_get_object(return_value TSRMLS_CC);
64 
65 		/* Save return_value in MyG(default_loop) */
66 		if (is_default_loop && !*default_loop_ptr_ptr) {
67 			ALLOC_INIT_ZVAL(*default_loop_ptr_ptr);
68 			REPLACE_ZVAL_VALUE(default_loop_ptr_ptr, return_value, 1);
69 		}
70 	} else {
71 		/* Create custom event loop(OOP API) */
72 		loop = ev_loop_new(flags);
73 		if (!loop) {
74 			php_error_docref(NULL TSRMLS_CC, E_ERROR,
75 					"Failed to instanciate loop, bad backend, "
76 					"or bad $LIBEV_FLAGS in environment?");
77 			return;
78 		}
79 
80 		ev_obj = (php_ev_object *) zend_object_store_get_object(getThis() TSRMLS_CC);
81 	}
82 
83 	php_ev_loop *ptr = (php_ev_loop *) emalloc(sizeof(php_ev_loop));
84 	memset(ptr, 0, sizeof(php_ev_loop));
85 	ptr->loop = loop;
86 
87 	if (data) {
88 		Z_ADDREF_P(data);
89 	}
90 	ptr->data                     = data;
91 	ptr->io_collect_interval      = io_collect_interval;
92 	ptr->timeout_collect_interval = timeout_collect_interval;
93 	ev_obj->ptr                   = (void *) ptr;
94 
95 	ev_set_userdata(loop, (void *) (in_ctor ? getThis() : return_value));
96 }
97 /* }}} */
98 
99 /* {{{ proto EvLoop EvLoop::defaultLoop([int flags = Ev::FLAG_AUTO[, mixed data = NULL[, double io_interval = 0.[, double timeout_interval = 0.]]]])
100 */
PHP_METHOD(EvLoop,defaultLoop)101 PHP_METHOD(EvLoop, defaultLoop)
102 {
103 	php_ev_loop_object_ctor(INTERNAL_FUNCTION_PARAM_PASSTHRU,
104 			/* in ctor */FALSE, /* is_default_loop */TRUE);
105 }
106 /* }}} */
107 
108 /* {{{ proto EvLoop EvLoop::__construct([int flags = Ev::FLAG_AUTO[[, mixed data = NULL[, double io_interval = 0.[, double timeout_interval = 0.]]]]) */
PHP_METHOD(EvLoop,__construct)109 PHP_METHOD(EvLoop, __construct)
110 {
111 	php_ev_loop_object_ctor(INTERNAL_FUNCTION_PARAM_PASSTHRU,
112 			/* in ctor */TRUE, /* is_default_loop */FALSE);
113 }
114 /* }}} */
115 
116 
117 #define PHP_EV_LOOP_METHOD_VOID(name, evname)          \
118     PHP_METHOD(EvLoop, name)                           \
119     {                                                  \
120         PHP_EV_LOOP_FETCH_FROM_THIS;                   \
121                                                        \
122         if (zend_parse_parameters_none() == FAILURE) { \
123             return;                                    \
124         }                                              \
125                                                        \
126         ev_ ## evname(EV_A);                           \
127     }
128 
129 #define PHP_EV_LOOP_METHOD_INT_VOID(name, evname)      \
130     PHP_METHOD(EvLoop, name)                           \
131     {                                                  \
132         PHP_EV_LOOP_FETCH_FROM_THIS;                   \
133                                                        \
134         if (zend_parse_parameters_none() == FAILURE) { \
135             return;                                    \
136         }                                              \
137                                                        \
138         RETURN_LONG(ev_ ## evname(EV_A));              \
139     }
140 
PHP_EV_LOOP_METHOD_VOID(loopFork,loop_fork)141 PHP_EV_LOOP_METHOD_VOID(loopFork, loop_fork)
142 PHP_EV_LOOP_METHOD_VOID(verify, verify)
143 PHP_EV_LOOP_METHOD_VOID(invokePending, invoke_pending)
144 PHP_EV_LOOP_METHOD_VOID(nowUpdate, now_update)
145 PHP_EV_LOOP_METHOD_VOID(suspend, suspend)
146 PHP_EV_LOOP_METHOD_VOID(resume, resume)
147 PHP_EV_LOOP_METHOD_INT_VOID(backend, backend)
148 
149 /* {{{ proto double EvLoop::now(void) */
150 PHP_METHOD(EvLoop, now)
151 {
152 	PHP_EV_LOOP_FETCH_FROM_THIS;
153 
154 	if (zend_parse_parameters_none() == FAILURE) {
155 		return;
156 	}
157 
158 	RETURN_DOUBLE((double)ev_now(EV_A));
159 }
160 /* }}} */
161 
162 /* {{{ proto void EvLoop::run([int flags = 0]) */
PHP_METHOD(EvLoop,run)163 PHP_METHOD(EvLoop, run)
164 {
165 	PHP_EV_LOOP_FETCH_FROM_THIS;
166 
167 	long flags = 0;
168 
169 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &flags) == FAILURE) {
170 		return;
171 	}
172 
173 	ev_run(EV_A_ flags);
174 }
175 /* }}} */
176 
177 /* {{{ proto void EvLoop::stop([int how = 0]) */
PHP_METHOD(EvLoop,stop)178 PHP_METHOD(EvLoop, stop)
179 {
180 	PHP_EV_LOOP_FETCH_FROM_THIS;
181 
182 	long how = EVBREAK_ONE;
183 
184 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &how) == FAILURE) {
185 		return;
186 	}
187 
188 	ev_break(EV_A_ how);
189 }
190 /* }}} */
191 
192 /* {{{ proto EvIo EvLoop::io(mixed fd, int events, callable callback[, mixed data = NULL[, int priority = 0]]) */
PHP_METHOD(EvLoop,io)193 PHP_METHOD(EvLoop, io)
194 {
195 	PHP_EV_WATCHER_FACTORY(io, getThis());
196 }
197 /* }}} */
198 
199 /* {{{ proto EvTimer EvLoop::timer(double after, double repeat, EvLoop loop, callable callback[, mixed data = NULL[, int priority = 0]]) */
PHP_METHOD(EvLoop,timer)200 PHP_METHOD(EvLoop, timer)
201 {
202 	PHP_EV_WATCHER_FACTORY(timer, getThis());
203 }
204 /* }}} */
205 
206 #if EV_PERIODIC_ENABLE
207 /* {{{ proto EvPeriodic EvLoop::periodic(double offset, double interval, callable reschedule_cb, callable callback[, mixed data = NULL[, int priority = 0]]) */
PHP_METHOD(EvLoop,periodic)208 PHP_METHOD(EvLoop, periodic)
209 {
210 	PHP_EV_WATCHER_FACTORY(periodic, getThis());
211 }
212 /* }}} */
213 #endif
214 
215 #if EV_SIGNAL_ENABLE
216 /* {{{ proto EvSignal EvLoop::signal(int signum, callable callback[, mixed data = NULL[, int priority = 0]]) */
PHP_METHOD(EvLoop,signal)217 PHP_METHOD(EvLoop, signal)
218 {
219 	PHP_EV_WATCHER_FACTORY(signal, getThis());
220 }
221 /* }}} */
222 #endif
223 
224 #if EV_CHILD_ENABLE
225 /* {{{ proto EvChild EvLoop::child(int pid, bool trace, callable callback[, mixed data = NULL[, int priority = 0]]) */
PHP_METHOD(EvLoop,child)226 PHP_METHOD(EvLoop, child)
227 {
228 	PHP_EV_WATCHER_FACTORY(child, getThis());
229 }
230 /* }}} */
231 #endif
232 
233 #if EV_STAT_ENABLE
234 /* {{{ proto EvStat EvLoop::stat(string path, double interval, callable callback[, mixed data = NULL[, int priority = 0]]) */
PHP_METHOD(EvLoop,stat)235 PHP_METHOD(EvLoop, stat)
236 {
237 	PHP_EV_WATCHER_FACTORY(stat, getThis());
238 }
239 /* }}} */
240 #endif
241 
242 #if EV_IDLE_ENABLE
243 /* {{{ proto EvIdle EvLoop::idle(callable callback[, mixed data = NULL[, int priority = 0]]) */
PHP_METHOD(EvLoop,idle)244 PHP_METHOD(EvLoop, idle)
245 {
246 	PHP_EV_WATCHER_FACTORY(idle, getThis());
247 }
248 /* }}} */
249 #endif
250 
251 #if EV_CHECK_ENABLE
252 /* {{{ proto EvCheck EvLoop::check() */
PHP_METHOD(EvLoop,check)253 PHP_METHOD(EvLoop, check)
254 {
255 	PHP_EV_WATCHER_FACTORY(check, getThis());
256 }
257 /* }}} */
258 #endif
259 
260 #if EV_PREPARE_ENABLE
261 /* {{{ proto EvPrepare EvLoop::prepare() */
PHP_METHOD(EvLoop,prepare)262 PHP_METHOD(EvLoop, prepare)
263 {
264 	PHP_EV_WATCHER_FACTORY(prepare, getThis());
265 }
266 /* }}} */
267 #endif
268 
269 #if EV_EMBED_ENABLE
270 /* {{{ proto EvEmbed EvLoop::embed() */
PHP_METHOD(EvLoop,embed)271 PHP_METHOD(EvLoop, embed)
272 {
273 	PHP_EV_WATCHER_FACTORY(embed, getThis());
274 }
275 /* }}} */
276 #endif
277 
278 #if EV_FORK_ENABLE
279 /* {{{ proto EvFork EvLoop::fork() */
PHP_METHOD(EvLoop,fork)280 PHP_METHOD(EvLoop, fork)
281 {
282 	PHP_EV_WATCHER_FACTORY(fork, getThis());
283 }
284 /* }}} */
285 #endif
286 
287 /*
288  * Local variables:
289  * tab-width: 4
290  * c-basic-offset: 4
291  * End:
292  * vim600: noet sw=4 ts=4 sts=4 fdm=marker
293  * vim<600: noet sw=4 ts=4 sts=4
294  */
295