• Home
  • History
  • Annotate
Name Date Size #Lines LOC

..03-May-2022-

libev/H03-May-2022-9,4946,658

php5/H03-May-2022-6,1673,879

php7/H03-May-2022-5,9203,853

php8/H03-May-2022-6,0584,057

tests/H03-May-2022-1,126969

CREDITSH A D17-Sep-202138 43

INSTALL.mdH A D17-Sep-20211.2 KiB6133

LICENSEH A D17-Sep-20213.1 KiB7055

README.mdH A D17-Sep-202110 KiB438332

TODO.mdH A D17-Sep-2021841 2917

config.m4H A D17-Sep-20214.1 KiB11799

config.w32H A D17-Sep-20211.6 KiB4336

README.md

1ev PECL extension
2
3DESCRIPTION
4===========
5
6ev is a PECL extension providing interface to libev library - high performance
7full-featured event loop written in C.
8
9
10ABOUT LIBEV
11-----------
12
13Libev is an event loop: you register interest in certain events (such as a file
14descriptor being readable or a timeout occurring), and it will manage these
15event sources and provide your program with events.
16
17To do this, it must take more or less complete control over your process (or
18thread) by executing the event loop handler, and will then communicate events
19via a callback mechanism.
20
21You register interest in certain events by registering so-called event watchers,
22and then hand it over to libev by starting the watcher.
23
24For details refer to the libev's homepage:
25<http://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#EMBEDDING>
26
27For installation instructions see file named INSTALL.
28
29
30LIBEV IS EMBEDDED
31-----------------
32
33You don't need to install libev separately, since it is embedded into this
34extension.
35
36
37PORTABILITY
38-----------
39
40Currently GNU/Linux platforms supported only. But likely will work on others
41too.
42
43
44EXAMPLES
45========
46
47SIMPLE TIMERS
48-------------
49
50	<?php
51	// Create and start timer firing after 2 seconds
52	$w1 = new EvTimer(2, 0, function () {
53		echo "2 seconds elapsed\n";
54	});
55
56	// Create and launch timer firing after 2 seconds repeating each second
57	// until we manually stop it
58	$w2 = new EvTimer(2, 1, function ($w) {
59		echo "is called every second, is launched after 2 seconds\n";
60		echo "iteration = ", Ev::iteration(), PHP_EOL;
61
62		// Stop the watcher after 5 iterations
63		Ev::iteration() == 5 and $w->stop();
64		// Stop the watcher if further calls cause more than 10 iterations
65		Ev::iteration() >= 10 and $w->stop();
66	});
67
68	// Create stopped timer. It will be inactive until we start it ourselves
69	$w_stopped = EvTimer::createStopped(10, 5, function($w) {
70		echo "Callback of a timer created as stopped\n";
71
72		// Stop the watcher after 2 iterations
73		Ev::iteration() >= 2 and $w->stop();
74	});
75
76	// Loop until Ev::stop() is called or all of watchers stop
77	Ev::run();
78
79	// Start and look if it works
80	$w_stopped->start();
81	echo "Run single iteration\n";
82	Ev::run(Ev::RUN_ONCE);
83
84	echo "Restart the second watcher and try to handle the same events, but don't block\n";
85	$w2->again();
86	Ev::run(Ev::RUN_NOWAIT);
87
88	$w = new EvTimer(10, 0, function() {});
89	echo "Running a blocking loop\n";
90	Ev::run();
91	echo "END\n";
92	?>
93
94*Output*
95
96	2 seconds elapsed
97	is called every second, is launched after 2 seconds
98	iteration = 1
99	is called every second, is launched after 2 seconds
100	iteration = 2
101	is called every second, is launched after 2 seconds
102	iteration = 3
103	is called every second, is launched after 2 seconds
104	iteration = 4
105	is called every second, is launched after 2 seconds
106	iteration = 5
107	Run single iteration
108	Callback of a timer created as stopped
109	Restart the second watcher and try to handle the same events, but don't block
110	Running a blocking loop
111	is called every second, is launched after 2 seconds
112	iteration = 8
113	is called every second, is launched after 2 seconds
114	iteration = 9
115	is called every second, is launched after 2 seconds
116	iteration = 10
117	END
118
119PERIODIC TIMERS
120---------------
121
122*Example 1*
123
124	<?php
125	// Tick each 10.5 seconds
126	$w = new EvPeriodic(0., 10.5, NULL, function ($w, $revents) {
127		echo time(), PHP_EOL;
128	});
129	Ev::run();
130	?>
131
132*Example 2*
133
134	<?php
135	// Tick each 10.5 seconds. Use reschedule callback
136
137	function reschedule_cb ($watcher, $now) {
138		return $now + (10.5. - fmod($now, 10.5));
139
140	}
141
142	$w = new EvPeriodic(0., 0., "reschedule_cb", function ($w, $revents) {
143		echo time(), PHP_EOL;
144	});
145	Ev::run();
146	?>
147
148*Example 3*
149
150	<?php
151	// Tick every 10.5 seconds starting at now
152	$w = new EvPeriodic(fmod(Ev::now(), 10.5), 10.5, NULL, function ($w, $revents) {
153		echo time(), PHP_EOL;
154	});
155	Ev::run();
156	?>
157
158I/O EVENTS
159----------
160
161*Example 1*
162
163	<?php
164	// Wait until STDIN is readable
165	$w = new EvIo(STDIN, Ev::READ, function ($watcher, $revents) {
166		echo "STDIN is readable\n";
167	});
168	Ev::run(Ev::RUN_ONCE);
169	?>
170
171*Example 2*
172
173	<?php
174	/* Use some async I/O to access a socket */
175
176	// `sockets' extension still logs warnings
177	// for EINPROGRESS, EAGAIN/EWOULDBLOCK etc.
178	error_reporting(E_ERROR);
179
180	$e_nonblocking = array (/*EAGAIN or EWOULDBLOCK*/11, /*EINPROGRESS*/115);
181
182	// Get the port for the WWW service
183	$service_port = getservbyname('www', 'tcp');
184
185	// Get the IP address for the target host
186	$address = gethostbyname('google.co.uk');
187
188	// Create a TCP/IP socket
189	$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
190	if ($socket === FALSE) {
191    	echo "socket_create() failed: reason: "
192			.socket_strerror(socket_last_error()) . "\n";
193	}
194
195	// Set O_NONBLOCK flag
196	socket_set_nonblock($socket);
197
198	// Abort on timeout
199	$timeout_watcher = new EvTimer(10.0, 0., function () use ($socket) {
200		socket_close($socket);
201		Ev::stop(Ev::BREAK_ALL);
202	});
203
204	// Make HEAD request when the socket is writable
205	$write_watcher = new EvIo($socket, Ev::WRITE, function ($w)
206		use ($socket, $timeout_watcher, $e_nonblocking) {
207		// Stop timeout watcher
208		$timeout_watcher->stop();
209		// Stop write watcher
210		$w->stop();
211
212		$in = "HEAD / HTTP/1.1\r\n";
213		$in .= "Host: google.co.uk\r\n";
214		$in .= "Connection: Close\r\n\r\n";
215
216		if (!socket_write($socket, $in, strlen($in))) {
217			trigger_error("Failed writing $in to socket", E_USER_ERROR);
218		}
219
220		$read_watcher = new EvIo($socket, Ev::READ, function ($w, $re)
221			use ($socket, $e_nonblocking) {
222			// Socket is readable. recv() 20 bytes using non-blocking mode
223			$ret = socket_recv($socket, $out, 20, MSG_DONTWAIT);
224
225			if ($ret) {
226    			echo $out;
227			} elseif ($ret === 0) {
228				// All read
229				$w->stop();
230				socket_close($socket);
231				return;
232			}
233
234			// Caught EINPROGRESS, EAGAIN, or EWOULDBLOCK
235			if (in_array(socket_last_error(), $e_nonblocking)) {
236				return;
237			}
238
239			$w->stop();
240			socket_close($socket);
241		});
242
243		Ev::run();
244	});
245
246	$result = socket_connect($socket, $address, $service_port);
247
248	Ev::run();
249	?>
250
251Sample output:
252
253	HTTP/1.1 301 Moved Permanently
254	Location: http://www.google.co.uk/
255	Content-Type: text/html; charset=UTF-8
256	Date: Sun, 23 Dec 2012 16:08:27 GMT
257	Expires: Tue, 22 Jan 2012 16:08:27 GMT
258	Cache-Control: public, max-age=2592000
259	Server: gws
260	Content-Length: 221
261	X-XSS-Protection: 1; mode=block
262	X-Frame-Options: SAMEORIGIN
263	Connection: close
264
265
266EMBEDDING ONE LOOP INTO ANOTHER
267-------------------------------
268
269*Example 1*
270
271	<?php
272	/*
273 	 * Try to get an embeddable event loop and embed it into the default event loop.
274 	 * If it is impossible, use the default
275 	 * loop. The default loop is stored in `$loop_hi`, while the embeddable loop is
276 	 * stored in `$loop_lo`(which is `$loop_hi` in the case no embeddable loop can be
277 	 * used).
278 	 *
279 	 * Sample translated to PHP
280 	 * <http://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#Examples_CONTENT-9>
281 	 */
282	$loop_hi = EvLoop::defaultLoop();
283	$loop_lo = NULL;
284	$embed   = NULL;
285
286	/*
287	* See if there is a chance of getting one that works
288	* (flags' value of 0 means autodetection)
289	*/
290	$loop_lo = Ev::embeddableBackends() & Ev::recommendedBackends()
291    	? new EvLoop(Ev::embeddableBackends() & Ev::recommendedBackends())
292    	: 0;
293
294	if ($loop_lo) {
295		$embed = new EvEmbed($loop_lo, function () {});
296	} else {
297		$loop_lo = $loop_hi;
298	}
299	?>
300
301*Example 2*
302
303	<?php
304	/*
305 	 * Check if kqueue is available but not recommended and create a kqueue backend
306 	 * for use with sockets (which usually work with any kqueue implementation).
307 	 * Store the kqueue/socket-only event loop in `$socket_loop`. (One might optionally
308 	 * use `EVFLAG_NOENV`, too)
309 	 *
310 	 * Example borrowed from
311 	 * <http://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#Examples_CONTENT-9>
312 	 */
313	$loop        = EvLoop::defaultLoop();
314	$socket_loop = NULL;
315	$embed       = NULL;
316
317	if (Ev::supportedBackends() & ~Ev::recommendedBackends() & Ev::BACKEND_KQUEUE) {
318		if (($socket_loop = new EvLoop(Ev::BACKEND_KQUEUE))) {
319			$embed = new EvEmbed($loop);
320		}
321	}
322
323	if (!$socket_loop) {
324		$socket_loop = $loop;
325	}
326
327	// Now use $socket_loop for all sockets, and $loop for anything else
328	?>
329
330SIGNALS
331-------
332
333	<?php
334	// Handle SIGTERM signal
335	$w = new EvSignal(SIGTERM, function ($watcher) {
336		echo "SIGTERM received\n";
337		$watcher->stop();
338	});
339	Ev::run();
340	?>
341
342STAT - FILE STATUS CHANGES
343--------------------------
344
345*Example 1*
346
347	<?php
348	// Monitor changes of /var/log/messages.
349	// Use 10 second update interval.
350	$w = new EvStat("/var/log/messages", 8, function ($w) {
351		echo "/var/log/messages changed\n";
352
353		$attr = $w->attr();
354
355		if ($attr['nlink']) {
356			printf("Current size: %ld\n", $attr['size']);
357			printf("Current atime: %ld\n", $attr['atime']);
358			printf("Current mtime: %ld\n", $attr['mtime']);
359		} else {
360			fprintf(STDERR, "`messages` file is not there!");
361			$w->stop();
362		}
363	});
364
365	Ev::run();
366	?>
367
368*Example 2*
369
370	<?php
371	// Avoid missing updates by means of one second delay
372	$timer = EvTimer::createStopped(0., 1.02, function ($w) {
373		$w->stop();
374
375		$stat = $w->data;
376
377		// 1 second after the most recent change of the file
378		printf("Current size: %ld\n", $stat->attr()['size']);
379	});
380
381	$stat = new EvStat("/var/log/messages", 0., function () use ($timer) {
382		// Reset timer watcher
383		$timer->again();
384	});
385
386	$timer->data = $stat;
387
388	Ev::run();
389	?>
390
391PROCESS STATUS CHANGES
392----------------------
393
394	<?php
395	$pid = pcntl_fork();
396
397	if ($pid == -1) {
398		fprintf(STDERR, "pcntl_fork failed\n");
399	} elseif ($pid) {
400		$w = new EvChild($pid, FALSE, function ($w, $revents) {
401			$w->stop();
402
403			printf("Process %d exited with status %d\n", $w->rpid, $w->rstatus);
404		});
405
406		Ev::run();
407
408		// Protect against Zombies
409		pcntl_wait($status);
410	} else {
411		//Forked child
412		exit(2);
413	}
414	?>
415
416
417AUTHORS
418=======
419
420Ruslan Osmanov <osmanov@php.net>
421
422
423COPYRIGHT
424=========
425
426	Copyright (c) 2012-2019 Ruslan Osmanov <osmanov@php.net>
427
428	This project is subject to version 3.01 of the PHP license, that is bundled
429	with this package in the file LICENSE, and is available through the
430	world-wide-web at the following url: http://www.php.net/license/3_01.txt If you
431	did not receive a copy of the PHP license and are unable to obtain it through
432	the world-wide-web, please send a note to license@php.net so we can mail you a
433	copy immediately.
434
435
436vim: tw=80 ft=markdown
437
438