rev 0.2.1 → 0.2.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -71,11 +71,11 @@
71
71
  # elements
72
72
  token = (ascii -- (CTL | tspecials));
73
73
 
74
- Reason_Phrase = (any -- CRLF)+ >mark %reason_phrase;
75
- Status_Code = digit+ >mark %status_code;
74
+ Reason_Phrase = (any -- CRLF)* >mark %reason_phrase;
75
+ Status_Code = digit{3} >mark %status_code;
76
76
  http_number = (digit+ "." digit+) ;
77
77
  HTTP_Version = ("HTTP/" http_number) >mark %http_version ;
78
- Status_Line = HTTP_Version " " Status_Code " " Reason_Phrase :> CRLF;
78
+ Status_Line = HTTP_Version " " Status_Code " "? Reason_Phrase :> CRLF;
79
79
 
80
80
  field_name = token+ >start_field %write_field;
81
81
  field_value = any* >start_value %write_value;
data/ext/libev/Changes CHANGED
@@ -1,5 +1,26 @@
1
1
  Revision history for libev, a high-performance and full-featured event loop.
2
2
 
3
+ 3.41 Fri May 23 18:42:54 CEST 2008
4
+ - work around an (undocumented) bug in winsocket select: if you
5
+ provide only empty fd sets then select returns WSAEINVAL. how sucky.
6
+ - improve timer scheduling stability and reduce use of time_epsilon.
7
+ - use 1-based 2-heap for EV_MINIMAL, simplifies code, reduces
8
+ codesize and makes for better cache-efficiency.
9
+ - use 3-based 4-heap for !EV_MINIMAL. this makes better use
10
+ of cpu cache lines and gives better growth behaviour than
11
+ 2-based heaps.
12
+ - cache timestamp within heap for !EV_MINIMAL, to avoid random
13
+ memory accesses.
14
+ - document/add EV_USE_4HEAP and EV_HEAP_CACHE_AT.
15
+ - fix a potential aliasing issue in ev_timer_again.
16
+ - add/document ev_periodic_at, retract direct access to ->at.
17
+ - improve ev_stat docs.
18
+ - add portability requirements section.
19
+ - fix manpage headers etc.
20
+ - normalise WSA error codes to lower range on windows.
21
+ - add consistency check code that can be called automatically
22
+ or on demand to check for internal structures (ev_loop_verify).
23
+
3
24
  3.31 Wed Apr 16 20:45:04 CEST 2008
4
25
  - added last minute fix for ev_poll.c by Brandon Black.
5
26
 
data/ext/libev/LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- All files in libev are Copyright (C)2007 Marc Alexander Lehmann.
1
+ All files in libev are Copyright (C)2007,2008 Marc Alexander Lehmann.
2
2
 
3
3
  Redistribution and use in source and binary forms, with or without
4
4
  modification, are permitted provided that the following conditions are
@@ -23,3 +23,14 @@ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23
23
  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24
24
  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25
25
  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26
+
27
+ Alternatively, the contents of this package may be used under the terms
28
+ of the GNU General Public License ("GPL") version 2 or any later version,
29
+ in which case the provisions of the GPL are applicable instead of the
30
+ above. If you wish to allow the use of your version of this package only
31
+ under the terms of the GPL and not to allow others to use your version of
32
+ this file under the BSD license, indicate your decision by deleting the
33
+ provisions above and replace them with the notice and other provisions
34
+ required by the GPL in this and the other files of this package. If you do
35
+ not delete the provisions above, a recipient may use your version of this
36
+ file under either the BSD or the GPL.
data/ext/libev/README CHANGED
@@ -1,128 +1,56 @@
1
1
  libev is a high-performance event loop/event model with lots of features.
2
2
  (see benchmark at http://libev.schmorp.de/bench.html)
3
3
 
4
- Homepage: http://software.schmorp.de/pkg/libev
5
- E-Mail: libev@lists.schmorp.de
6
- Library Documentation: http://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod
7
-
8
- It is modelled (very losely) after libevent and the Event perl module,
9
- but aims to be faster and more correct, and also more featureful. And
10
- also smaller. Yay.
11
4
 
12
- ABOUT THIS DISTRIBUTION
5
+ ABOUT
13
6
 
14
- If you downloaded the libevent+libev distribution of libev, you will
15
- find it looks very much like libevent. In fact, the distributed libev
16
- tarballs are indeed libevent tarballs patched up with the libev
17
- event core, taking the evbuffer, evtag, evdns and evhttpd parts from
18
- libevent (they use the libevent emulation inside libev). Configure and
19
- Makefile stuff is also a more or less direct copy of libevent, and are
20
- maintained by the libevent authors.
21
-
22
- If you downloaded the libev distribution (without libevent), then
23
- you only get the core parts of the library, meaning http and dns
24
- client/server code and similar things are missing. Only the core event
25
- loop is included.
7
+ Homepage: http://software.schmorp.de/pkg/libev
8
+ Mailinglist: libev@lists.schmorp.de
9
+ http://lists.schmorp.de/cgi-bin/mailman/listinfo/libev
10
+ Library Documentation: http://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod
26
11
 
27
- If you are looking for an easily embeddable version, I recommend using
28
- the libev standalone distribution or the CVS repository.
12
+ Libev is modelled (very losely) after libevent and the Event perl
13
+ module, but is faster, scales better and is more correct, and also more
14
+ featureful. And also smaller. Yay.
15
+
16
+ Some of the specialties of libev not commonly found elsewhere are:
17
+
18
+ - extensive and detailed, readable documentation (not doxygen garbage).
19
+ - fully supports fork, can detect fork in various ways and automatically
20
+ re-arms kernel mechanisms that do not support fork.
21
+ - highly optimised select, poll, epoll, kqueue and event ports backends.
22
+ - filesystem object (path) watching (with optional linux inotify support).
23
+ - wallclock-based times (using absolute time, cron-like).
24
+ - relative timers/timeouts (handle time jumps).
25
+ - fast intra-thread communication between multiple
26
+ event loops (with optional fast linux eventfd backend).
27
+ - extremely easy to embed.
28
+ - very small codebase, no bloated library.
29
+ - fully extensible by being able to plug into the event loop,
30
+ integrate other event loops, integrate other event loop users.
31
+ - very little memory use (small watchers, small event loop data).
32
+ - optional C++ interface allowing method and function callbacks
33
+ at no extra memory or runtime overhead.
34
+ - optional Perl interface with similar characteristics (capable
35
+ of running Glib/Gtk2 on libev, interfaces with Net::SNMP and
36
+ libadns).
37
+ - support for other languages (multiple C++ interfaces, D, Ruby,
38
+ Python) available from third-parties.
29
39
 
30
40
  Examples of programs that embed libev: the EV perl module,
31
- rxvt-unicode, gvpe (GNU Virtual Private Ethernet) and deliantra
32
- (http://www.deliantra.net).
33
-
34
- DIFFERENCES AND COMPARISON TO LIBEVENT
35
-
36
- The comparisons below are relative to libevent-1.3e.
37
-
38
- - multiple watchers can wait for the same event without deregistering others,
39
- both for file descriptors as well as signals.
40
- (registering two read events on fd 10 and unregistering one will not
41
- break the other).
42
-
43
- - fork() is supported and can be handled
44
- (there is no way to recover from a fork with libevent).
45
-
46
- - timers are handled as a priority queue (important operations are O(1))
47
- (libevent uses a much less efficient but more complex red-black tree).
48
-
49
- - supports absolute (wallclock-based) timers in addition to relative ones,
50
- i.e. can schedule timers to occur after n seconds, or at a specific time.
51
-
52
- - timers can be repeating (both absolute and relative ones).
53
-
54
- - absolute timers can have customised rescheduling hooks (suitable for cron-like
55
- applications).
56
-
57
- - detects time jumps and adjusts timers
58
- (works for both forward and backward time jumps and also for absolute timers).
59
-
60
- - race-free signal processing
61
- (libevent may delay processing signals till after the next event).
62
-
63
- - more efficient epoll backend
64
- (stopping and starting an io watcher between two loop iterations will not
65
- result in spurious epoll_ctl calls).
66
-
67
- - usually less calls to gettimeofday and clock_gettime
68
- (libevent calls it on every timer event change, libev twice per iteration).
69
-
70
- - watchers use less memory
71
- (libevent watcher on amd64: 152 bytes, libev native: <= 56 bytes, libevent emulation: 144 bytes).
72
-
73
- - library uses less memory
74
- (libevent allocates large data structures wether used or not, libev
75
- scales all its data structures dynamically).
76
-
77
- - no hardcoded arbitrary limits
78
- (libevent contains an off-by-one bug and sometimes hardcodes limits).
79
-
80
- - libev separates timer, signal and io watchers from each other
81
- (libevent combines them, but with libev you can combine them yourself
82
- by reusing the same callback and still save memory).
83
-
84
- - simpler design, backends are potentially much simpler
85
- (in libevent, backends have to deal with watchers, thus the problems with
86
- wildly different semantics between diferent backends)
87
- (epoll backend in libevent: 366 lines no caching, libev: 90 lines full caching).
88
-
89
- - libev handles EBADF gracefully by removing the offending fds.
90
-
91
- - libev communicates errors to the callback, libevent to the
92
- event adder or not at all.
93
-
94
- - doesn't rely on nonportable BSD header files.
95
-
96
- - an event.h compatibility header exists, and can be used to run a wide
97
- range of libevent programs unchanged (such as evdns.c).
98
-
99
- - win32 compatibility for the core parts.
100
- (the backend is fd-based as documented and on other platforms,
101
- not handle-based like libevent, and can be used for both winscoket environments
102
- and unix-like ones).
103
-
104
- - libev can be embedded easily with or without autoconf support into
105
- other programs, with no changes to the source code necessary.
106
-
107
- - the event core library (ev and event layer) compiles and works both as
108
- C and C++.
109
-
110
- - a simple C++ wrapper that supports methods as callbacks exists.
111
-
112
- - a full featured and widely used perl module is available.
113
-
114
- whats missing?
41
+ rxvt-unicode, gvpe (GNU Virtual Private Ethernet), the Deliantra MMORPG
42
+ server (http://www.deliantra.net/), Rubinius (a next-generation Ruby
43
+ VM), the Ebb web server, the Rev event toolkit.
115
44
 
116
- - no event-like priority support at the moment (the ev priorities work
117
- differently, but you can use idle watchers to get a similar effect).
118
45
 
119
- AUTHOR
46
+ CONTRIBUTORS
120
47
 
121
48
  libev was written and designed by Marc Lehmann and Emanuele Giaquinta.
122
49
 
123
50
  The following people sent in patches or made other noteworthy
124
- contributions to the design (if I forgot to include you, please shout
125
- at me, it was an accident):
51
+ contributions to the design (for minor patches, see the Changes
52
+ file. If I forgot to include you, please shout at me, it was an
53
+ accident):
126
54
 
127
55
  W.C.A. Wijngaards
128
56
  Christopher Layne
data/ext/libev/ev.c CHANGED
@@ -128,7 +128,7 @@ extern "C" {
128
128
  # define EV_USE_EVENTFD 0
129
129
  # endif
130
130
  # endif
131
-
131
+
132
132
  #endif
133
133
 
134
134
  #include <math.h>
@@ -237,6 +237,24 @@ extern "C" {
237
237
  # endif
238
238
  #endif
239
239
 
240
+ #if 0 /* debugging */
241
+ # define EV_VERIFY 3
242
+ # define EV_USE_4HEAP 1
243
+ # define EV_HEAP_CACHE_AT 1
244
+ #endif
245
+
246
+ #ifndef EV_VERIFY
247
+ # define EV_VERIFY !EV_MINIMAL
248
+ #endif
249
+
250
+ #ifndef EV_USE_4HEAP
251
+ # define EV_USE_4HEAP !EV_MINIMAL
252
+ #endif
253
+
254
+ #ifndef EV_HEAP_CACHE_AT
255
+ # define EV_HEAP_CACHE_AT !EV_MINIMAL
256
+ #endif
257
+
240
258
  /* this block fixes any misconfiguration where we know we run into trouble otherwise */
241
259
 
242
260
  #ifndef CLOCK_MONOTONIC
@@ -282,6 +300,12 @@ int eventfd (unsigned int initval, int flags);
282
300
 
283
301
  /**/
284
302
 
303
+ #if EV_VERIFY >= 3
304
+ # define EV_FREQUENT_CHECK ev_loop_verify (EV_A)
305
+ #else
306
+ # define EV_FREQUENT_CHECK do { } while (0)
307
+ #endif
308
+
285
309
  /*
286
310
  * This is used to avoid floating point rounding problems.
287
311
  * It is added to ev_rt_now when scheduling periodics
@@ -327,6 +351,9 @@ typedef ev_watcher *W;
327
351
  typedef ev_watcher_list *WL;
328
352
  typedef ev_watcher_time *WT;
329
353
 
354
+ #define ev_active(w) ((W)(w))->active
355
+ #define ev_at(w) ((WT)(w))->at
356
+
330
357
  #if EV_USE_MONOTONIC
331
358
  /* sig_atomic_t is used to avoid per-thread variables or locking but still */
332
359
  /* giving it a reasonably high chance of working on typical architetcures */
@@ -421,12 +448,31 @@ typedef struct
421
448
  } ANPENDING;
422
449
 
423
450
  #if EV_USE_INOTIFY
451
+ /* hash table entry per inotify-id */
424
452
  typedef struct
425
453
  {
426
454
  WL head;
427
455
  } ANFS;
428
456
  #endif
429
457
 
458
+ /* Heap Entry */
459
+ #if EV_HEAP_CACHE_AT
460
+ typedef struct {
461
+ ev_tstamp at;
462
+ WT w;
463
+ } ANHE;
464
+
465
+ #define ANHE_w(he) (he).w /* access watcher, read-write */
466
+ #define ANHE_at(he) (he).at /* access cached at, read-only */
467
+ #define ANHE_at_cache(he) (he).at = (he).w->at /* update at from watcher */
468
+ #else
469
+ typedef WT ANHE;
470
+
471
+ #define ANHE_w(he) (he)
472
+ #define ANHE_at(he) (he)->at
473
+ #define ANHE_at_cache(he)
474
+ #endif
475
+
430
476
  #if EV_MULTIPLICITY
431
477
 
432
478
  struct ev_loop
@@ -519,6 +565,8 @@ ev_sleep (ev_tstamp delay)
519
565
 
520
566
  /*****************************************************************************/
521
567
 
568
+ #define MALLOC_ROUND 4096 /* prefer to allocate in chunks of this size, must be 2**n and >> 4 longs */
569
+
522
570
  int inline_size
523
571
  array_nextsize (int elem, int cur, int cnt)
524
572
  {
@@ -528,11 +576,11 @@ array_nextsize (int elem, int cur, int cnt)
528
576
  ncur <<= 1;
529
577
  while (cnt > ncur);
530
578
 
531
- /* if size > 4096, round to 4096 - 4 * longs to accomodate malloc overhead */
532
- if (elem * ncur > 4096)
579
+ /* if size is large, round to MALLOC_ROUND - 4 * longs to accomodate malloc overhead */
580
+ if (elem * ncur > MALLOC_ROUND - sizeof (void *) * 4)
533
581
  {
534
582
  ncur *= elem;
535
- ncur = (ncur + elem + 4095 + sizeof (void *) * 4) & ~4095;
583
+ ncur = (ncur + elem + (MALLOC_ROUND - 1) + sizeof (void *) * 4) & ~(MALLOC_ROUND - 1);
536
584
  ncur = ncur - sizeof (void *) * 4;
537
585
  ncur /= elem;
538
586
  }
@@ -756,60 +804,146 @@ fd_rearm_all (EV_P)
756
804
 
757
805
  /*****************************************************************************/
758
806
 
807
+ /*
808
+ * the heap functions want a real array index. array index 0 uis guaranteed to not
809
+ * be in-use at any time. the first heap entry is at array [HEAP0]. DHEAP gives
810
+ * the branching factor of the d-tree.
811
+ */
812
+
813
+ /*
814
+ * at the moment we allow libev the luxury of two heaps,
815
+ * a small-code-size 2-heap one and a ~1.5kb larger 4-heap
816
+ * which is more cache-efficient.
817
+ * the difference is about 5% with 50000+ watchers.
818
+ */
819
+ #if EV_USE_4HEAP
820
+
821
+ #define DHEAP 4
822
+ #define HEAP0 (DHEAP - 1) /* index of first element in heap */
823
+ #define HPARENT(k) ((((k) - HEAP0 - 1) / DHEAP) + HEAP0)
824
+ #define UPHEAP_DONE(p,k) ((p) == (k))
825
+
826
+ /* away from the root */
759
827
  void inline_speed
760
- upheap (WT *heap, int k)
828
+ downheap (ANHE *heap, int N, int k)
761
829
  {
762
- WT w = heap [k];
830
+ ANHE he = heap [k];
831
+ ANHE *E = heap + N + HEAP0;
763
832
 
764
- while (k)
833
+ for (;;)
765
834
  {
766
- int p = (k - 1) >> 1;
835
+ ev_tstamp minat;
836
+ ANHE *minpos;
837
+ ANHE *pos = heap + DHEAP * (k - HEAP0) + HEAP0 + 1;
767
838
 
768
- if (heap [p]->at <= w->at)
839
+ /* find minimum child */
840
+ if (expect_true (pos + DHEAP - 1 < E))
841
+ {
842
+ /* fast path */ (minpos = pos + 0), (minat = ANHE_at (*minpos));
843
+ if ( ANHE_at (pos [1]) < minat) (minpos = pos + 1), (minat = ANHE_at (*minpos));
844
+ if ( ANHE_at (pos [2]) < minat) (minpos = pos + 2), (minat = ANHE_at (*minpos));
845
+ if ( ANHE_at (pos [3]) < minat) (minpos = pos + 3), (minat = ANHE_at (*minpos));
846
+ }
847
+ else if (pos < E)
848
+ {
849
+ /* slow path */ (minpos = pos + 0), (minat = ANHE_at (*minpos));
850
+ if (pos + 1 < E && ANHE_at (pos [1]) < minat) (minpos = pos + 1), (minat = ANHE_at (*minpos));
851
+ if (pos + 2 < E && ANHE_at (pos [2]) < minat) (minpos = pos + 2), (minat = ANHE_at (*minpos));
852
+ if (pos + 3 < E && ANHE_at (pos [3]) < minat) (minpos = pos + 3), (minat = ANHE_at (*minpos));
853
+ }
854
+ else
769
855
  break;
770
856
 
771
- heap [k] = heap [p];
772
- ((W)heap [k])->active = k + 1;
773
- k = p;
857
+ if (ANHE_at (he) <= minat)
858
+ break;
859
+
860
+ heap [k] = *minpos;
861
+ ev_active (ANHE_w (*minpos)) = k;
862
+
863
+ k = minpos - heap;
774
864
  }
775
865
 
776
- heap [k] = w;
777
- ((W)heap [k])->active = k + 1;
866
+ heap [k] = he;
867
+ ev_active (ANHE_w (he)) = k;
778
868
  }
779
869
 
870
+ #else /* 4HEAP */
871
+
872
+ #define HEAP0 1
873
+ #define HPARENT(k) ((k) >> 1)
874
+ #define UPHEAP_DONE(p,k) (!(p))
875
+
876
+ /* away from the root */
780
877
  void inline_speed
781
- downheap (WT *heap, int N, int k)
878
+ downheap (ANHE *heap, int N, int k)
782
879
  {
783
- WT w = heap [k];
880
+ ANHE he = heap [k];
784
881
 
785
882
  for (;;)
786
883
  {
787
- int c = (k << 1) + 1;
884
+ int c = k << 1;
788
885
 
789
- if (c >= N)
886
+ if (c > N + HEAP0 - 1)
790
887
  break;
791
888
 
792
- c += c + 1 < N && heap [c]->at > heap [c + 1]->at
889
+ c += c + 1 < N + HEAP0 && ANHE_at (heap [c]) > ANHE_at (heap [c + 1])
793
890
  ? 1 : 0;
794
891
 
795
- if (w->at <= heap [c]->at)
892
+ if (ANHE_at (he) <= ANHE_at (heap [c]))
796
893
  break;
797
894
 
798
895
  heap [k] = heap [c];
799
- ((W)heap [k])->active = k + 1;
800
-
896
+ ev_active (ANHE_w (heap [k])) = k;
897
+
801
898
  k = c;
802
899
  }
803
900
 
804
- heap [k] = w;
805
- ((W)heap [k])->active = k + 1;
901
+ heap [k] = he;
902
+ ev_active (ANHE_w (he)) = k;
903
+ }
904
+ #endif
905
+
906
+ /* towards the root */
907
+ void inline_speed
908
+ upheap (ANHE *heap, int k)
909
+ {
910
+ ANHE he = heap [k];
911
+
912
+ for (;;)
913
+ {
914
+ int p = HPARENT (k);
915
+
916
+ if (UPHEAP_DONE (p, k) || ANHE_at (heap [p]) <= ANHE_at (he))
917
+ break;
918
+
919
+ heap [k] = heap [p];
920
+ ev_active (ANHE_w (heap [k])) = k;
921
+ k = p;
922
+ }
923
+
924
+ heap [k] = he;
925
+ ev_active (ANHE_w (he)) = k;
926
+ }
927
+
928
+ void inline_size
929
+ adjustheap (ANHE *heap, int N, int k)
930
+ {
931
+ if (k > HEAP0 && ANHE_at (heap [HPARENT (k)]) >= ANHE_at (heap [k]))
932
+ upheap (heap, k);
933
+ else
934
+ downheap (heap, N, k);
806
935
  }
807
936
 
937
+ /* rebuild the heap: this function is used only once and executed rarely */
808
938
  void inline_size
809
- adjustheap (WT *heap, int N, int k)
939
+ reheap (ANHE *heap, int N)
810
940
  {
811
- upheap (heap, k);
812
- downheap (heap, N, k);
941
+ int i;
942
+
943
+ /* we don't use floyds algorithm, upheap is simpler and is more cache-efficient */
944
+ /* also, this is easy to implement and correct for both 2-heaps and 4-heaps */
945
+ for (i = 0; i < N; ++i)
946
+ upheap (heap, i + HEAP0);
813
947
  }
814
948
 
815
949
  /*****************************************************************************/
@@ -908,7 +1042,7 @@ pipecb (EV_P_ ev_io *iow, int revents)
908
1042
  #if EV_USE_EVENTFD
909
1043
  if (evfd >= 0)
910
1044
  {
911
- uint64_t counter = 1;
1045
+ uint64_t counter;
912
1046
  read (evfd, &counter, sizeof (uint64_t));
913
1047
  }
914
1048
  else
@@ -1285,7 +1419,9 @@ loop_destroy (EV_P)
1285
1419
  backend = 0;
1286
1420
  }
1287
1421
 
1422
+ #if EV_USE_INOTIFY
1288
1423
  void inline_size infy_fork (EV_P);
1424
+ #endif
1289
1425
 
1290
1426
  void inline_size
1291
1427
  loop_fork (EV_P)
@@ -1335,6 +1471,7 @@ loop_fork (EV_P)
1335
1471
  }
1336
1472
 
1337
1473
  #if EV_MULTIPLICITY
1474
+
1338
1475
  struct ev_loop *
1339
1476
  ev_loop_new (unsigned int flags)
1340
1477
  {
@@ -1363,7 +1500,106 @@ ev_loop_fork (EV_P)
1363
1500
  postfork = 1; /* must be in line with ev_default_fork */
1364
1501
  }
1365
1502
 
1503
+ #if EV_VERIFY
1504
+ void noinline
1505
+ verify_watcher (EV_P_ W w)
1506
+ {
1507
+ assert (("watcher has invalid priority", ABSPRI (w) >= 0 && ABSPRI (w) < NUMPRI));
1508
+
1509
+ if (w->pending)
1510
+ assert (("pending watcher not on pending queue", pendings [ABSPRI (w)][w->pending - 1].w == w));
1511
+ }
1512
+
1513
+ static void noinline
1514
+ verify_heap (EV_P_ ANHE *heap, int N)
1515
+ {
1516
+ int i;
1517
+
1518
+ for (i = HEAP0; i < N + HEAP0; ++i)
1519
+ {
1520
+ assert (("active index mismatch in heap", ev_active (ANHE_w (heap [i])) == i));
1521
+ assert (("heap condition violated", i == HEAP0 || ANHE_at (heap [HPARENT (i)]) <= ANHE_at (heap [i])));
1522
+ assert (("heap at cache mismatch", ANHE_at (heap [i]) == ev_at (ANHE_w (heap [i]))));
1523
+
1524
+ verify_watcher (EV_A_ (W)ANHE_w (heap [i]));
1525
+ }
1526
+ }
1527
+
1528
+ static void noinline
1529
+ array_verify (EV_P_ W *ws, int cnt)
1530
+ {
1531
+ while (cnt--)
1532
+ {
1533
+ assert (("active index mismatch", ev_active (ws [cnt]) == cnt + 1));
1534
+ verify_watcher (EV_A_ ws [cnt]);
1535
+ }
1536
+ }
1537
+ #endif
1538
+
1539
+ void
1540
+ ev_loop_verify (EV_P)
1541
+ {
1542
+ #if EV_VERIFY
1543
+ int i;
1544
+ WL w;
1545
+
1546
+ assert (activecnt >= -1);
1547
+
1548
+ assert (fdchangemax >= fdchangecnt);
1549
+ for (i = 0; i < fdchangecnt; ++i)
1550
+ assert (("negative fd in fdchanges", fdchanges [i] >= 0));
1551
+
1552
+ assert (anfdmax >= 0);
1553
+ for (i = 0; i < anfdmax; ++i)
1554
+ for (w = anfds [i].head; w; w = w->next)
1555
+ {
1556
+ verify_watcher (EV_A_ (W)w);
1557
+ assert (("inactive fd watcher on anfd list", ev_active (w) == 1));
1558
+ assert (("fd mismatch between watcher and anfd", ((ev_io *)w)->fd == i));
1559
+ }
1560
+
1561
+ assert (timermax >= timercnt);
1562
+ verify_heap (EV_A_ timers, timercnt);
1563
+
1564
+ #if EV_PERIODIC_ENABLE
1565
+ assert (periodicmax >= periodiccnt);
1566
+ verify_heap (EV_A_ periodics, periodiccnt);
1567
+ #endif
1568
+
1569
+ for (i = NUMPRI; i--; )
1570
+ {
1571
+ assert (pendingmax [i] >= pendingcnt [i]);
1572
+ #if EV_IDLE_ENABLE
1573
+ assert (idleall >= 0);
1574
+ assert (idlemax [i] >= idlecnt [i]);
1575
+ array_verify (EV_A_ (W *)idles [i], idlecnt [i]);
1576
+ #endif
1577
+ }
1578
+
1579
+ #if EV_FORK_ENABLE
1580
+ assert (forkmax >= forkcnt);
1581
+ array_verify (EV_A_ (W *)forks, forkcnt);
1582
+ #endif
1583
+
1584
+ #if EV_ASYNC_ENABLE
1585
+ assert (asyncmax >= asynccnt);
1586
+ array_verify (EV_A_ (W *)asyncs, asynccnt);
1587
+ #endif
1588
+
1589
+ assert (preparemax >= preparecnt);
1590
+ array_verify (EV_A_ (W *)prepares, preparecnt);
1591
+
1592
+ assert (checkmax >= checkcnt);
1593
+ array_verify (EV_A_ (W *)checks, checkcnt);
1594
+
1595
+ # if 0
1596
+ for (w = (ev_child *)childs [chain & (EV_PID_HASHSIZE - 1)]; w; w = (ev_child *)((WL)w)->next)
1597
+ for (signum = signalmax; signum--; ) if (signals [signum].gotsig)
1598
+ # endif
1366
1599
  #endif
1600
+ }
1601
+
1602
+ #endif /* multiplicity */
1367
1603
 
1368
1604
  #if EV_MULTIPLICITY
1369
1605
  struct ev_loop *
@@ -1449,33 +1685,61 @@ call_pending (EV_P)
1449
1685
 
1450
1686
  p->w->pending = 0;
1451
1687
  EV_CB_INVOKE (p->w, p->events);
1688
+ EV_FREQUENT_CHECK;
1452
1689
  }
1453
1690
  }
1454
1691
  }
1455
1692
 
1693
+ #if EV_IDLE_ENABLE
1694
+ void inline_size
1695
+ idle_reify (EV_P)
1696
+ {
1697
+ if (expect_false (idleall))
1698
+ {
1699
+ int pri;
1700
+
1701
+ for (pri = NUMPRI; pri--; )
1702
+ {
1703
+ if (pendingcnt [pri])
1704
+ break;
1705
+
1706
+ if (idlecnt [pri])
1707
+ {
1708
+ queue_events (EV_A_ (W *)idles [pri], idlecnt [pri], EV_IDLE);
1709
+ break;
1710
+ }
1711
+ }
1712
+ }
1713
+ }
1714
+ #endif
1715
+
1456
1716
  void inline_size
1457
1717
  timers_reify (EV_P)
1458
1718
  {
1459
- while (timercnt && ((WT)timers [0])->at <= mn_now)
1719
+ EV_FREQUENT_CHECK;
1720
+
1721
+ while (timercnt && ANHE_at (timers [HEAP0]) < mn_now)
1460
1722
  {
1461
- ev_timer *w = (ev_timer *)timers [0];
1723
+ ev_timer *w = (ev_timer *)ANHE_w (timers [HEAP0]);
1462
1724
 
1463
1725
  /*assert (("inactive timer on timer heap detected", ev_is_active (w)));*/
1464
1726
 
1465
1727
  /* first reschedule or stop timer */
1466
1728
  if (w->repeat)
1467
1729
  {
1468
- assert (("negative ev_timer repeat value found while processing timers", w->repeat > 0.));
1730
+ ev_at (w) += w->repeat;
1731
+ if (ev_at (w) < mn_now)
1732
+ ev_at (w) = mn_now;
1469
1733
 
1470
- ((WT)w)->at += w->repeat;
1471
- if (((WT)w)->at < mn_now)
1472
- ((WT)w)->at = mn_now;
1734
+ assert (("negative ev_timer repeat value found while processing timers", w->repeat > 0.));
1473
1735
 
1474
- downheap (timers, timercnt, 0);
1736
+ ANHE_at_cache (timers [HEAP0]);
1737
+ downheap (timers, timercnt, HEAP0);
1475
1738
  }
1476
1739
  else
1477
1740
  ev_timer_stop (EV_A_ w); /* nonrepeating: stop timer */
1478
1741
 
1742
+ EV_FREQUENT_CHECK;
1479
1743
  ev_feed_event (EV_A_ (W)w, EV_TIMEOUT);
1480
1744
  }
1481
1745
  }
@@ -1484,29 +1748,47 @@ timers_reify (EV_P)
1484
1748
  void inline_size
1485
1749
  periodics_reify (EV_P)
1486
1750
  {
1487
- while (periodiccnt && ((WT)periodics [0])->at <= ev_rt_now)
1751
+ EV_FREQUENT_CHECK;
1752
+
1753
+ while (periodiccnt && ANHE_at (periodics [HEAP0]) < ev_rt_now)
1488
1754
  {
1489
- ev_periodic *w = (ev_periodic *)periodics [0];
1755
+ ev_periodic *w = (ev_periodic *)ANHE_w (periodics [HEAP0]);
1490
1756
 
1491
1757
  /*assert (("inactive timer on periodic heap detected", ev_is_active (w)));*/
1492
1758
 
1493
1759
  /* first reschedule or stop timer */
1494
1760
  if (w->reschedule_cb)
1495
1761
  {
1496
- ((WT)w)->at = w->reschedule_cb (w, ev_rt_now + TIME_EPSILON);
1497
- assert (("ev_periodic reschedule callback returned time in the past", ((WT)w)->at > ev_rt_now));
1498
- downheap (periodics, periodiccnt, 0);
1762
+ ev_at (w) = w->reschedule_cb (w, ev_rt_now);
1763
+
1764
+ assert (("ev_periodic reschedule callback returned time in the past", ev_at (w) >= ev_rt_now));
1765
+
1766
+ ANHE_at_cache (periodics [HEAP0]);
1767
+ downheap (periodics, periodiccnt, HEAP0);
1499
1768
  }
1500
1769
  else if (w->interval)
1501
1770
  {
1502
- ((WT)w)->at = w->offset + ceil ((ev_rt_now - w->offset) / w->interval) * w->interval;
1503
- if (((WT)w)->at - ev_rt_now <= TIME_EPSILON) ((WT)w)->at += w->interval;
1504
- assert (("ev_periodic timeout in the past detected while processing timers, negative interval?", ((WT)w)->at > ev_rt_now));
1505
- downheap (periodics, periodiccnt, 0);
1771
+ ev_at (w) = w->offset + ceil ((ev_rt_now - w->offset) / w->interval) * w->interval;
1772
+ /* if next trigger time is not sufficiently in the future, put it there */
1773
+ /* this might happen because of floating point inexactness */
1774
+ if (ev_at (w) - ev_rt_now < TIME_EPSILON)
1775
+ {
1776
+ ev_at (w) += w->interval;
1777
+
1778
+ /* if interval is unreasonably low we might still have a time in the past */
1779
+ /* so correct this. this will make the periodic very inexact, but the user */
1780
+ /* has effectively asked to get triggered more often than possible */
1781
+ if (ev_at (w) < ev_rt_now)
1782
+ ev_at (w) = ev_rt_now;
1783
+ }
1784
+
1785
+ ANHE_at_cache (periodics [HEAP0]);
1786
+ downheap (periodics, periodiccnt, HEAP0);
1506
1787
  }
1507
1788
  else
1508
1789
  ev_periodic_stop (EV_A_ w); /* nonrepeating: stop timer */
1509
1790
 
1791
+ EV_FREQUENT_CHECK;
1510
1792
  ev_feed_event (EV_A_ (W)w, EV_PERIODIC);
1511
1793
  }
1512
1794
  }
@@ -1517,42 +1799,19 @@ periodics_reschedule (EV_P)
1517
1799
  int i;
1518
1800
 
1519
1801
  /* adjust periodics after time jump */
1520
- for (i = 0; i < periodiccnt; ++i)
1802
+ for (i = HEAP0; i < periodiccnt + HEAP0; ++i)
1521
1803
  {
1522
- ev_periodic *w = (ev_periodic *)periodics [i];
1804
+ ev_periodic *w = (ev_periodic *)ANHE_w (periodics [i]);
1523
1805
 
1524
1806
  if (w->reschedule_cb)
1525
- ((WT)w)->at = w->reschedule_cb (w, ev_rt_now);
1807
+ ev_at (w) = w->reschedule_cb (w, ev_rt_now);
1526
1808
  else if (w->interval)
1527
- ((WT)w)->at = w->offset + ceil ((ev_rt_now - w->offset) / w->interval) * w->interval;
1528
- }
1809
+ ev_at (w) = w->offset + ceil ((ev_rt_now - w->offset) / w->interval) * w->interval;
1529
1810
 
1530
- /* now rebuild the heap */
1531
- for (i = periodiccnt >> 1; i--; )
1532
- downheap (periodics, periodiccnt, i);
1533
- }
1534
- #endif
1535
-
1536
- #if EV_IDLE_ENABLE
1537
- void inline_size
1538
- idle_reify (EV_P)
1539
- {
1540
- if (expect_false (idleall))
1541
- {
1542
- int pri;
1543
-
1544
- for (pri = NUMPRI; pri--; )
1545
- {
1546
- if (pendingcnt [pri])
1547
- break;
1548
-
1549
- if (idlecnt [pri])
1550
- {
1551
- queue_events (EV_A_ (W *)idles [pri], idlecnt [pri], EV_IDLE);
1552
- break;
1553
- }
1554
- }
1811
+ ANHE_at_cache (periodics [i]);
1555
1812
  }
1813
+
1814
+ reheap (periodics, periodiccnt);
1556
1815
  }
1557
1816
  #endif
1558
1817
 
@@ -1591,7 +1850,7 @@ time_update (EV_P_ ev_tstamp max_block)
1591
1850
  {
1592
1851
  rtmn_diff = ev_rt_now - mn_now;
1593
1852
 
1594
- if (fabs (odiff - rtmn_diff) < MIN_TIMEJUMP)
1853
+ if (expect_true (fabs (odiff - rtmn_diff) < MIN_TIMEJUMP))
1595
1854
  return; /* all is well */
1596
1855
 
1597
1856
  ev_rt_now = ev_time ();
@@ -1617,7 +1876,11 @@ time_update (EV_P_ ev_tstamp max_block)
1617
1876
  #endif
1618
1877
  /* adjust timers. this is easy, as the offset is the same for all of them */
1619
1878
  for (i = 0; i < timercnt; ++i)
1620
- ((WT)timers [i])->at += ev_rt_now - mn_now;
1879
+ {
1880
+ ANHE *he = timers + i + HEAP0;
1881
+ ANHE_w (*he)->at += ev_rt_now - mn_now;
1882
+ ANHE_at_cache (*he);
1883
+ }
1621
1884
  }
1622
1885
 
1623
1886
  mn_now = ev_rt_now;
@@ -1647,6 +1910,10 @@ ev_loop (EV_P_ int flags)
1647
1910
 
1648
1911
  do
1649
1912
  {
1913
+ #if EV_VERIFY >= 2
1914
+ ev_loop_verify (EV_A);
1915
+ #endif
1916
+
1650
1917
  #ifndef _WIN32
1651
1918
  if (expect_false (curpid)) /* penalise the forking check even more */
1652
1919
  if (expect_false (getpid () != curpid))
@@ -1697,14 +1964,14 @@ ev_loop (EV_P_ int flags)
1697
1964
 
1698
1965
  if (timercnt)
1699
1966
  {
1700
- ev_tstamp to = ((WT)timers [0])->at - mn_now + backend_fudge;
1967
+ ev_tstamp to = ANHE_at (timers [HEAP0]) - mn_now + backend_fudge;
1701
1968
  if (waittime > to) waittime = to;
1702
1969
  }
1703
1970
 
1704
1971
  #if EV_PERIODIC_ENABLE
1705
1972
  if (periodiccnt)
1706
1973
  {
1707
- ev_tstamp to = ((WT)periodics [0])->at - ev_rt_now + backend_fudge;
1974
+ ev_tstamp to = ANHE_at (periodics [HEAP0]) - ev_rt_now + backend_fudge;
1708
1975
  if (waittime > to) waittime = to;
1709
1976
  }
1710
1977
  #endif
@@ -1851,12 +2118,16 @@ ev_io_start (EV_P_ ev_io *w)
1851
2118
 
1852
2119
  assert (("ev_io_start called with negative fd", fd >= 0));
1853
2120
 
2121
+ EV_FREQUENT_CHECK;
2122
+
1854
2123
  ev_start (EV_A_ (W)w, 1);
1855
2124
  array_needsize (ANFD, anfds, anfdmax, fd + 1, anfds_init);
1856
2125
  wlist_add (&anfds[fd].head, (WL)w);
1857
2126
 
1858
2127
  fd_change (EV_A_ fd, w->events & EV_IOFDSET | 1);
1859
2128
  w->events &= ~EV_IOFDSET;
2129
+
2130
+ EV_FREQUENT_CHECK;
1860
2131
  }
1861
2132
 
1862
2133
  void noinline
@@ -1866,12 +2137,16 @@ ev_io_stop (EV_P_ ev_io *w)
1866
2137
  if (expect_false (!ev_is_active (w)))
1867
2138
  return;
1868
2139
 
1869
- assert (("ev_io_start called with illegal fd (must stay constant after start!)", w->fd >= 0 && w->fd < anfdmax));
2140
+ assert (("ev_io_stop called with illegal fd (must stay constant after start!)", w->fd >= 0 && w->fd < anfdmax));
2141
+
2142
+ EV_FREQUENT_CHECK;
1870
2143
 
1871
2144
  wlist_del (&anfds[w->fd].head, (WL)w);
1872
2145
  ev_stop (EV_A_ (W)w);
1873
2146
 
1874
2147
  fd_change (EV_A_ w->fd, 1);
2148
+
2149
+ EV_FREQUENT_CHECK;
1875
2150
  }
1876
2151
 
1877
2152
  void noinline
@@ -1880,16 +2155,22 @@ ev_timer_start (EV_P_ ev_timer *w)
1880
2155
  if (expect_false (ev_is_active (w)))
1881
2156
  return;
1882
2157
 
1883
- ((WT)w)->at += mn_now;
2158
+ ev_at (w) += mn_now;
1884
2159
 
1885
2160
  assert (("ev_timer_start called with negative timer repeat value", w->repeat >= 0.));
1886
2161
 
1887
- ev_start (EV_A_ (W)w, ++timercnt);
1888
- array_needsize (WT, timers, timermax, timercnt, EMPTY2);
1889
- timers [timercnt - 1] = (WT)w;
1890
- upheap (timers, timercnt - 1);
2162
+ EV_FREQUENT_CHECK;
1891
2163
 
1892
- /*assert (("internal timer heap corruption", timers [((W)w)->active - 1] == w));*/
2164
+ ++timercnt;
2165
+ ev_start (EV_A_ (W)w, timercnt + HEAP0 - 1);
2166
+ array_needsize (ANHE, timers, timermax, ev_active (w) + 1, EMPTY2);
2167
+ ANHE_w (timers [ev_active (w)]) = (WT)w;
2168
+ ANHE_at_cache (timers [ev_active (w)]);
2169
+ upheap (timers, ev_active (w));
2170
+
2171
+ EV_FREQUENT_CHECK;
2172
+
2173
+ /*assert (("internal timer heap corruption", timers [ev_active (w)] == (WT)w));*/
1893
2174
  }
1894
2175
 
1895
2176
  void noinline
@@ -1899,19 +2180,25 @@ ev_timer_stop (EV_P_ ev_timer *w)
1899
2180
  if (expect_false (!ev_is_active (w)))
1900
2181
  return;
1901
2182
 
1902
- assert (("internal timer heap corruption", timers [((W)w)->active - 1] == (WT)w));
2183
+ EV_FREQUENT_CHECK;
1903
2184
 
1904
2185
  {
1905
- int active = ((W)w)->active;
2186
+ int active = ev_active (w);
2187
+
2188
+ assert (("internal timer heap corruption", ANHE_w (timers [active]) == (WT)w));
2189
+
2190
+ --timercnt;
1906
2191
 
1907
- if (expect_true (--active < --timercnt))
2192
+ if (expect_true (active < timercnt + HEAP0))
1908
2193
  {
1909
- timers [active] = timers [timercnt];
2194
+ timers [active] = timers [timercnt + HEAP0];
1910
2195
  adjustheap (timers, timercnt, active);
1911
2196
  }
1912
2197
  }
1913
2198
 
1914
- ((WT)w)->at -= mn_now;
2199
+ EV_FREQUENT_CHECK;
2200
+
2201
+ ev_at (w) -= mn_now;
1915
2202
 
1916
2203
  ev_stop (EV_A_ (W)w);
1917
2204
  }
@@ -1919,21 +2206,26 @@ ev_timer_stop (EV_P_ ev_timer *w)
1919
2206
  void noinline
1920
2207
  ev_timer_again (EV_P_ ev_timer *w)
1921
2208
  {
2209
+ EV_FREQUENT_CHECK;
2210
+
1922
2211
  if (ev_is_active (w))
1923
2212
  {
1924
2213
  if (w->repeat)
1925
2214
  {
1926
- ((WT)w)->at = mn_now + w->repeat;
1927
- adjustheap (timers, timercnt, ((W)w)->active - 1);
2215
+ ev_at (w) = mn_now + w->repeat;
2216
+ ANHE_at_cache (timers [ev_active (w)]);
2217
+ adjustheap (timers, timercnt, ev_active (w));
1928
2218
  }
1929
2219
  else
1930
2220
  ev_timer_stop (EV_A_ w);
1931
2221
  }
1932
2222
  else if (w->repeat)
1933
2223
  {
1934
- w->at = w->repeat;
2224
+ ev_at (w) = w->repeat;
1935
2225
  ev_timer_start (EV_A_ w);
1936
2226
  }
2227
+
2228
+ EV_FREQUENT_CHECK;
1937
2229
  }
1938
2230
 
1939
2231
  #if EV_PERIODIC_ENABLE
@@ -1944,22 +2236,28 @@ ev_periodic_start (EV_P_ ev_periodic *w)
1944
2236
  return;
1945
2237
 
1946
2238
  if (w->reschedule_cb)
1947
- ((WT)w)->at = w->reschedule_cb (w, ev_rt_now);
2239
+ ev_at (w) = w->reschedule_cb (w, ev_rt_now);
1948
2240
  else if (w->interval)
1949
2241
  {
1950
2242
  assert (("ev_periodic_start called with negative interval value", w->interval >= 0.));
1951
2243
  /* this formula differs from the one in periodic_reify because we do not always round up */
1952
- ((WT)w)->at = w->offset + ceil ((ev_rt_now - w->offset) / w->interval) * w->interval;
2244
+ ev_at (w) = w->offset + ceil ((ev_rt_now - w->offset) / w->interval) * w->interval;
1953
2245
  }
1954
2246
  else
1955
- ((WT)w)->at = w->offset;
2247
+ ev_at (w) = w->offset;
1956
2248
 
1957
- ev_start (EV_A_ (W)w, ++periodiccnt);
1958
- array_needsize (WT, periodics, periodicmax, periodiccnt, EMPTY2);
1959
- periodics [periodiccnt - 1] = (WT)w;
1960
- upheap (periodics, periodiccnt - 1);
2249
+ EV_FREQUENT_CHECK;
1961
2250
 
1962
- /*assert (("internal periodic heap corruption", periodics [((W)w)->active - 1] == w));*/
2251
+ ++periodiccnt;
2252
+ ev_start (EV_A_ (W)w, periodiccnt + HEAP0 - 1);
2253
+ array_needsize (ANHE, periodics, periodicmax, ev_active (w) + 1, EMPTY2);
2254
+ ANHE_w (periodics [ev_active (w)]) = (WT)w;
2255
+ ANHE_at_cache (periodics [ev_active (w)]);
2256
+ upheap (periodics, ev_active (w));
2257
+
2258
+ EV_FREQUENT_CHECK;
2259
+
2260
+ /*assert (("internal periodic heap corruption", ANHE_w (periodics [ev_active (w)]) == (WT)w));*/
1963
2261
  }
1964
2262
 
1965
2263
  void noinline
@@ -1969,18 +2267,24 @@ ev_periodic_stop (EV_P_ ev_periodic *w)
1969
2267
  if (expect_false (!ev_is_active (w)))
1970
2268
  return;
1971
2269
 
1972
- assert (("internal periodic heap corruption", periodics [((W)w)->active - 1] == (WT)w));
2270
+ EV_FREQUENT_CHECK;
1973
2271
 
1974
2272
  {
1975
- int active = ((W)w)->active;
2273
+ int active = ev_active (w);
2274
+
2275
+ assert (("internal periodic heap corruption", ANHE_w (periodics [active]) == (WT)w));
2276
+
2277
+ --periodiccnt;
1976
2278
 
1977
- if (expect_true (--active < --periodiccnt))
2279
+ if (expect_true (active < periodiccnt + HEAP0))
1978
2280
  {
1979
- periodics [active] = periodics [periodiccnt];
2281
+ periodics [active] = periodics [periodiccnt + HEAP0];
1980
2282
  adjustheap (periodics, periodiccnt, active);
1981
2283
  }
1982
2284
  }
1983
2285
 
2286
+ EV_FREQUENT_CHECK;
2287
+
1984
2288
  ev_stop (EV_A_ (W)w);
1985
2289
  }
1986
2290
 
@@ -2010,6 +2314,8 @@ ev_signal_start (EV_P_ ev_signal *w)
2010
2314
 
2011
2315
  evpipe_init (EV_A);
2012
2316
 
2317
+ EV_FREQUENT_CHECK;
2318
+
2013
2319
  {
2014
2320
  #ifndef _WIN32
2015
2321
  sigset_t full, prev;
@@ -2039,6 +2345,8 @@ ev_signal_start (EV_P_ ev_signal *w)
2039
2345
  sigaction (w->signum, &sa, 0);
2040
2346
  #endif
2041
2347
  }
2348
+
2349
+ EV_FREQUENT_CHECK;
2042
2350
  }
2043
2351
 
2044
2352
  void noinline
@@ -2048,11 +2356,15 @@ ev_signal_stop (EV_P_ ev_signal *w)
2048
2356
  if (expect_false (!ev_is_active (w)))
2049
2357
  return;
2050
2358
 
2359
+ EV_FREQUENT_CHECK;
2360
+
2051
2361
  wlist_del (&signals [w->signum - 1].head, (WL)w);
2052
2362
  ev_stop (EV_A_ (W)w);
2053
2363
 
2054
2364
  if (!signals [w->signum - 1].head)
2055
2365
  signal (w->signum, SIG_DFL);
2366
+
2367
+ EV_FREQUENT_CHECK;
2056
2368
  }
2057
2369
 
2058
2370
  void
@@ -2064,8 +2376,12 @@ ev_child_start (EV_P_ ev_child *w)
2064
2376
  if (expect_false (ev_is_active (w)))
2065
2377
  return;
2066
2378
 
2379
+ EV_FREQUENT_CHECK;
2380
+
2067
2381
  ev_start (EV_A_ (W)w, 1);
2068
2382
  wlist_add (&childs [w->pid & (EV_PID_HASHSIZE - 1)], (WL)w);
2383
+
2384
+ EV_FREQUENT_CHECK;
2069
2385
  }
2070
2386
 
2071
2387
  void
@@ -2075,8 +2391,12 @@ ev_child_stop (EV_P_ ev_child *w)
2075
2391
  if (expect_false (!ev_is_active (w)))
2076
2392
  return;
2077
2393
 
2394
+ EV_FREQUENT_CHECK;
2395
+
2078
2396
  wlist_del (&childs [w->pid & (EV_PID_HASHSIZE - 1)], (WL)w);
2079
2397
  ev_stop (EV_A_ (W)w);
2398
+
2399
+ EV_FREQUENT_CHECK;
2080
2400
  }
2081
2401
 
2082
2402
  #if EV_STAT_ENABLE
@@ -2104,6 +2424,8 @@ infy_add (EV_P_ ev_stat *w)
2104
2424
  ev_timer_start (EV_A_ &w->timer); /* this is not race-free, so we still need to recheck periodically */
2105
2425
 
2106
2426
  /* monitor some parent directory for speedup hints */
2427
+ /* note that exceeding the hardcoded limit is not a correctness issue, */
2428
+ /* but an efficiency issue only */
2107
2429
  if ((errno == ENOENT || errno == EACCES) && strlen (w->path) < 4096)
2108
2430
  {
2109
2431
  char path [4096];
@@ -2312,6 +2634,8 @@ ev_stat_start (EV_P_ ev_stat *w)
2312
2634
  ev_timer_start (EV_A_ &w->timer);
2313
2635
 
2314
2636
  ev_start (EV_A_ (W)w, 1);
2637
+
2638
+ EV_FREQUENT_CHECK;
2315
2639
  }
2316
2640
 
2317
2641
  void
@@ -2321,12 +2645,16 @@ ev_stat_stop (EV_P_ ev_stat *w)
2321
2645
  if (expect_false (!ev_is_active (w)))
2322
2646
  return;
2323
2647
 
2648
+ EV_FREQUENT_CHECK;
2649
+
2324
2650
  #if EV_USE_INOTIFY
2325
2651
  infy_del (EV_A_ w);
2326
2652
  #endif
2327
2653
  ev_timer_stop (EV_A_ &w->timer);
2328
2654
 
2329
2655
  ev_stop (EV_A_ (W)w);
2656
+
2657
+ EV_FREQUENT_CHECK;
2330
2658
  }
2331
2659
  #endif
2332
2660
 
@@ -2339,6 +2667,8 @@ ev_idle_start (EV_P_ ev_idle *w)
2339
2667
 
2340
2668
  pri_adjust (EV_A_ (W)w);
2341
2669
 
2670
+ EV_FREQUENT_CHECK;
2671
+
2342
2672
  {
2343
2673
  int active = ++idlecnt [ABSPRI (w)];
2344
2674
 
@@ -2348,6 +2678,8 @@ ev_idle_start (EV_P_ ev_idle *w)
2348
2678
  array_needsize (ev_idle *, idles [ABSPRI (w)], idlemax [ABSPRI (w)], active, EMPTY2);
2349
2679
  idles [ABSPRI (w)][active - 1] = w;
2350
2680
  }
2681
+
2682
+ EV_FREQUENT_CHECK;
2351
2683
  }
2352
2684
 
2353
2685
  void
@@ -2357,15 +2689,19 @@ ev_idle_stop (EV_P_ ev_idle *w)
2357
2689
  if (expect_false (!ev_is_active (w)))
2358
2690
  return;
2359
2691
 
2692
+ EV_FREQUENT_CHECK;
2693
+
2360
2694
  {
2361
- int active = ((W)w)->active;
2695
+ int active = ev_active (w);
2362
2696
 
2363
2697
  idles [ABSPRI (w)][active - 1] = idles [ABSPRI (w)][--idlecnt [ABSPRI (w)]];
2364
- ((W)idles [ABSPRI (w)][active - 1])->active = active;
2698
+ ev_active (idles [ABSPRI (w)][active - 1]) = active;
2365
2699
 
2366
2700
  ev_stop (EV_A_ (W)w);
2367
2701
  --idleall;
2368
2702
  }
2703
+
2704
+ EV_FREQUENT_CHECK;
2369
2705
  }
2370
2706
  #endif
2371
2707
 
@@ -2375,9 +2711,13 @@ ev_prepare_start (EV_P_ ev_prepare *w)
2375
2711
  if (expect_false (ev_is_active (w)))
2376
2712
  return;
2377
2713
 
2714
+ EV_FREQUENT_CHECK;
2715
+
2378
2716
  ev_start (EV_A_ (W)w, ++preparecnt);
2379
2717
  array_needsize (ev_prepare *, prepares, preparemax, preparecnt, EMPTY2);
2380
2718
  prepares [preparecnt - 1] = w;
2719
+
2720
+ EV_FREQUENT_CHECK;
2381
2721
  }
2382
2722
 
2383
2723
  void
@@ -2387,13 +2727,18 @@ ev_prepare_stop (EV_P_ ev_prepare *w)
2387
2727
  if (expect_false (!ev_is_active (w)))
2388
2728
  return;
2389
2729
 
2730
+ EV_FREQUENT_CHECK;
2731
+
2390
2732
  {
2391
- int active = ((W)w)->active;
2733
+ int active = ev_active (w);
2734
+
2392
2735
  prepares [active - 1] = prepares [--preparecnt];
2393
- ((W)prepares [active - 1])->active = active;
2736
+ ev_active (prepares [active - 1]) = active;
2394
2737
  }
2395
2738
 
2396
2739
  ev_stop (EV_A_ (W)w);
2740
+
2741
+ EV_FREQUENT_CHECK;
2397
2742
  }
2398
2743
 
2399
2744
  void
@@ -2402,9 +2747,13 @@ ev_check_start (EV_P_ ev_check *w)
2402
2747
  if (expect_false (ev_is_active (w)))
2403
2748
  return;
2404
2749
 
2750
+ EV_FREQUENT_CHECK;
2751
+
2405
2752
  ev_start (EV_A_ (W)w, ++checkcnt);
2406
2753
  array_needsize (ev_check *, checks, checkmax, checkcnt, EMPTY2);
2407
2754
  checks [checkcnt - 1] = w;
2755
+
2756
+ EV_FREQUENT_CHECK;
2408
2757
  }
2409
2758
 
2410
2759
  void
@@ -2414,13 +2763,18 @@ ev_check_stop (EV_P_ ev_check *w)
2414
2763
  if (expect_false (!ev_is_active (w)))
2415
2764
  return;
2416
2765
 
2766
+ EV_FREQUENT_CHECK;
2767
+
2417
2768
  {
2418
- int active = ((W)w)->active;
2769
+ int active = ev_active (w);
2770
+
2419
2771
  checks [active - 1] = checks [--checkcnt];
2420
- ((W)checks [active - 1])->active = active;
2772
+ ev_active (checks [active - 1]) = active;
2421
2773
  }
2422
2774
 
2423
2775
  ev_stop (EV_A_ (W)w);
2776
+
2777
+ EV_FREQUENT_CHECK;
2424
2778
  }
2425
2779
 
2426
2780
  #if EV_EMBED_ENABLE
@@ -2477,6 +2831,8 @@ ev_embed_start (EV_P_ ev_embed *w)
2477
2831
  ev_io_init (&w->io, embed_io_cb, backend_fd, EV_READ);
2478
2832
  }
2479
2833
 
2834
+ EV_FREQUENT_CHECK;
2835
+
2480
2836
  ev_set_priority (&w->io, ev_priority (w));
2481
2837
  ev_io_start (EV_A_ &w->io);
2482
2838
 
@@ -2487,6 +2843,8 @@ ev_embed_start (EV_P_ ev_embed *w)
2487
2843
  /*ev_idle_init (&w->idle, e,bed_idle_cb);*/
2488
2844
 
2489
2845
  ev_start (EV_A_ (W)w, 1);
2846
+
2847
+ EV_FREQUENT_CHECK;
2490
2848
  }
2491
2849
 
2492
2850
  void
@@ -2496,10 +2854,14 @@ ev_embed_stop (EV_P_ ev_embed *w)
2496
2854
  if (expect_false (!ev_is_active (w)))
2497
2855
  return;
2498
2856
 
2857
+ EV_FREQUENT_CHECK;
2858
+
2499
2859
  ev_io_stop (EV_A_ &w->io);
2500
2860
  ev_prepare_stop (EV_A_ &w->prepare);
2501
2861
 
2502
2862
  ev_stop (EV_A_ (W)w);
2863
+
2864
+ EV_FREQUENT_CHECK;
2503
2865
  }
2504
2866
  #endif
2505
2867
 
@@ -2510,9 +2872,13 @@ ev_fork_start (EV_P_ ev_fork *w)
2510
2872
  if (expect_false (ev_is_active (w)))
2511
2873
  return;
2512
2874
 
2875
+ EV_FREQUENT_CHECK;
2876
+
2513
2877
  ev_start (EV_A_ (W)w, ++forkcnt);
2514
2878
  array_needsize (ev_fork *, forks, forkmax, forkcnt, EMPTY2);
2515
2879
  forks [forkcnt - 1] = w;
2880
+
2881
+ EV_FREQUENT_CHECK;
2516
2882
  }
2517
2883
 
2518
2884
  void
@@ -2522,13 +2888,18 @@ ev_fork_stop (EV_P_ ev_fork *w)
2522
2888
  if (expect_false (!ev_is_active (w)))
2523
2889
  return;
2524
2890
 
2891
+ EV_FREQUENT_CHECK;
2892
+
2525
2893
  {
2526
- int active = ((W)w)->active;
2894
+ int active = ev_active (w);
2895
+
2527
2896
  forks [active - 1] = forks [--forkcnt];
2528
- ((W)forks [active - 1])->active = active;
2897
+ ev_active (forks [active - 1]) = active;
2529
2898
  }
2530
2899
 
2531
2900
  ev_stop (EV_A_ (W)w);
2901
+
2902
+ EV_FREQUENT_CHECK;
2532
2903
  }
2533
2904
  #endif
2534
2905
 
@@ -2541,9 +2912,13 @@ ev_async_start (EV_P_ ev_async *w)
2541
2912
 
2542
2913
  evpipe_init (EV_A);
2543
2914
 
2915
+ EV_FREQUENT_CHECK;
2916
+
2544
2917
  ev_start (EV_A_ (W)w, ++asynccnt);
2545
2918
  array_needsize (ev_async *, asyncs, asyncmax, asynccnt, EMPTY2);
2546
2919
  asyncs [asynccnt - 1] = w;
2920
+
2921
+ EV_FREQUENT_CHECK;
2547
2922
  }
2548
2923
 
2549
2924
  void
@@ -2553,13 +2928,18 @@ ev_async_stop (EV_P_ ev_async *w)
2553
2928
  if (expect_false (!ev_is_active (w)))
2554
2929
  return;
2555
2930
 
2931
+ EV_FREQUENT_CHECK;
2932
+
2556
2933
  {
2557
- int active = ((W)w)->active;
2934
+ int active = ev_active (w);
2935
+
2558
2936
  asyncs [active - 1] = asyncs [--asynccnt];
2559
- ((W)asyncs [active - 1])->active = active;
2937
+ ev_active (asyncs [active - 1]) = active;
2560
2938
  }
2561
2939
 
2562
2940
  ev_stop (EV_A_ (W)w);
2941
+
2942
+ EV_FREQUENT_CHECK;
2563
2943
  }
2564
2944
 
2565
2945
  void