-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathlibev.mhtml
6932 lines (6573 loc) · 285 KB
/
libev.mhtml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
From: <Saved by Blink>
Snapshot-Content-Location: https://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod
Subject: libev
Date: Thu, 7 Dec 2023 09:59:33 +0530
MIME-Version: 1.0
Content-Type: multipart/related;
type="text/html";
boundary="----MultipartBoundary--lCm896T9QuEV0CLQdSNSjAthU9PAkRB95Q3Cpl1K1P----"
------MultipartBoundary--lCm896T9QuEV0CLQdSNSjAthU9PAkRB95Q3Cpl1K1P----
Content-Type: text/html
Content-ID: <frame-13CA796EBFA6FCF37B009697738CFAE4@mhtml.blink>
Content-Transfer-Encoding: quoted-printable
Content-Location: https://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod
<!--?xml version=3D"1.0" encoding=3D"UTF-8"?--><!DOCTYPE html PUBLIC "-//W3=
C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"><html =
xmlns=3D"http://www.w3.org/1999/xhtml" xml:lang=3D"en"><head><meta http-equ=
iv=3D"Content-Type" content=3D"text/html; charset=3DUTF-8">
<title>libev</title>
<meta name=3D"description" content=3D"Pod documentation for libev">
<meta name=3D"inputfile" content=3D"(unknown)">
<meta name=3D"outputfile" content=3D"(unknown)">
<meta name=3D"created" content=3D"Thu Dec 7 05:27:58 2023">
<meta name=3D"generator" content=3D"Pod::Xhtml 1.61">
<link rel=3D"stylesheet" href=3D"http://res.tst.eu/pod.css"></head>
<body data-new-gr-c-s-check-loaded=3D"14.1143.0" data-gr-ext-installed=3D""=
>
<div class=3D"pod">
<!-- INDEX START -->
<h3 id=3D"TOP">Index</h3>
<ul><li><a href=3D"https://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#NA=
ME">NAME</a></li>
<li><a href=3D"https://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#SYNOPS=
IS">SYNOPSIS</a>
<ul><li><a href=3D"https://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#EX=
AMPLE_PROGRAM">EXAMPLE PROGRAM</a></li>
</ul>
</li>
<li><a href=3D"https://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#ABOUT_=
THIS_DOCUMENT">ABOUT THIS DOCUMENT</a></li>
<li><a href=3D"https://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#WHAT_T=
O_READ_WHEN_IN_A_HURRY">WHAT TO READ WHEN IN A HURRY</a></li>
<li><a href=3D"https://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#ABOUT_=
LIBEV">ABOUT LIBEV</a>
<ul><li><a href=3D"https://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#FE=
ATURES">FEATURES</a></li>
<li><a href=3D"https://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#CONVEN=
TIONS">CONVENTIONS</a></li>
<li><a href=3D"https://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#TIME_R=
EPRESENTATION">TIME REPRESENTATION</a></li>
</ul>
</li>
<li><a href=3D"https://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#ERROR_=
HANDLING">ERROR HANDLING</a></li>
<li><a href=3D"https://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#GLOBAL=
_FUNCTIONS">GLOBAL FUNCTIONS</a></li>
<li><a href=3D"https://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#FUNCTI=
ONS_CONTROLLING_EVENT_LOOPS">FUNCTIONS CONTROLLING EVENT LOOPS</a></li>
<li><a href=3D"https://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#ANATOM=
Y_OF_A_WATCHER">ANATOMY OF A WATCHER</a>
<ul><li><a href=3D"https://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#GE=
NERIC_WATCHER_FUNCTIONS">GENERIC WATCHER FUNCTIONS</a></li>
<li><a href=3D"https://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#WATCHE=
R_STATES">WATCHER STATES</a></li>
<li><a href=3D"https://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#WATCHE=
R_PRIORITY_MODELS">WATCHER PRIORITY MODELS</a></li>
</ul>
</li>
<li><a href=3D"https://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#WATCHE=
R_TYPES">WATCHER TYPES</a>
<ul><li><a href=3D"https://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#co=
de_ev_io_code_is_this_file_descrip"><code>ev_io</code> - is this file descr=
iptor readable or writable?</a>
<ul><li><a href=3D"https://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#Th=
e_special_problem_of_disappearing_">The special problem of disappearing fil=
e descriptors</a></li>
<li><a href=3D"https://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#The_sp=
ecial_problem_of_dup_ed_file_d">The special problem of dup'ed file descript=
ors</a></li>
<li><a href=3D"https://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#The_sp=
ecial_problem_of_files">The special problem of files</a></li>
<li><a href=3D"https://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#The_sp=
ecial_problem_of_fork">The special problem of fork</a></li>
<li><a href=3D"https://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#The_sp=
ecial_problem_of_SIGPIPE">The special problem of SIGPIPE</a></li>
<li><a href=3D"https://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#The_sp=
ecial_problem_of_accept_ing_wh">The special problem of accept()ing when you=
can't</a></li>
<li><a href=3D"https://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#Watche=
r_Specific_Functions">Watcher-Specific Functions</a></li>
<li><a href=3D"https://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#Exampl=
es">Examples</a></li>
</ul>
</li>
<li><a href=3D"https://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#code_e=
v_timer_code_relative_and_opti"><code>ev_timer</code> - relative and option=
ally repeating timeouts</a>
<ul><li><a href=3D"https://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#Be=
_smart_about_timeouts">Be smart about timeouts</a></li>
<li><a href=3D"https://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#The_sp=
ecial_problem_of_being_too_ear">The special problem of being too early</a><=
/li>
<li><a href=3D"https://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#The_sp=
ecial_problem_of_time_updates">The special problem of time updates</a></li>
<li><a href=3D"https://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#The_sp=
ecial_problem_of_unsynchronise">The special problem of unsynchronised clock=
s</a></li>
<li><a href=3D"https://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#The_sp=
ecial_problems_of_suspended_an">The special problems of suspended animation=
</a></li>
<li><a href=3D"https://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#Watche=
r_Specific_Functions_and_Data_">Watcher-Specific Functions and Data Members=
</a></li>
<li><a href=3D"https://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#Exampl=
es-2">Examples</a></li>
</ul>
</li>
<li><a href=3D"https://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#code_e=
v_periodic_code_to_cron_or_not"><code>ev_periodic</code> - to cron or not t=
o cron?</a>
<ul><li><a href=3D"https://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#Wa=
tcher_Specific_Functions_and_Data_-3">Watcher-Specific Functions and Data M=
embers</a></li>
<li><a href=3D"https://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#Exampl=
es-3">Examples</a></li>
</ul>
</li>
<li><a href=3D"https://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#code_e=
v_signal_code_signal_me_when_a"><code>ev_signal</code> - signal me when a s=
ignal gets signalled!</a>
<ul><li><a href=3D"https://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#Th=
e_special_problem_of_inheritance_o">The special problem of inheritance over=
fork/execve/pthread_create</a></li>
<li><a href=3D"https://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#The_sp=
ecial_problem_of_threads_signa">The special problem of threads signal handl=
ing</a></li>
<li><a href=3D"https://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#Watche=
r_Specific_Functions_and_Data_-4">Watcher-Specific Functions and Data Membe=
rs</a></li>
<li><a href=3D"https://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#Exampl=
es-4">Examples</a></li>
</ul>
</li>
<li><a href=3D"https://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#code_e=
v_child_code_watch_out_for_pro"><code>ev_child</code> - watch out for proce=
ss status changes</a>
<ul><li><a href=3D"https://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#Pr=
ocess_Interaction">Process Interaction</a></li>
<li><a href=3D"https://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#Overri=
ding_the_Built_In_Processing">Overriding the Built-In Processing</a></li>
<li><a href=3D"https://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#Stoppi=
ng_the_Child_Watcher">Stopping the Child Watcher</a></li>
<li><a href=3D"https://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#Watche=
r_Specific_Functions_and_Data_-5">Watcher-Specific Functions and Data Membe=
rs</a></li>
<li><a href=3D"https://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#Exampl=
es-5">Examples</a></li>
</ul>
</li>
<li><a href=3D"https://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#code_e=
v_stat_code_did_the_file_attri"><code>ev_stat</code> - did the file attribu=
tes just change?</a>
<ul><li><a href=3D"https://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#AB=
I_Issues_Largefile_Support">ABI Issues (Largefile Support)</a></li>
<li><a href=3D"https://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#Inotif=
y_and_Kqueue">Inotify and Kqueue</a></li>
<li><a href=3D"https://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#code_s=
tat_code_is_a_synchronous_oper"><code>stat ()</code> is a synchronous opera=
tion</a></li>
<li><a href=3D"https://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#The_sp=
ecial_problem_of_stat_time_res">The special problem of stat time resolution=
</a></li>
<li><a href=3D"https://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#Watche=
r_Specific_Functions_and_Data_-6">Watcher-Specific Functions and Data Membe=
rs</a></li>
<li><a href=3D"https://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#Exampl=
es-6">Examples</a></li>
</ul>
</li>
<li><a href=3D"https://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#code_e=
v_idle_code_when_you_ve_got_no"><code>ev_idle</code> - when you've got noth=
ing better to do...</a>
<ul><li><a href=3D"https://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#Ab=
using_an_code_ev_idle_code_watcher">Abusing an <code>ev_idle</code> watcher=
for its side-effect</a></li>
<li><a href=3D"https://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#Watche=
r_Specific_Functions_and_Data_-7">Watcher-Specific Functions and Data Membe=
rs</a></li>
<li><a href=3D"https://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#Exampl=
es-7">Examples</a></li>
</ul>
</li>
<li><a href=3D"https://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#code_e=
v_prepare_code_and_code_ev_che"><code>ev_prepare</code> and <code>ev_check<=
/code> - customise your event loop!</a>
<ul><li><a href=3D"https://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#Ab=
using_an_code_ev_check_code_watche">Abusing an <code>ev_check</code> watche=
r for its side-effect</a></li>
<li><a href=3D"https://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#Watche=
r_Specific_Functions_and_Data_-8">Watcher-Specific Functions and Data Membe=
rs</a></li>
<li><a href=3D"https://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#Exampl=
es-8">Examples</a></li>
</ul>
</li>
<li><a href=3D"https://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#code_e=
v_embed_code_when_one_backend_"><code>ev_embed</code> - when one backend is=
n't enough...</a>
<ul><li><a href=3D"https://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#co=
de_ev_embed_code_and_fork"><code>ev_embed</code> and fork</a></li>
<li><a href=3D"https://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#Watche=
r_Specific_Functions_and_Data_-9">Watcher-Specific Functions and Data Membe=
rs</a></li>
<li><a href=3D"https://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#Exampl=
es-9">Examples</a></li>
</ul>
</li>
<li><a href=3D"https://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#code_e=
v_fork_code_the_audacity_to_re"><code>ev_fork</code> - the audacity to resu=
me the event loop after a fork</a>
<ul><li><a href=3D"https://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#Th=
e_special_problem_of_life_after_fo">The special problem of life after fork =
- how is it possible?</a></li>
<li><a href=3D"https://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#Watche=
r_Specific_Functions_and_Data_-10">Watcher-Specific Functions and Data Memb=
ers</a></li>
</ul>
</li>
<li><a href=3D"https://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#code_e=
v_cleanup_code_even_the_best_t"><code>ev_cleanup</code> - even the best thi=
ngs end</a>
<ul><li><a href=3D"https://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#Wa=
tcher_Specific_Functions_and_Data_-11">Watcher-Specific Functions and Data =
Members</a></li>
</ul>
</li>
<li><a href=3D"https://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#code_e=
v_async_code_how_to_wake_up_an"><code>ev_async</code> - how to wake up an e=
vent loop</a>
<ul><li><a href=3D"https://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#Qu=
eueing">Queueing</a></li>
<li><a href=3D"https://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#Watche=
r_Specific_Functions_and_Data_-12">Watcher-Specific Functions and Data Memb=
ers</a></li>
</ul>
</li>
</ul>
</li>
<li><a href=3D"https://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#OTHER_=
FUNCTIONS">OTHER FUNCTIONS</a></li>
<li><a href=3D"https://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#COMMON=
_OR_USEFUL_IDIOMS_OR_BOTH">COMMON OR USEFUL IDIOMS (OR BOTH)</a>
<ul><li><a href=3D"https://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#AS=
SOCIATING_CUSTOM_DATA_WITH_A_WATCH">ASSOCIATING CUSTOM DATA WITH A WATCHER<=
/a></li>
<li><a href=3D"https://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#BUILDI=
NG_YOUR_OWN_COMPOSITE_WATCHERS">BUILDING YOUR OWN COMPOSITE WATCHERS</a></l=
i>
<li><a href=3D"https://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#AVOIDI=
NG_FINISHING_BEFORE_RETURNING">AVOIDING FINISHING BEFORE RETURNING</a></li>
<li><a href=3D"https://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#MODEL_=
NESTED_EVENT_LOOP_INVOCATIONS_">MODEL/NESTED EVENT LOOP INVOCATIONS AND EXI=
T CONDITIONS</a></li>
<li><a href=3D"https://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#THREAD=
_LOCKING_EXAMPLE">THREAD LOCKING EXAMPLE</a></li>
<li><a href=3D"https://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#THREAD=
S_COROUTINES_CONTINUATIONS_QUE">THREADS, COROUTINES, CONTINUATIONS, QUEUES.=
.. INSTEAD OF CALLBACKS</a></li>
</ul>
</li>
<li><a href=3D"https://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#LIBEVE=
NT_EMULATION">LIBEVENT EMULATION</a></li>
<li><a href=3D"https://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#C_SUPP=
ORT">C++ SUPPORT</a>
<ul><li><a href=3D"https://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#C_=
API">C API</a></li>
<li><a href=3D"https://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#C_API-=
2">C++ API</a></li>
</ul>
</li>
<li><a href=3D"https://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#OTHER_=
LANGUAGE_BINDINGS">OTHER LANGUAGE BINDINGS</a></li>
<li><a href=3D"https://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#MACRO_=
MAGIC">MACRO MAGIC</a></li>
<li><a href=3D"https://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#EMBEDD=
ING">EMBEDDING</a>
<ul><li><a href=3D"https://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#FI=
LESETS">FILESETS</a>
<ul><li><a href=3D"https://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#CO=
RE_EVENT_LOOP">CORE EVENT LOOP</a></li>
<li><a href=3D"https://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#LIBEVE=
NT_COMPATIBILITY_API">LIBEVENT COMPATIBILITY API</a></li>
<li><a href=3D"https://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#AUTOCO=
NF_SUPPORT">AUTOCONF SUPPORT</a></li>
</ul>
</li>
<li><a href=3D"https://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#PREPRO=
CESSOR_SYMBOLS_MACROS">PREPROCESSOR SYMBOLS/MACROS</a></li>
<li><a href=3D"https://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#EXPORT=
ED_API_SYMBOLS">EXPORTED API SYMBOLS</a></li>
<li><a href=3D"https://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#EXAMPL=
ES">EXAMPLES</a></li>
</ul>
</li>
<li><a href=3D"https://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#INTERA=
CTION_WITH_OTHER_PROGRAMS_LIBR">INTERACTION WITH OTHER PROGRAMS, LIBRARIES =
OR THE ENVIRONMENT</a>
<ul><li><a href=3D"https://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#TH=
READS_AND_COROUTINES">THREADS AND COROUTINES</a>
<ul><li><a href=3D"https://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#TH=
READS">THREADS</a></li>
<li><a href=3D"https://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#COROUT=
INES">COROUTINES</a></li>
</ul>
</li>
<li><a href=3D"https://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#COMPIL=
ER_WARNINGS">COMPILER WARNINGS</a></li>
<li><a href=3D"https://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#VALGRI=
ND">VALGRIND</a></li>
</ul>
</li>
<li><a href=3D"https://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#PORTAB=
ILITY_NOTES">PORTABILITY NOTES</a>
<ul><li><a href=3D"https://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#GN=
U_LINUX_32_BIT_LIMITATIONS">GNU/LINUX 32 BIT LIMITATIONS</a></li>
<li><a href=3D"https://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#OS_X_A=
ND_DARWIN_BUGS">OS/X AND DARWIN BUGS</a>
<ul><li><a href=3D"https://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#co=
de_kqueue_code_is_buggy"><code>kqueue</code> is buggy</a></li>
<li><a href=3D"https://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#code_p=
oll_code_is_buggy"><code>poll</code> is buggy</a></li>
<li><a href=3D"https://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#code_s=
elect_code_is_buggy"><code>select</code> is buggy</a></li>
</ul>
</li>
<li><a href=3D"https://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#SOLARI=
S_PROBLEMS_AND_WORKAROUNDS">SOLARIS PROBLEMS AND WORKAROUNDS</a>
<ul><li><a href=3D"https://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#co=
de_errno_code_reentrancy"><code>errno</code> reentrancy</a></li>
<li><a href=3D"https://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#Event_=
port_backend">Event port backend</a></li>
</ul>
</li>
<li><a href=3D"https://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#AIX_PO=
LL_BUG">AIX POLL BUG</a></li>
<li><a href=3D"https://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#WIN32_=
PLATFORM_LIMITATIONS_AND_WORKA">WIN32 PLATFORM LIMITATIONS AND WORKAROUNDS<=
/a>
<ul><li><a href=3D"https://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#Ge=
neral_issues">General issues</a></li>
<li><a href=3D"https://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#The_wi=
nsocket_code_select_code_funct">The winsocket <code>select</code> function<=
/a></li>
<li><a href=3D"https://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#Limite=
d_number_of_file_descriptors">Limited number of file descriptors</a></li>
</ul>
</li>
<li><a href=3D"https://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#PORTAB=
ILITY_REQUIREMENTS">PORTABILITY REQUIREMENTS</a></li>
</ul>
</li>
<li><a href=3D"https://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#ALGORI=
THMIC_COMPLEXITIES">ALGORITHMIC COMPLEXITIES</a></li>
<li><a href=3D"https://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#PORTIN=
G_FROM_LIBEV_3_X_TO_4_X">PORTING FROM LIBEV 3.X TO 4.X</a></li>
<li><a href=3D"https://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#GLOSSA=
RY">GLOSSARY</a></li>
<li><a href=3D"https://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#AUTHOR=
">AUTHOR</a>
</li>
</ul><hr>
<!-- INDEX END -->
<h1 id=3D"NAME">NAME</h1>
<div id=3D"NAME_CONTENT">
<p>libev - a high performance full-featured event loop written in C</p>
</div>
<h1 id=3D"SYNOPSIS">SYNOPSIS</h1>
<div id=3D"SYNOPSIS_CONTENT">
<pre> #include <ev.h>
</pre>
</div>
<h2 id=3D"EXAMPLE_PROGRAM">EXAMPLE PROGRAM</h2>
<div id=3D"EXAMPLE_PROGRAM_CONTENT">
<pre> // a single header file is required
#include <ev.h>
#include <stdio.h> // for puts
// every watcher type has its own typedef'd struct
// with the name ev_TYPE
ev_io stdin_watcher;
ev_timer timeout_watcher;
// all watcher callbacks have a similar signature
// this callback is called when data is readable on stdin
static void
stdin_cb (EV_P_ ev_io *w, int revents)
{
puts ("stdin ready");
// for one-shot events, one must manually stop the watcher
// with its corresponding stop function.
ev_io_stop (EV_A_ w);
// this causes all nested ev_run's to stop iterating
ev_break (EV_A_ EVBREAK_ALL);
}
// another callback, this time for a time-out
static void
timeout_cb (EV_P_ ev_timer *w, int revents)
{
puts ("timeout");
// this causes the innermost ev_run to stop iterating
ev_break (EV_A_ EVBREAK_ONE);
}
int
main (void)
{
// use the default event loop unless you have special needs
struct ev_loop *loop =3D EV_DEFAULT;
// initialise an io watcher, then start it
// this one will watch for stdin to become readable
ev_io_init (&stdin_watcher, stdin_cb, /*STDIN_FILENO*/ 0, EV_READ)=
;
ev_io_start (loop, &stdin_watcher);
// initialise a timer watcher, then start it
// simple non-repeating 5.5 second timeout
ev_timer_init (&timeout_watcher, timeout_cb, 5.5, 0.);
ev_timer_start (loop, &timeout_watcher);
// now wait for events to arrive
ev_run (loop, 0);
// break was called, so exit
return 0;
}
</pre>
</div>
<h1 id=3D"ABOUT_THIS_DOCUMENT">ABOUT THIS DOCUMENT</h1>
<div id=3D"ABOUT_THIS_DOCUMENT_CONTENT">
<p>This document documents the libev software package.</p>
<p>The newest version of this document is also available as an html-formatt=
ed
web page you might find easier to navigate when reading it for the first
time: <a href=3D"http://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod">http=
://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod</a>.</p>
<p>While this document tries to be as complete as possible in documenting
libev, its usage and the rationale behind its design, it is not a tutorial
on event-based programming, nor will it introduce event-based programming
with libev.</p>
<p>Familiarity with event based programming techniques in general is assume=
d
throughout this document.</p>
</div>
<h1 id=3D"WHAT_TO_READ_WHEN_IN_A_HURRY">WHAT TO READ WHEN IN A HURRY</h1>
<div id=3D"WHAT_TO_READ_WHEN_IN_A_HURRY_CONTENT">
<p>This manual tries to be very detailed, but unfortunately, this also make=
s
it very long. If you just want to know the basics of libev, I suggest
reading <a href=3D"https://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#AN=
ATOMY_OF_A_WATCHER">ANATOMY OF A WATCHER</a>, then the <a href=3D"https://p=
od.tst.eu/http://cvs.schmorp.de/libev/ev.pod#EXAMPLE_PROGRAM">EXAMPLE PROGR=
AM</a> above and
look up the missing functions in <a href=3D"https://pod.tst.eu/http://cvs.s=
chmorp.de/libev/ev.pod#GLOBAL_FUNCTIONS">GLOBAL FUNCTIONS</a> and the <code=
>ev_io</code> and
<code>ev_timer</code> sections in <a href=3D"https://pod.tst.eu/http://cvs.=
schmorp.de/libev/ev.pod#WATCHER_TYPES">WATCHER TYPES</a>.</p>
</div>
<h1 id=3D"ABOUT_LIBEV">ABOUT LIBEV</h1>
<div id=3D"ABOUT_LIBEV_CONTENT">
<p>Libev is an event loop: you register interest in certain events (such as=
a
file descriptor being readable or a timeout occurring), and it will manage
these event sources and provide your program with events.</p>
<p>To do this, it must take more or less complete control over your process
(or thread) by executing the <i>event loop</i> handler, and will then
communicate events via a callback mechanism.</p>
<p>You register interest in certain events by registering so-called <i>even=
t
watchers</i>, which are relatively small C structures you initialise with t=
he
details of the event, and then hand it over to libev by <i>starting</i> the
watcher.</p>
</div>
<h2 id=3D"FEATURES">FEATURES</h2>
<div id=3D"FEATURES_CONTENT">
<p>Libev supports <code>select</code>, <code>poll</code>, the Linux-specifi=
c aio and <code>epoll</code>
interfaces, the BSD-specific <code>kqueue</code> and the Solaris-specific e=
vent port
mechanisms for file descriptor events (<code>ev_io</code>), the Linux <code=
>inotify</code>
interface (for <code>ev_stat</code>), Linux eventfd/signalfd (for faster an=
d cleaner
inter-thread wakeup (<code>ev_async</code>)/signal handling (<code>ev_signa=
l</code>)) relative
timers (<code>ev_timer</code>), absolute timers with customised reschedulin=
g
(<code>ev_periodic</code>), synchronous signals (<code>ev_signal</code>), p=
rocess status
change events (<code>ev_child</code>), and event watchers dealing with the =
event
loop mechanism itself (<code>ev_idle</code>, <code>ev_embed</code>, <code>e=
v_prepare</code> and
<code>ev_check</code> watchers) as well as file watchers (<code>ev_stat</co=
de>) and even
limited support for fork events (<code>ev_fork</code>).</p>
<p>It also is quite fast (see this
<a href=3D"http://libev.schmorp.de/bench.html">benchmark</a> comparing it t=
o libevent
for example).</p>
</div>
<h2 id=3D"CONVENTIONS">CONVENTIONS</h2>
<div id=3D"CONVENTIONS_CONTENT">
<p>Libev is very configurable. In this manual the default (and most common)
configuration will be described, which supports multiple event loops. For
more info about various configuration options please have a look at
<strong>EMBED</strong> section in this manual. If libev was configured with=
out support
for multiple event loops, then all functions taking an initial argument of
name <code>loop</code> (which is always of type <code>struct ev_loop *</cod=
e>) will not have
this argument.</p>
</div>
<h2 id=3D"TIME_REPRESENTATION">TIME REPRESENTATION</h2>
<div id=3D"TIME_REPRESENTATION_CONTENT">
<p>Libev represents time as a single floating point number, representing
the (fractional) number of seconds since the (POSIX) epoch (in practice
somewhere near the beginning of 1970, details are complicated, don't
ask). This type is called <code>ev_tstamp</code>, which is what you should =
use
too. It usually aliases to the <code>double</code> type in C. When you need=
to do
any calculations on it, you should treat it as some floating point value.</=
p>
<p>Unlike the name component <code>stamp</code> might indicate, it is also =
used for
time differences (e.g. delays) throughout libev.</p>
</div>
<h1 id=3D"ERROR_HANDLING">ERROR HANDLING</h1>
<div id=3D"ERROR_HANDLING_CONTENT">
<p>Libev knows three classes of errors: operating system errors, usage erro=
rs
and internal errors (bugs).</p>
<p>When libev catches an operating system error it cannot handle (for examp=
le
a system call indicating a condition libev cannot fix), it calls the callba=
ck
set via <code>ev_set_syserr_cb</code>, which is supposed to fix the problem=
or
abort. The default is to print a diagnostic message and to call <code>abort
()</code>.</p>
<p>When libev detects a usage error such as a negative timer interval, then
it will print a diagnostic message and abort (via the <code>assert</code> m=
echanism,
so <code>NDEBUG</code> will disable this checking): these are programming e=
rrors in
the libev caller and need to be fixed there.</p>
<p>Via the <code>EV_FREQUENT</code> macro you can compile in and/or enable =
extensive
consistency checking code inside libev that can be used to check for
internal inconsistencies, suually caused by application bugs.</p>
<p>Libev also has a few internal error-checking <code>assert</code>ions. Th=
ese do not
trigger under normal circumstances, as they indicate either a bug in libev
or worse.</p>
</div>
<h1 id=3D"GLOBAL_FUNCTIONS">GLOBAL FUNCTIONS</h1>
<div id=3D"GLOBAL_FUNCTIONS_CONTENT">
<p>These functions can be called anytime, even before initialising the
library in any way.</p>
<dl>
<dt>ev_tstamp ev_time ()</dt>
<dd>
<p>Returns the current time as libev would use it. Please note that the
<code>ev_now</code> function is usually faster and also often returns the t=
imestamp
you actually want to know. Also interesting is the combination of
<code>ev_now_update</code> and <code>ev_now</code>.</p>
</dd>
<dt>ev_sleep (ev_tstamp interval)</dt>
<dd>
<p>Sleep for the given interval: The current thread will be blocked
until either it is interrupted or the given time interval has
passed (approximately - it might return a bit earlier even if not
interrupted). Returns immediately if <code>interval <=3D 0</code>.</p>
<p>Basically this is a sub-second-resolution <code>sleep ()</code>.</p>
<p>The range of the <code>interval</code> is limited - libev only guarant=
ees to work
with sleep times of up to one day (<code>interval <=3D 86400</code>).</p=
>
</dd>
<dt>int ev_version_major ()</dt>
<dt>int ev_version_minor ()</dt>
<dd>
<p>You can find out the major and minor ABI version numbers of the librar=
y
you linked against by calling the functions <code>ev_version_major</code> a=
nd
<code>ev_version_minor</code>. If you want, you can compare against the glo=
bal
symbols <code>EV_VERSION_MAJOR</code> and <code>EV_VERSION_MINOR</code>, wh=
ich specify the
version of the library your program was compiled against.</p>
<p>These version numbers refer to the ABI version of the library, not the
release version.</p>
<p>Usually, it's a good idea to terminate if the major versions mismatch,
as this indicates an incompatible change. Minor versions are usually
compatible to older versions, so a larger minor version alone is usually
not a problem.</p>
<p>Example: Make sure we haven't accidentally been linked against the wro=
ng
version (note, however, that this will not detect other ABI mismatches,
such as LFS or reentrancy).</p>
<pre> assert (("libev version mismatch",
ev_version_major () =3D=3D EV_VERSION_MAJOR
&& ev_version_minor () >=3D EV_VERSION_MINOR));
</pre>
</dd>
<dt>unsigned int ev_supported_backends ()</dt>
<dd>
<p>Return the set of all backends (i.e. their corresponding <code>EV_BACK=
END_*</code>
value) compiled into this binary of libev (independent of their
availability on the system you are running on). See <code>ev_default_loop</=
code> for
a description of the set values.</p>
<p>Example: make sure we have the epoll method, because yeah this is cool=
and
a must have and can we have a torrent of it please!!!11</p>
<pre> assert (("sorry, no epoll, no sex",
ev_supported_backends () & EVBACKEND_EPOLL));
</pre>
</dd>
<dt>unsigned int ev_recommended_backends ()</dt>
<dd>
<p>Return the set of all backends compiled into this binary of libev and
also recommended for this platform, meaning it will work for most file
descriptor types. This set is often smaller than the one returned by
<code>ev_supported_backends</code>, as for example kqueue is broken on most=
BSDs
and will not be auto-detected unless you explicitly request it (assuming
you know what you are doing). This is the set of backends that libev will
probe for if you specify no backends explicitly.</p>
</dd>
<dt>unsigned int ev_embeddable_backends ()</dt>
<dd>
<p>Returns the set of backends that are embeddable in other event loops. =
This
value is platform-specific but can include backends not available on the
current system. To find which embeddable backends might be supported on
the current system, you would need to look at <code>ev_embeddable_backends =
()
& ev_supported_backends ()</code>, likewise for recommended ones.</p>
<p>See the description of <code>ev_embed</code> watchers for more info.</=
p>
</dd>
<dt>ev_set_allocator (void *(*cb)(void *ptr, long size) throw ())</dt>
<dd>
<p>Sets the allocation function to use (the prototype is similar - the
semantics are identical to the <code>realloc</code> C89/SuS/POSIX function)=
. It is
used to allocate and free memory (no surprises here). If it returns zero
when memory needs to be allocated (<code>size !=3D 0</code>), the library m=
ight abort
or take some potentially destructive action.</p>
<p>Since some systems (at least OpenBSD and Darwin) fail to implement
correct <code>realloc</code> semantics, libev will use a wrapper around the=
system
<code>realloc</code> and <code>free</code> functions by default.</p>
<p>You could override this function in high-availability programs to, say=
,
free some memory if it cannot allocate memory, to use a special allocator,
or even to sleep a while and retry until some memory is available.</p>
<p>Example: The following is the <code>realloc</code> function that libev=
itself uses
which should work with <code>realloc</code> and <code>free</code> functions=
of all kinds and
is probably a good basis for your own implementation.</p>
<pre> static void *
ev_realloc_emul (void *ptr, long size) EV_NOEXCEPT
{
if (size)
return realloc (ptr, size);
free (ptr);
return 0;
}
</pre>
<p>Example: Replace the libev allocator with one that waits a bit and the=
n
retries.</p>
<pre> static void *
persistent_realloc (void *ptr, size_t size)
{
if (!size)
{
free (ptr);
return 0;
}
for (;;)
{
void *newptr =3D realloc (ptr, size);
if (newptr)
return newptr;
sleep (60);
}
}
...
ev_set_allocator (persistent_realloc);
</pre>
</dd>
<dt>ev_set_syserr_cb (void (*cb)(const char *msg) throw ())</dt>
<dd>
<p>Set the callback function to call on a retryable system call error (su=
ch
as failed select, poll, epoll_wait). The message is a printable string
indicating the system call or subsystem causing the problem. If this
callback is set, then libev will expect it to remedy the situation, no
matter what, when it returns. That is, libev will generally retry the
requested operation, or, if the condition doesn't go away, do bad stuff
(such as abort).</p>
<p>Example: This is basically the same thing that libev does internally, =
too.</p>
<pre> static void
fatal_error (const char *msg)
{
perror (msg);
abort ();
}
...
ev_set_syserr_cb (fatal_error);
</pre>
</dd>
<dt>ev_feed_signal (int signum)</dt>
<dd>
<p>This function can be used to "simulate" a signal receive. It is comple=
tely
safe to call this function at any time, from any context, including signal
handlers or random threads.</p>
<p>Its main use is to customise signal handling in your process, especial=
ly
in the presence of threads. For example, you could block signals
by default in all threads (and specifying <code>EVFLAG_NOSIGMASK</code> whe=
n
creating any loops), and in one thread, use <code>sigwait</code> or any oth=
er
mechanism to wait for signals, then "deliver" them to libev by calling
<code>ev_feed_signal</code>.</p>
</dd>
</dl>
</div>
<h1 id=3D"FUNCTIONS_CONTROLLING_EVENT_LOOPS">FUNCTIONS CONTROLLING EVENT LO=
OPS</h1>
<div id=3D"FUNCTIONS_CONTROLLING_EVENT_LOOPS_CO">
<p>An event loop is described by a <code>struct ev_loop *</code> (the <code=
>struct</code> is
<i>not</i> optional in this case unless libev 3 compatibility is disabled, =
as
libev 3 had an <code>ev_loop</code> function colliding with the struct name=
).</p>
<p>The library knows two types of such loops, the <i>default</i> loop, whic=
h
supports child process events, and dynamically created event loops which
do not.</p>
<dl>
<dt>struct ev_loop *ev_default_loop (unsigned int flags)</dt>
<dd>
<p>This returns the "default" event loop object, which is what you should
normally use when you just need "the event loop". Event loop objects and
the <code>flags</code> parameter are described in more detail in the entry =
for
<code>ev_loop_new</code>.</p>
<p>If the default loop is already initialised then this function simply
returns it (and ignores the flags. If that is troubling you, check
<code>ev_backend ()</code> afterwards). Otherwise it will create it with th=
e given
flags, which should almost always be <code>0</code>, unless the caller is a=
lso the
one calling <code>ev_run</code> or otherwise qualifies as "the main program=
".</p>
<p>If you don't know what event loop to use, use the one returned from th=
is
function (or via the <code>EV_DEFAULT</code> macro).</p>
<p>Note that this function is <i>not</i> thread-safe, so if you want to u=
se it
from multiple threads, you have to employ some kind of mutex (note also
that this case is unlikely, as loops cannot be shared easily between
threads anyway).</p>
<p>The default loop is the only loop that can handle <code>ev_child</code=
> watchers,
and to do this, it always registers a handler for <code>SIGCHLD</code>. If =
this is
a problem for your application you can either create a dynamic loop with
<code>ev_loop_new</code> which doesn't do that, or you can simply overwrite=
the
<code>SIGCHLD</code> signal handler <i>after</i> calling <code>ev_default_i=
nit</code>.</p>
<p>Example: This is the most typical usage.</p>
<pre> if (!ev_default_loop (0))
fatal ("could not initialise libev, bad $LIBEV_FLAGS in environment?")=
;
</pre>
<p>Example: Restrict libev to the select and poll backends, and do not al=
low
environment settings to be taken into account:</p>
<pre> ev_default_loop (EVBACKEND_POLL | EVBACKEND_SELECT | EVFLAG_NOENV);
</pre>
</dd>
<dt>struct ev_loop *ev_loop_new (unsigned int flags)</dt>
<dd>
<p>This will create and initialise a new event loop object. If the loop
could not be initialised, returns false.</p>
<p>This function is thread-safe, and one common way to use libev with
threads is indeed to create one loop per thread, and using the default
loop in the "main" or "initial" thread.</p>
<p>The flags argument can be used to specify special behaviour or specifi=
c
backends to use, and is usually specified as <code>0</code> (or <code>EVFLA=
G_AUTO</code>).</p>
<p>The following flags are supported:</p>
<p>
</p><dl>
<dt><code>EVFLAG_AUTO</code></dt>
<dd>
<p>The default flags value. Use this if you have no clue (it's the rig=
ht
thing, believe me).</p>
</dd>
<dt><code>EVFLAG_NOENV</code></dt>
<dd>
<p>If this flag bit is or'ed into the flag value (or the program runs =
setuid
or setgid) then libev will <i>not</i> look at the environment variable
<code>LIBEV_FLAGS</code>. Otherwise (the default), this environment variabl=
e will
override the flags completely if it is found in the environment. This is
useful to try out specific backends to test their performance, to work
around bugs, or to make libev threadsafe (accessing environment variables
cannot be done in a threadsafe way, but usually it works if no other
thread modifies them).</p>
</dd>
<dt><code>EVFLAG_FORKCHECK</code></dt>
<dd>
<p>Instead of calling <code>ev_loop_fork</code> manually after a fork,=
you can also
make libev check for a fork in each iteration by enabling this flag.</p>
<p>This works by calling <code>getpid ()</code> on every iteration of =
the loop,
and thus this might slow down your event loop if you do a lot of loop
iterations and little real work, but is usually not noticeable (on my
GNU/Linux system for example, <code>getpid</code> is actually a simple 5-in=
sn
sequence without a system call and thus <i>very</i> fast, but my GNU/Linux
system also has <code>pthread_atfork</code> which is even faster). (Update:=
glibc
versions 2.25 apparently removed the <code>getpid</code> optimisation again=
).</p>
<p>The big advantage of this flag is that you can forget about fork (a=
nd
forget about forgetting to tell libev about forking, although you still
have to ignore <code>SIGPIPE</code>) when you use this flag.</p>
<p>This flag setting cannot be overridden or specified in the <code>LI=
BEV_FLAGS</code>
environment variable.</p>
</dd>
<dt><code>EVFLAG_NOINOTIFY</code></dt>
<dd>
<p>When this flag is specified, then libev will not attempt to use the
<i>inotify</i> API for its <code>ev_stat</code> watchers. Apart from debugg=
ing and
testing, this flag can be useful to conserve inotify file descriptors, as
otherwise each loop using <code>ev_stat</code> watchers consumes one inotif=
y handle.</p>
</dd>
<dt><code>EVFLAG_SIGNALFD</code></dt>
<dd>
<p>When this flag is specified, then libev will attempt to use the
<i>signalfd</i> API for its <code>ev_signal</code> (and <code>ev_child</cod=
e>) watchers. This API
delivers signals synchronously, which makes it both faster and might make
it possible to get the queued signal data. It can also simplify signal
handling with threads, as long as you properly block signals in your
threads that are not interested in handling them.</p>
<p>Signalfd will not be used by default as this changes your signal ma=
sk, and
there are a lot of shoddy libraries and programs (glib's threadpool for
example) that can't properly initialise their signal masks.</p>
</dd>
<dt><code>EVFLAG_NOSIGMASK</code></dt>
<dd>
<p>When this flag is specified, then libev will avoid to modify the si=
gnal
mask. Specifically, this means you have to make sure signals are unblocked
when you want to receive them.</p>
<p>This behaviour is useful when you want to do your own signal handli=
ng, or
want to handle signals only in specific threads and want to avoid libev
unblocking the signals.</p>
<p>It's also required by POSIX in a threaded program, as libev calls
<code>sigprocmask</code>, whose behaviour is officially unspecified.</p>
</dd>
<dt><code>EVFLAG_NOTIMERFD</code></dt>
<dd>
<p>When this flag is specified, the libev will avoid using a <code>tim=
erfd</code> to
detect time jumps. It will still be able to detect time jumps, but takes
longer and has a lower accuracy in doing so, but saves a file descriptor
per loop.</p>
<p>The current implementation only tries to use a <code>timerfd</code>=
when the first
<code>ev_periodic</code> watcher is started and falls back on other methods=
if it
cannot be created, but this behaviour might change in the future.</p>
</dd>
<dt><code>EVBACKEND_SELECT</code> (value 1, portable select backend)</=
dt>
<dd>
<p>This is your standard select(2) backend. Not <i>completely</i> stan=
dard, as
libev tries to roll its own fd_set with no limits on the number of fds,
but if that fails, expect a fairly low limit on the number of fds when
using this backend. It doesn't scale too well (O(highest_fd)), but its
usually the fastest backend for a low number of (low-numbered :) fds.</p>
<p>To get good performance out of this backend you need a high amount =
of
parallelism (most of the file descriptors should be busy). If you are
writing a server, you should <code>accept ()</code> in a loop to accept as =
many
connections as possible during one iteration. You might also want to have
a look at <code>ev_set_io_collect_interval ()</code> to increase the amount=
of
readiness notifications you get per iteration.</p>
<p>This backend maps <code>EV_READ</code> to the <code>readfds</code> =
set and <code>EV_WRITE</code> to the
<code>writefds</code> set (and to work around Microsoft Windows bugs, also =
onto the
<code>exceptfds</code> set on that platform).</p>
</dd>
<dt><code>EVBACKEND_POLL</code> (value 2, poll backend, available ev=
erywhere except on windows)</dt>
<dd>
<p>And this is your standard poll(2) backend. It's more complicated
than select, but handles sparse fds better and has no artificial
limit on the number of fds you can use (except it will slow down
considerably with a lot of inactive fds). It scales similarly to select,
i.e. O(total_fds). See the entry for <code>EVBACKEND_SELECT</code>, above, =
for
performance tips.</p>
<p>This backend maps <code>EV_READ</code> to <code>POLLIN | POLLERR | =
POLLHUP</code>, and
<code>EV_WRITE</code> to <code>POLLOUT | POLLERR | POLLHUP</code>.</p>
</dd>
<dt><code>EVBACKEND_EPOLL</code> (value 4, Linux)</dt>
<dd>
<p>Use the Linux-specific epoll(7) interface (for both pre- and post-2=
.6.9
kernels).</p>
<p>For few fds, this backend is a bit little slower than poll and sele=
ct, but
it scales phenomenally better. While poll and select usually scale like
O(total_fds) where total_fds is the total number of fds (or the highest
fd), epoll scales either O(1) or O(active_fds).</p>
<p>The epoll mechanism deserves honorable mention as the most misdesig=
ned
of the more advanced event mechanisms: mere annoyances include silently
dropping file descriptors, requiring a system call per change per file