cool.io 1.2.3-x86-mingw32 → 1.4.1-x86-mingw32

Sign up to get free protection for your applications and to get access to all the features.
Files changed (52) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +3 -0
  3. data/.travis.yml +3 -3
  4. data/CHANGES.md +35 -0
  5. data/README.md +1 -3
  6. data/Rakefile +11 -13
  7. data/cool.io.gemspec +3 -2
  8. data/examples/callbacked_echo_server.rb +24 -0
  9. data/ext/cool.io/extconf.rb +8 -24
  10. data/ext/cool.io/loop.c +1 -1
  11. data/ext/iobuffer/iobuffer.c +2 -0
  12. data/ext/libev/Changes +123 -4
  13. data/ext/libev/LICENSE +2 -1
  14. data/ext/libev/README +8 -8
  15. data/ext/libev/ev.c +313 -144
  16. data/ext/libev/ev.h +18 -10
  17. data/ext/libev/ev_epoll.c +4 -1
  18. data/ext/libev/ev_kqueue.c +1 -1
  19. data/ext/libev/ev_select.c +3 -4
  20. data/ext/libev/ev_vars.h +3 -2
  21. data/ext/libev/ev_win32.c +1 -1
  22. data/ext/libev/win_select.patch +115 -0
  23. data/lib/cool.io.rb +6 -4
  24. data/lib/cool.io/dns_resolver.rb +4 -10
  25. data/lib/cool.io/dsl.rb +6 -2
  26. data/lib/cool.io/io.rb +36 -16
  27. data/lib/cool.io/loop.rb +3 -11
  28. data/lib/cool.io/meta.rb +2 -2
  29. data/lib/cool.io/version.rb +4 -2
  30. data/spec/async_watcher_spec.rb +5 -5
  31. data/spec/dns_spec.rb +11 -7
  32. data/spec/iobuffer_spec.rb +147 -0
  33. data/spec/spec_helper.rb +2 -2
  34. data/spec/stat_watcher_spec.rb +3 -3
  35. data/spec/tcp_server_spec.rb +98 -5
  36. data/spec/tcp_socket_spec.rb +185 -0
  37. data/spec/timer_watcher_spec.rb +23 -19
  38. data/spec/udp_socket_spec.rb +58 -0
  39. data/spec/unix_listener_spec.rb +7 -7
  40. data/spec/unix_server_spec.rb +7 -7
  41. metadata +83 -103
  42. data/examples/httpclient.rb +0 -38
  43. data/ext/http11_client/.gitignore +0 -5
  44. data/ext/http11_client/LICENSE +0 -31
  45. data/ext/http11_client/ext_help.h +0 -14
  46. data/ext/http11_client/extconf.rb +0 -6
  47. data/ext/http11_client/http11_client.c +0 -300
  48. data/ext/http11_client/http11_parser.c +0 -403
  49. data/ext/http11_client/http11_parser.h +0 -48
  50. data/ext/http11_client/http11_parser.rl +0 -173
  51. data/lib/cool.io/eventmachine.rb +0 -234
  52. data/lib/cool.io/http_client.rb +0 -427
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: b6642bffcf0b40c0f50f0e8429748e4deda9988b
4
+ data.tar.gz: 8d90a3f730addf0a28bfb5f4a4d5e2a39b8cc4fa
5
+ SHA512:
6
+ metadata.gz: 4599d50e5cae6df39e5ed72e0410eb322ffa36747d34c7fde13655dfca4831dfd2d95d9a5158fee846150c73cd478ec8241b52caf74e9371c4711e674189ac3e
7
+ data.tar.gz: d2c3277b5fce654234033ad3a97d60c94ab8e1b80d2ed8cc7300fed171ba89ac04ed933db919d1d94245530437af1deab9568b1cbc5c9bcf19e1cc5c280f6be6
data/.gitignore CHANGED
@@ -24,3 +24,6 @@ tmp
24
24
 
25
25
  ## PROJECT::SPECIFIC
26
26
  conftest.dSYM
27
+
28
+ *.lock
29
+ .ruby-version
@@ -2,9 +2,9 @@ language: ruby
2
2
 
3
3
  rvm:
4
4
  - 1.9.3
5
- - 2.0.0
6
- - 2.1.0
7
- - 2.1.1
5
+ - 2.0
6
+ - 2.1
7
+ - 2.2
8
8
  - ruby-head
9
9
  - rbx
10
10
 
data/CHANGES.md CHANGED
@@ -1,3 +1,38 @@
1
+ 1.4.1
2
+ -----
3
+
4
+ * Use SleepEx instead of Sleep for better fix of process hung problem on windows environment
5
+ * Use rake-compiler-dock for cross compilation
6
+
7
+ 1.4.0
8
+ -----
9
+
10
+ * Update libev to 4.20
11
+ * Sleep in timeout instead of select on Windows
12
+
13
+ 1.3.1
14
+ -----
15
+
16
+ * Fix several bugs for JRuby support enhancement
17
+ * Fix deadlock bug on Windows environment
18
+ * Use RSpec3
19
+
20
+ 1.3.0
21
+ -----
22
+
23
+ * Block evaluation doesn't change self for keeping consistency with Ruby block
24
+ * Remove EventMachine emulation module
25
+ * Remove HttpClient
26
+ * DSL syntax is no longer available by default. Need to require 'cool.io/dsl' in user code
27
+ * Update libev to 4.19
28
+
29
+ 1.2.4
30
+ -----
31
+
32
+ * Fix a bug that #close for unconnected Socket doesn't detach all watchers (#33)
33
+ * Remove 1.8 support code
34
+ * Use standard library instead of own hosts list (#34)
35
+
1
36
  1.2.3
2
37
  -----
3
38
 
data/README.md CHANGED
@@ -86,15 +86,13 @@ core socket classes are also provided. Among these are:
86
86
  Cool.io::TCPSocket (or any subclass you wish to provide) whenever an incoming
87
87
  connection is received.
88
88
 
89
- * Cool.io::HttpClient - An HTTP/1.1 client with support for chunked encoding
90
- and streaming response processing through asynchronous callbacks.
91
-
92
89
  Example Program
93
90
  ---------------
94
91
 
95
92
  Cool.io provides a Sinatra-like DSL for authoring event-driven programs:
96
93
 
97
94
  require 'cool.io'
95
+ require 'cool.io/dsl'
98
96
 
99
97
  ADDR = '127.0.0.1'
100
98
  PORT = 4321
data/Rakefile CHANGED
@@ -27,7 +27,7 @@ spec = eval(File.read("cool.io.gemspec"))
27
27
  def configure_cross_compilation(ext)
28
28
  unless RUBY_PLATFORM =~ /mswin|mingw/
29
29
  ext.cross_compile = true
30
- ext.cross_platform = 'i386-mingw32'#['i386-mswin32-60', 'i386-mingw32']
30
+ ext.cross_platform = ['x86-mingw32', 'x64-mingw32']
31
31
  end
32
32
  end
33
33
 
@@ -36,23 +36,21 @@ Rake::ExtensionTask.new('iobuffer_ext', spec) do |ext|
36
36
  configure_cross_compilation(ext)
37
37
  end
38
38
 
39
- Rake::ExtensionTask.new('http11_client', spec) do |ext|
40
- ext.ext_dir = 'ext/http11_client'
41
- configure_cross_compilation(ext)
42
- end
43
-
44
39
  Rake::ExtensionTask.new('cool.io_ext', spec) do |ext|
45
40
  ext.ext_dir = 'ext/cool.io'
46
41
  configure_cross_compilation(ext)
47
42
  end
48
43
 
49
- # Rebuild parser Ragel
50
- task :http11_parser do
51
- Dir.chdir "ext/http11_client" do
52
- target = "http11_parser.c"
53
- File.unlink target if File.exist? target
54
- sh "ragel http11_parser.rl | rlgen-cd -G2 -o #{target}"
55
- raise "Failed to build C source" unless File.exist? target
44
+ # Note that this rake-compiler-dock rake task dose not support bundle install(1) --path option.
45
+ # Please use bundle install instead when you execute this rake task.
46
+ namespace :build do
47
+ desc 'Build gems for Windows per rake-compiler-dock'
48
+ task :windows do
49
+ require 'rake_compiler_dock'
50
+ RakeCompilerDock.sh <<-CROSS
51
+ bundle
52
+ rake cross native gem RUBY_CC_VERSION='2.0.0:2.1.6:2.2.2'
53
+ CROSS
56
54
  end
57
55
  end
58
56
 
@@ -15,14 +15,15 @@ Gem::Specification.new do |s|
15
15
  s.homepage = "http://coolio.github.com"
16
16
  s.summary = "A cool framework for doing high performance I/O in Ruby"
17
17
  s.description = "Cool.io provides a high performance event framework for Ruby which uses the libev C library"
18
- s.extensions = ["ext/cool.io/extconf.rb", "ext/http11_client/extconf.rb", "ext/iobuffer/extconf.rb"]
18
+ s.extensions = ["ext/cool.io/extconf.rb", "ext/iobuffer/extconf.rb"]
19
19
 
20
20
  s.files = `git ls-files`.split("\n")
21
21
  s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
22
22
  s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
23
23
  s.require_paths = ["lib"]
24
24
 
25
- s.add_development_dependency "rake-compiler", "~> 0.8.3"
25
+ s.add_development_dependency "rake-compiler", "~> 0.9.5"
26
+ s.add_development_dependency "rake-compiler-dock", "~> 0.4.3"
26
27
  s.add_development_dependency "rspec", ">= 2.13.0"
27
28
  s.add_development_dependency "rdoc", ">= 3.6.0"
28
29
  end
@@ -0,0 +1,24 @@
1
+ $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
2
+
3
+ require 'rubygems'
4
+ require 'cool.io'
5
+
6
+ ADDR = '127.0.0.1'
7
+ PORT = 4321
8
+
9
+ event_loop = Cool.io::Loop.default
10
+ server = Cool.io::TCPServer.new(ADDR, PORT) do |connection|
11
+ puts "#{connection.remote_addr}:#{connection.remote_port} connected"
12
+
13
+ connection.on_close do
14
+ puts "#{connection.remote_addr}:#{connection.remote_port} disconnected"
15
+ end
16
+
17
+ connection.on_read do |data|
18
+ connection.write data
19
+ end
20
+ end
21
+ server.attach(event_loop)
22
+
23
+ puts "Echo server listening on #{ADDR}:#{PORT}"
24
+ event_loop.run
@@ -4,25 +4,11 @@ libs = []
4
4
 
5
5
  $defs << "-DRUBY_VERSION_CODE=#{RUBY_VERSION.gsub(/\D/, '')}"
6
6
 
7
- if have_func('rb_thread_blocking_region')
8
- $defs << '-DHAVE_RB_THREAD_BLOCKING_REGION'
9
- end
10
-
11
- if have_func('rb_thread_call_without_gvl')
12
- $defs << '-DHAVE_RB_THEREAD_CALL_WITHOUT_GVL'
13
- end
14
-
15
- if have_func('rb_thread_alone')
16
- $defs << '-DHAVE_RB_THREAD_ALONE'
17
- end
18
-
19
- if have_func('rb_str_set_len')
20
- $defs << '-DHAVE_RB_STR_SET_LEN'
21
- end
22
-
23
- if have_library('rt', 'clock_gettime')
24
- libs << "-lrt"
25
- end
7
+ have_func('rb_thread_blocking_region')
8
+ have_func('rb_thread_call_without_gvl')
9
+ have_func('rb_thread_alone')
10
+ have_func('rb_str_set_len')
11
+ have_library('rt', 'clock_gettime')
26
12
 
27
13
  if have_header('sys/select.h')
28
14
  $defs << '-DEV_USE_SELECT'
@@ -44,9 +30,7 @@ if have_header('port.h')
44
30
  $defs << '-DEV_USE_PORT'
45
31
  end
46
32
 
47
- if have_header('sys/resource.h')
48
- $defs << '-DHAVE_SYS_RESOURCE_H'
49
- end
33
+ have_header('sys/resource.h')
50
34
 
51
35
  # ncpu detection specifics
52
36
  case RUBY_PLATFORM
@@ -64,14 +48,14 @@ dir_config('cool.io_ext')
64
48
  create_makefile('cool.io_ext')
65
49
 
66
50
  # win32 needs to link in "just the right order" for some reason or ioctlsocket will be mapped to an [inverted] ruby specific version. See libev mailing list for (not so helpful discussion--true cause I'm not sure, but this overcomes the symptom)
67
- if RUBY_PLATFORM =~ /mingw|win32/
51
+ if RUBY_PLATFORM =~ /mingw|mswin/
68
52
  makefile_contents = File.read 'Makefile'
69
53
 
70
54
  # "Init_cool could not be found" when loading cool.io.so.
71
55
  # I'm not sure why this is needed. But this line causes "1114 A dynamic link library (DLL) initialization routine failed." So I commented out this line.
72
56
  #makefile_contents.gsub! 'DLDFLAGS = ', 'DLDFLAGS = -export-all '
73
57
 
74
- makefile_contents.gsub! 'LIBS = $(LIBRUBYARG_SHARED)', 'LIBS = -lws2_32 $(LIBRUBYARG_SHARED)'
58
+ makefile_contents.gsub! /LIBS = (.*) (\S*ws2_32\S*)/i, 'LIBS = \\2 \\1'
75
59
  File.open('Makefile', 'w') { |f| f.write makefile_contents }
76
60
  end
77
61
 
@@ -81,7 +81,7 @@ static void Coolio_Loop_free(struct Coolio_Loop *loop)
81
81
 
82
82
  static VALUE Coolio_Loop_initialize(VALUE self)
83
83
  {
84
- Coolio_Loop_ev_loop_new(self, INT2NUM(0));
84
+ return Coolio_Loop_ev_loop_new(self, INT2NUM(0));
85
85
  }
86
86
 
87
87
  /* Wrapper for populating a Coolio_Loop struct with a new event loop */
@@ -11,7 +11,9 @@
11
11
 
12
12
  #include <string.h>
13
13
  #include <time.h>
14
+ #ifndef _MSC_VER
14
15
  #include <unistd.h>
16
+ #endif
15
17
  #include <errno.h>
16
18
 
17
19
  /* 1 GiB maximum buffer size */
@@ -1,5 +1,125 @@
1
1
  Revision history for libev, a high-performance and full-featured event loop.
2
2
 
3
+ TODO: ev_loop_wakeup
4
+ TODO: EV_STANDALONE == NO_HASSEL (do not use clock_gettime in ev_standalone)
5
+ TODO: faq, process a thing in each iteration
6
+ TODO: dbeugging tips, ev_verify, ev_init twice
7
+ TODO: ev_break for immediate exit (EVBREAK_NOW?)
8
+ TODO: ev_feed_child_event
9
+ TODO: document the special problem of signals around fork.
10
+ TODO: store pid for each signal
11
+ TODO: document file descriptor usage per loop
12
+ TODO: store loop pid_t and compare isndie signal handler,store 1 for same, 2 for differign pid, clean up in loop_fork
13
+ TODO: embed watchers need updating when fd changes
14
+ TODO: document portability requirements for atomic pointer access
15
+ TODO: possible cb aliasing?
16
+ TODO: document requirements for function pointers and calling conventions.
17
+
18
+ 4.20 Sat Jun 20 13:01:43 CEST 2015
19
+ - prefer noexcept over throw () with C++ 11.
20
+ - update ecb.h due to incompatibilities with c11.
21
+ - fix a potential aliasing issue when reading and writing
22
+ watcher callbacks.
23
+
24
+ 4.19 Thu Sep 25 08:18:25 CEST 2014
25
+ - ev.h wasn't valid C++ anymore, which tripped compilers other than
26
+ clang, msvc or gcc (analyzed by Raphael 'kena' Poss). Unfortunately,
27
+ C++ doesn't support typedefs for function pointers fully, so the affected
28
+ declarations have to spell out the types each time.
29
+ - when not using autoconf, tighten the check for clock_gettime and related
30
+ functionality.
31
+
32
+ 4.18 Fri Sep 5 17:55:26 CEST 2014
33
+ - events on files were not always generated properly with the
34
+ epoll backend (testcase by Assaf Inbal).
35
+ - mark event pipe fd as cloexec after a fork (analyzed by Sami Farin).
36
+ - (ecb) support m68k, m88k and sh (patch by Miod Vallat).
37
+ - use a reasonable fallback for EV_NSIG instead of erroring out
38
+ when we can't detect the signal set size.
39
+ - in the absence of autoconf, do not use the clock syscall
40
+ on glibc >= 2.17 (avoids the syscall AND -lrt on systems
41
+ doing clock_gettime in userspace).
42
+ - ensure extern "C" function pointers are used for externally-visible
43
+ loop callbacks (not watcher callbacks yet).
44
+ - (ecb) work around memory barriers and volatile apparently both being
45
+ broken in visual studio 2008 and later (analysed and patch by Nicolas Noble).
46
+
47
+ 4.15 Fri Mar 1 12:04:50 CET 2013
48
+ - destroying a non-default loop would stop the global waitpid
49
+ watcher (Denis Bilenko).
50
+ - queueing pending watchers of higher priority from a watcher now invokes
51
+ them in a timely fashion (reported by Denis Bilenko).
52
+ - add throw() to all libev functions that cannot throw exceptions, for
53
+ further code size decrease when compiling for C++.
54
+ - add throw () to callbacks that must not throw exceptions (allocator,
55
+ syserr, loop acquire/release, periodic reschedule cbs).
56
+ - fix event_base_loop return code, add event_get_callback, event_base_new,
57
+ event_base_get_method calls to improve libevent 1.x emulation and add
58
+ some libevent 2.x functionality (based on a patch by Jeff Davey).
59
+ - add more memory fences to fix a bug reported by Jeff Davey. Better
60
+ be overfenced than underprotected.
61
+ - ev_run now returns a boolean status (true meaning watchers are
62
+ still active).
63
+ - ev_once: undef EV_ERROR in ev_kqueue.c, to avoid clashing with
64
+ libev's EV_ERROR (reported by 191919).
65
+ - (ecb) add memory fence support for xlC (Darin McBride).
66
+ - (ecb) add memory fence support for gcc-mips (Anton Kirilov).
67
+ - (ecb) add memory fence support for gcc-alpha (Christian Weisgerber).
68
+ - work around some kernels losing file descriptors by leaking
69
+ the kqueue descriptor in the child.
70
+ - work around linux inotify not reporting IN_ATTRIB changes for directories
71
+ in many cases.
72
+ - include sys/syscall.h instead of plain syscall.h.
73
+ - check for io watcher loops in ev_verify, check for the most
74
+ common reported usage bug in ev_io_start.
75
+ - choose socket vs. WSASocket at compiletime using EV_USE_WSASOCKET.
76
+ - always use WSASend/WSARecv directly on windows, hoping that this
77
+ works in all cases (unlike read/write/send/recv...).
78
+ - try to detect signals around a fork faster (test program by
79
+ Denis Bilenko).
80
+ - work around recent glibc versions that leak memory in realloc.
81
+ - rename ev::embed::set to ev::embed::set_embed to avoid clashing
82
+ the watcher base set (loop) method.
83
+ - rewrite the async/signal pipe logic to always keep a valid fd, which
84
+ simplifies (and hopefully correctifies :) the race checking
85
+ on fork, at the cost of one extra fd.
86
+ - add fat, msdos, jffs2, ramfs, ntfs and btrfs to the list of
87
+ inotify-supporting filesystems.
88
+ - move orig_CFLAGS assignment to after AC_INIT, as newer autoconf
89
+ versions ignore it before
90
+ (https://bugzilla.redhat.com/show_bug.cgi?id=908096).
91
+ - add some untested android support.
92
+ - enum expressions must be of type int (reported by Juan Pablo L).
93
+
94
+ 4.11 Sat Feb 4 19:52:39 CET 2012
95
+ - INCOMPATIBLE CHANGE: ev_timer_again now clears the pending status, as
96
+ was documented already, but not implemented in the repeating case.
97
+ - new compiletime symbols: EV_NO_SMP and EV_NO_THREADS.
98
+ - fix a race where the workaround against the epoll fork bugs
99
+ caused signals to not be handled anymore.
100
+ - correct backend_fudge for most backends, and implement a windows
101
+ specific workaround to avoid looping because we call both
102
+ select and Sleep, both with different time resolutions.
103
+ - document range and guarantees of ev_sleep.
104
+ - document reasonable ranges for periodics interval and offset.
105
+ - rename backend_fudge to backend_mintime to avoid future confusion :)
106
+ - change the default periodic reschedule function to hopefully be more
107
+ exact and correct even in corner cases or in the far future.
108
+ - do not rely on -lm anymore: use it when available but use our
109
+ own floor () if it is missing. This should make it easier to embed,
110
+ as no external libraries are required.
111
+ - strategically import macros from libecb and mark rarely-used functions
112
+ as cache-cold (saving almost 2k code size on typical amd64 setups).
113
+ - add Symbols.ev and Symbols.event files, that were missing.
114
+ - fix backend_mintime value for epoll (was 1/1024, is 1/1000 now).
115
+ - fix #3 "be smart about timeouts" to not "deadlock" when
116
+ timeout == now, also improve the section overall.
117
+ - avoid "AVOIDING FINISHING BEFORE RETURNING" idiom.
118
+ - support new EV_API_STATIC mode to make all libev symbols
119
+ static.
120
+ - supply default CFLAGS of -g -O3 with gcc when original CFLAGS
121
+ were empty.
122
+
3
123
  4.04 Wed Feb 16 09:01:51 CET 2011
4
124
  - fix two problems in the native win32 backend, where reuse of fd's
5
125
  with different underlying handles caused handles not to be removed
@@ -94,7 +214,7 @@ Revision history for libev, a high-performance and full-featured event loop.
94
214
  that this is a race condition regardless of EV_SIGNALFD.
95
215
  - backport inotify code to C89.
96
216
  - inotify file descriptors could leak into child processes.
97
- - ev_stat watchers could keep an errornous extra ref on the loop,
217
+ - ev_stat watchers could keep an erroneous extra ref on the loop,
98
218
  preventing exit when unregistering all watchers (testcases
99
219
  provided by ry@tinyclouds.org).
100
220
  - implement EV_WIN32_HANDLE_TO_FD and EV_WIN32_CLOSE_FD configuration
@@ -162,8 +282,8 @@ Revision history for libev, a high-performance and full-featured event loop.
162
282
  Malek Hadj-Ali).
163
283
  - implement ev_suspend and ev_resume.
164
284
  - new EV_CUSTOM revents flag for use by applications.
165
- - add documentation section about priorites.
166
- - add a glossary to the dcoumentation.
285
+ - add documentation section about priorities.
286
+ - add a glossary to the documentation.
167
287
  - extend the ev_fork description slightly.
168
288
  - optimize a jump out of call_pending.
169
289
 
@@ -385,4 +505,3 @@ Revision history for libev, a high-performance and full-featured event loop.
385
505
 
386
506
  0.1 Wed Oct 31 21:31:48 CET 2007
387
507
  - original version; hacked together in <24h.
388
-
@@ -1,4 +1,5 @@
1
- All files in libev are Copyright (C)2007,2008,2009 Marc Alexander Lehmann.
1
+ All files in libev are
2
+ Copyright (c)2007,2008,2009,2010,2011,2012,2013 Marc Alexander Lehmann.
2
3
 
3
4
  Redistribution and use in source and binary forms, with or without
4
5
  modification, are permitted provided that the following conditions are
@@ -24,23 +24,23 @@ ABOUT
24
24
  - relative timers/timeouts (handle time jumps).
25
25
  - fast intra-thread communication between multiple
26
26
  event loops (with optional fast linux eventfd backend).
27
- - extremely easy to embed.
28
- - very small codebase, no bloated library.
27
+ - extremely easy to embed (fully documented, no dependencies,
28
+ autoconf supported but optional).
29
+ - very small codebase, no bloated library, simple code.
29
30
  - fully extensible by being able to plug into the event loop,
30
31
  integrate other event loops, integrate other event loop users.
31
32
  - very little memory use (small watchers, small event loop data).
32
33
  - optional C++ interface allowing method and function callbacks
33
34
  at no extra memory or runtime overhead.
34
35
  - optional Perl interface with similar characteristics (capable
35
- of running Glib/Gtk2 on libev, interfaces with Net::SNMP and
36
- libadns).
36
+ of running Glib/Gtk2 on libev).
37
37
  - support for other languages (multiple C++ interfaces, D, Ruby,
38
38
  Python) available from third-parties.
39
39
 
40
- Examples of programs that embed libev: the EV perl module,
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.
40
+ Examples of programs that embed libev: the EV perl module, node.js,
41
+ auditd, rxvt-unicode, gvpe (GNU Virtual Private Ethernet), the
42
+ Deliantra MMORPG server (http://www.deliantra.net/), Rubinius (a
43
+ next-generation Ruby VM), the Ebb web server, the Rev event toolkit.
44
44
 
45
45
 
46
46
  CONTRIBUTORS
@@ -1,7 +1,7 @@
1
1
  /*
2
2
  * libev event processing core, watcher management
3
3
  *
4
- * Copyright (c) 2007,2008,2009,2010,2011,2012 Marc Alexander Lehmann <libev@schmorp.de>
4
+ * Copyright (c) 2007,2008,2009,2010,2011,2012,2013 Marc Alexander Lehmann <libev@schmorp.de>
5
5
  * All rights reserved.
6
6
  *
7
7
  * Redistribution and use in source and binary forms, with or without modifica-
@@ -49,11 +49,11 @@
49
49
  # include "config.h"
50
50
  # endif
51
51
 
52
- #if HAVE_FLOOR
53
- # ifndef EV_USE_FLOOR
54
- # define EV_USE_FLOOR 1
52
+ # if HAVE_FLOOR
53
+ # ifndef EV_USE_FLOOR
54
+ # define EV_USE_FLOOR 1
55
+ # endif
55
56
  # endif
56
- #endif
57
57
 
58
58
  # if HAVE_CLOCK_SYSCALL
59
59
  # ifndef EV_USE_CLOCK_SYSCALL
@@ -111,7 +111,7 @@
111
111
  # undef EV_USE_POLL
112
112
  # define EV_USE_POLL 0
113
113
  # endif
114
-
114
+
115
115
  # if HAVE_EPOLL_CTL && HAVE_SYS_EPOLL_H
116
116
  # ifndef EV_USE_EPOLL
117
117
  # define EV_USE_EPOLL EV_FEATURE_BACKENDS
@@ -120,7 +120,7 @@
120
120
  # undef EV_USE_EPOLL
121
121
  # define EV_USE_EPOLL 0
122
122
  # endif
123
-
123
+
124
124
  # if HAVE_KQUEUE && HAVE_SYS_EVENT_H
125
125
  # ifndef EV_USE_KQUEUE
126
126
  # define EV_USE_KQUEUE EV_FEATURE_BACKENDS
@@ -129,7 +129,7 @@
129
129
  # undef EV_USE_KQUEUE
130
130
  # define EV_USE_KQUEUE 0
131
131
  # endif
132
-
132
+
133
133
  # if HAVE_PORT_H && HAVE_PORT_CREATE
134
134
  # ifndef EV_USE_PORT
135
135
  # define EV_USE_PORT EV_FEATURE_BACKENDS
@@ -165,7 +165,7 @@
165
165
  # undef EV_USE_EVENTFD
166
166
  # define EV_USE_EVENTFD 0
167
167
  # endif
168
-
168
+
169
169
  #endif
170
170
 
171
171
  #include <stdlib.h>
@@ -247,10 +247,7 @@
247
247
  #elif defined _sys_nsig
248
248
  # define EV_NSIG (_sys_nsig) /* Solaris 2.5 */
249
249
  #else
250
- # error "unable to find value for NSIG, please report"
251
- /* to make it compile regardless, just remove the above line, */
252
- /* but consider reporting it, too! :) */
253
- # define EV_NSIG 65
250
+ # define EV_NSIG (8 * sizeof (sigset_t) + 1)
254
251
  #endif
255
252
 
256
253
  #ifndef EV_USE_FLOOR
@@ -258,13 +255,22 @@
258
255
  #endif
259
256
 
260
257
  #ifndef EV_USE_CLOCK_SYSCALL
261
- # if __linux && __GLIBC__ >= 2
258
+ # if __linux && __GLIBC__ == 2 && __GLIBC_MINOR__ < 17
262
259
  # define EV_USE_CLOCK_SYSCALL EV_FEATURE_OS
263
260
  # else
264
261
  # define EV_USE_CLOCK_SYSCALL 0
265
262
  # endif
266
263
  #endif
267
264
 
265
+ #if !(_POSIX_TIMERS > 0)
266
+ # ifndef EV_USE_MONOTONIC
267
+ # define EV_USE_MONOTONIC 0
268
+ # endif
269
+ # ifndef EV_USE_REALTIME
270
+ # define EV_USE_REALTIME 0
271
+ # endif
272
+ #endif
273
+
268
274
  #ifndef EV_USE_MONOTONIC
269
275
  # if defined _POSIX_MONOTONIC_CLOCK && _POSIX_MONOTONIC_CLOCK >= 0
270
276
  # define EV_USE_MONOTONIC EV_FEATURE_OS
@@ -491,7 +497,7 @@ struct signalfd_siginfo
491
497
  /*
492
498
  * libecb - http://software.schmorp.de/pkg/libecb
493
499
  *
494
- * Copyright (©) 2009-2012 Marc Alexander Lehmann <libecb@schmorp.de>
500
+ * Copyright (©) 2009-2015 Marc Alexander Lehmann <libecb@schmorp.de>
495
501
  * Copyright (©) 2011 Emanuele Giaquinta
496
502
  * All rights reserved.
497
503
  *
@@ -515,13 +521,24 @@ struct signalfd_siginfo
515
521
  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTH-
516
522
  * ERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
517
523
  * OF THE POSSIBILITY OF SUCH DAMAGE.
524
+ *
525
+ * Alternatively, the contents of this file may be used under the terms of
526
+ * the GNU General Public License ("GPL") version 2 or any later version,
527
+ * in which case the provisions of the GPL are applicable instead of
528
+ * the above. If you wish to allow the use of your version of this file
529
+ * only under the terms of the GPL and not to allow others to use your
530
+ * version of this file under the BSD license, indicate your decision
531
+ * by deleting the provisions above and replace them with the notice
532
+ * and other provisions required by the GPL. If you do not delete the
533
+ * provisions above, a recipient may use your version of this file under
534
+ * either the BSD or the GPL.
518
535
  */
519
536
 
520
537
  #ifndef ECB_H
521
538
  #define ECB_H
522
539
 
523
540
  /* 16 bits major, 16 bits minor */
524
- #define ECB_VERSION 0x00010003
541
+ #define ECB_VERSION 0x00010004
525
542
 
526
543
  #ifdef _WIN32
527
544
  typedef signed char int8_t;
@@ -555,9 +572,12 @@ struct signalfd_siginfo
555
572
  #endif
556
573
  #endif
557
574
 
575
+ #define ECB_GCC_AMD64 (__amd64 || __amd64__ || __x86_64 || __x86_64__)
576
+ #define ECB_MSVC_AMD64 (_M_AMD64 || _M_X64)
577
+
558
578
  /* work around x32 idiocy by defining proper macros */
559
- #if __x86_64 || _M_AMD64
560
- #if __ILP32
579
+ #if ECB_GCC_AMD64 || ECB_MSVC_AMD64
580
+ #if _ILP32
561
581
  #define ECB_AMD64_X32 1
562
582
  #else
563
583
  #define ECB_AMD64 1
@@ -571,20 +591,40 @@ struct signalfd_siginfo
571
591
  * we try to detect these and simply assume they are not gcc - if they have
572
592
  * an issue with that they should have done it right in the first place.
573
593
  */
574
- #ifndef ECB_GCC_VERSION
575
- #if !defined __GNUC_MINOR__ || defined __INTEL_COMPILER || defined __SUNPRO_C || defined __SUNPRO_CC || defined __llvm__ || defined __clang__
576
- #define ECB_GCC_VERSION(major,minor) 0
577
- #else
578
- #define ECB_GCC_VERSION(major,minor) (__GNUC__ > (major) || (__GNUC__ == (major) && __GNUC_MINOR__ >= (minor)))
579
- #endif
594
+ #if !defined __GNUC_MINOR__ || defined __INTEL_COMPILER || defined __SUNPRO_C || defined __SUNPRO_CC || defined __llvm__ || defined __clang__
595
+ #define ECB_GCC_VERSION(major,minor) 0
596
+ #else
597
+ #define ECB_GCC_VERSION(major,minor) (__GNUC__ > (major) || (__GNUC__ == (major) && __GNUC_MINOR__ >= (minor)))
598
+ #endif
599
+
600
+ #define ECB_CLANG_VERSION(major,minor) (__clang_major__ > (major) || (__clang_major__ == (major) && __clang_minor__ >= (minor)))
601
+
602
+ #if __clang__ && defined __has_builtin
603
+ #define ECB_CLANG_BUILTIN(x) __has_builtin (x)
604
+ #else
605
+ #define ECB_CLANG_BUILTIN(x) 0
606
+ #endif
607
+
608
+ #if __clang__ && defined __has_extension
609
+ #define ECB_CLANG_EXTENSION(x) __has_extension (x)
610
+ #else
611
+ #define ECB_CLANG_EXTENSION(x) 0
580
612
  #endif
581
613
 
582
- #define ECB_C (__STDC__+0) /* this assumes that __STDC__ is either empty or a number */
583
- #define ECB_C99 (__STDC_VERSION__ >= 199901L)
584
- #define ECB_C11 (__STDC_VERSION__ >= 201112L)
585
614
  #define ECB_CPP (__cplusplus+0)
586
615
  #define ECB_CPP11 (__cplusplus >= 201103L)
587
616
 
617
+ #if ECB_CPP
618
+ #define ECB_C 0
619
+ #define ECB_STDC_VERSION 0
620
+ #else
621
+ #define ECB_C 1
622
+ #define ECB_STDC_VERSION __STDC_VERSION__
623
+ #endif
624
+
625
+ #define ECB_C99 (ECB_STDC_VERSION >= 199901L)
626
+ #define ECB_C11 (ECB_STDC_VERSION >= 201112L)
627
+
588
628
  #if ECB_CPP
589
629
  #define ECB_EXTERN_C extern "C"
590
630
  #define ECB_EXTERN_C_BEG ECB_EXTERN_C {
@@ -608,13 +648,18 @@ struct signalfd_siginfo
608
648
  #define ECB_MEMORY_FENCE do { } while (0)
609
649
  #endif
610
650
 
651
+ /* http://www-01.ibm.com/support/knowledgecenter/SSGH3R_13.1.0/com.ibm.xlcpp131.aix.doc/compiler_ref/compiler_builtins.html */
652
+ #if __xlC__ && ECB_CPP
653
+ #include <builtins.h>
654
+ #endif
655
+
611
656
  #ifndef ECB_MEMORY_FENCE
612
657
  #if ECB_GCC_VERSION(2,5) || defined __INTEL_COMPILER || (__llvm__ && __GNUC__) || __SUNPRO_C >= 0x5110 || __SUNPRO_CC >= 0x5110
613
658
  #if __i386 || __i386__
614
659
  #define ECB_MEMORY_FENCE __asm__ __volatile__ ("lock; orb $0, -1(%%esp)" : : : "memory")
615
660
  #define ECB_MEMORY_FENCE_ACQUIRE __asm__ __volatile__ ("" : : : "memory")
616
661
  #define ECB_MEMORY_FENCE_RELEASE __asm__ __volatile__ ("")
617
- #elif __amd64 || __amd64__ || __x86_64 || __x86_64__
662
+ #elif ECB_GCC_AMD64
618
663
  #define ECB_MEMORY_FENCE __asm__ __volatile__ ("mfence" : : : "memory")
619
664
  #define ECB_MEMORY_FENCE_ACQUIRE __asm__ __volatile__ ("" : : : "memory")
620
665
  #define ECB_MEMORY_FENCE_RELEASE __asm__ __volatile__ ("")
@@ -626,14 +671,18 @@ struct signalfd_siginfo
626
671
  #elif defined __ARM_ARCH_7__ || defined __ARM_ARCH_7A__ \
627
672
  || defined __ARM_ARCH_7M__ || defined __ARM_ARCH_7R__
628
673
  #define ECB_MEMORY_FENCE __asm__ __volatile__ ("dmb" : : : "memory")
629
- #elif __sparc || __sparc__
674
+ #elif __aarch64__
675
+ #define ECB_MEMORY_FENCE __asm__ __volatile__ ("dmb ish" : : : "memory")
676
+ #elif (__sparc || __sparc__) && !__sparcv8
630
677
  #define ECB_MEMORY_FENCE __asm__ __volatile__ ("membar #LoadStore | #LoadLoad | #StoreStore | #StoreLoad" : : : "memory")
631
678
  #define ECB_MEMORY_FENCE_ACQUIRE __asm__ __volatile__ ("membar #LoadStore | #LoadLoad" : : : "memory")
632
679
  #define ECB_MEMORY_FENCE_RELEASE __asm__ __volatile__ ("membar #LoadStore | #StoreStore")
633
680
  #elif defined __s390__ || defined __s390x__
634
681
  #define ECB_MEMORY_FENCE __asm__ __volatile__ ("bcr 15,0" : : : "memory")
635
682
  #elif defined __mips__
636
- #define ECB_MEMORY_FENCE __asm__ __volatile__ ("sync" : : : "memory")
683
+ /* GNU/Linux emulates sync on mips1 architectures, so we force its use */
684
+ /* anybody else who still uses mips1 is supposed to send in their version, with detection code. */
685
+ #define ECB_MEMORY_FENCE __asm__ __volatile__ (".set mips2; sync; .set mips0" : : : "memory")
637
686
  #elif defined __alpha__
638
687
  #define ECB_MEMORY_FENCE __asm__ __volatile__ ("mb" : : : "memory")
639
688
  #elif defined __hppa__
@@ -641,6 +690,12 @@ struct signalfd_siginfo
641
690
  #define ECB_MEMORY_FENCE_RELEASE __asm__ __volatile__ ("")
642
691
  #elif defined __ia64__
643
692
  #define ECB_MEMORY_FENCE __asm__ __volatile__ ("mf" : : : "memory")
693
+ #elif defined __m68k__
694
+ #define ECB_MEMORY_FENCE __asm__ __volatile__ ("" : : : "memory")
695
+ #elif defined __m88k__
696
+ #define ECB_MEMORY_FENCE __asm__ __volatile__ ("tb1 0,%%r0,128" : : : "memory")
697
+ #elif defined __sh__
698
+ #define ECB_MEMORY_FENCE __asm__ __volatile__ ("" : : : "memory")
644
699
  #endif
645
700
  #endif
646
701
  #endif
@@ -649,18 +704,23 @@ struct signalfd_siginfo
649
704
  #if ECB_GCC_VERSION(4,7)
650
705
  /* see comment below (stdatomic.h) about the C11 memory model. */
651
706
  #define ECB_MEMORY_FENCE __atomic_thread_fence (__ATOMIC_SEQ_CST)
707
+ #define ECB_MEMORY_FENCE_ACQUIRE __atomic_thread_fence (__ATOMIC_ACQUIRE)
708
+ #define ECB_MEMORY_FENCE_RELEASE __atomic_thread_fence (__ATOMIC_RELEASE)
652
709
 
653
- /* The __has_feature syntax from clang is so misdesigned that we cannot use it
654
- * without risking compile time errors with other compilers. We *could*
655
- * define our own ecb_clang_has_feature, but I just can't be bothered to work
656
- * around this shit time and again.
657
- * #elif defined __clang && __has_feature (cxx_atomic)
658
- * // see comment below (stdatomic.h) about the C11 memory model.
659
- * #define ECB_MEMORY_FENCE __c11_atomic_thread_fence (__ATOMIC_SEQ_CST)
660
- */
710
+ #elif ECB_CLANG_EXTENSION(c_atomic)
711
+ /* see comment below (stdatomic.h) about the C11 memory model. */
712
+ #define ECB_MEMORY_FENCE __c11_atomic_thread_fence (__ATOMIC_SEQ_CST)
713
+ #define ECB_MEMORY_FENCE_ACQUIRE __c11_atomic_thread_fence (__ATOMIC_ACQUIRE)
714
+ #define ECB_MEMORY_FENCE_RELEASE __c11_atomic_thread_fence (__ATOMIC_RELEASE)
661
715
 
662
716
  #elif ECB_GCC_VERSION(4,4) || defined __INTEL_COMPILER || defined __clang__
663
717
  #define ECB_MEMORY_FENCE __sync_synchronize ()
718
+ #elif _MSC_VER >= 1500 /* VC++ 2008 */
719
+ /* apparently, microsoft broke all the memory barrier stuff in Visual Studio 2008... */
720
+ #pragma intrinsic(_ReadBarrier,_WriteBarrier,_ReadWriteBarrier)
721
+ #define ECB_MEMORY_FENCE _ReadWriteBarrier (); MemoryBarrier()
722
+ #define ECB_MEMORY_FENCE_ACQUIRE _ReadWriteBarrier (); MemoryBarrier() /* according to msdn, _ReadBarrier is not a load fence */
723
+ #define ECB_MEMORY_FENCE_RELEASE _WriteBarrier (); MemoryBarrier()
664
724
  #elif _MSC_VER >= 1400 /* VC++ 2005 */
665
725
  #pragma intrinsic(_ReadBarrier,_WriteBarrier,_ReadWriteBarrier)
666
726
  #define ECB_MEMORY_FENCE _ReadWriteBarrier ()
@@ -690,6 +750,8 @@ struct signalfd_siginfo
690
750
  /* for most usages, or gcc and clang have a bug */
691
751
  /* I *currently* lean towards the latter, and inefficiently implement */
692
752
  /* all three of ecb's fences as a seq_cst fence */
753
+ /* Update, gcc-4.8 generates mfence for all c++ fences, but nothing */
754
+ /* for all __atomic_thread_fence's except seq_cst */
693
755
  #define ECB_MEMORY_FENCE atomic_thread_fence (memory_order_seq_cst)
694
756
  #endif
695
757
  #endif
@@ -722,7 +784,7 @@ struct signalfd_siginfo
722
784
 
723
785
  /*****************************************************************************/
724
786
 
725
- #if __cplusplus
787
+ #if ECB_CPP
726
788
  #define ecb_inline static inline
727
789
  #elif ECB_GCC_VERSION(2,5)
728
790
  #define ecb_inline static __inline__
@@ -746,35 +808,79 @@ typedef int ecb_bool;
746
808
  #define ECB_CONCAT(a, b) ECB_CONCAT_(a, b)
747
809
  #define ECB_STRINGIFY_(a) # a
748
810
  #define ECB_STRINGIFY(a) ECB_STRINGIFY_(a)
811
+ #define ECB_STRINGIFY_EXPR(expr) ((expr), ECB_STRINGIFY_ (expr))
749
812
 
750
813
  #define ecb_function_ ecb_inline
751
814
 
752
- #if ECB_GCC_VERSION(3,1)
753
- #define ecb_attribute(attrlist) __attribute__(attrlist)
754
- #define ecb_is_constant(expr) __builtin_constant_p (expr)
755
- #define ecb_expect(expr,value) __builtin_expect ((expr),(value))
756
- #define ecb_prefetch(addr,rw,locality) __builtin_prefetch (addr, rw, locality)
815
+ #if ECB_GCC_VERSION(3,1) || ECB_CLANG_VERSION(2,8)
816
+ #define ecb_attribute(attrlist) __attribute__ (attrlist)
757
817
  #else
758
818
  #define ecb_attribute(attrlist)
819
+ #endif
820
+
821
+ #if ECB_GCC_VERSION(3,1) || ECB_CLANG_BUILTIN(__builtin_constant_p)
822
+ #define ecb_is_constant(expr) __builtin_constant_p (expr)
823
+ #else
824
+ /* possible C11 impl for integral types
825
+ typedef struct ecb_is_constant_struct ecb_is_constant_struct;
826
+ #define ecb_is_constant(expr) _Generic ((1 ? (struct ecb_is_constant_struct *)0 : (void *)((expr) - (expr)), ecb_is_constant_struct *: 0, default: 1)) */
827
+
759
828
  #define ecb_is_constant(expr) 0
829
+ #endif
830
+
831
+ #if ECB_GCC_VERSION(3,1) || ECB_CLANG_BUILTIN(__builtin_expect)
832
+ #define ecb_expect(expr,value) __builtin_expect ((expr),(value))
833
+ #else
760
834
  #define ecb_expect(expr,value) (expr)
835
+ #endif
836
+
837
+ #if ECB_GCC_VERSION(3,1) || ECB_CLANG_BUILTIN(__builtin_prefetch)
838
+ #define ecb_prefetch(addr,rw,locality) __builtin_prefetch (addr, rw, locality)
839
+ #else
761
840
  #define ecb_prefetch(addr,rw,locality)
762
841
  #endif
763
842
 
764
843
  /* no emulation for ecb_decltype */
765
- #if ECB_GCC_VERSION(4,5)
766
- #define ecb_decltype(x) __decltype(x)
767
- #elif ECB_GCC_VERSION(3,0)
768
- #define ecb_decltype(x) __typeof(x)
844
+ #if ECB_CPP11
845
+ // older implementations might have problems with decltype(x)::type, work around it
846
+ template<class T> struct ecb_decltype_t { typedef T type; };
847
+ #define ecb_decltype(x) ecb_decltype_t<decltype (x)>::type
848
+ #elif ECB_GCC_VERSION(3,0) || ECB_CLANG_VERSION(2,8)
849
+ #define ecb_decltype(x) __typeof__ (x)
850
+ #endif
851
+
852
+ #if _MSC_VER >= 1300
853
+ #define ecb_deprecated __declspec (deprecated)
854
+ #else
855
+ #define ecb_deprecated ecb_attribute ((__deprecated__))
856
+ #endif
857
+
858
+ #if _MSC_VER >= 1500
859
+ #define ecb_deprecated_message(msg) __declspec (deprecated (msg))
860
+ #elif ECB_GCC_VERSION(4,5)
861
+ #define ecb_deprecated_message(msg) ecb_attribute ((__deprecated__ (msg))
862
+ #else
863
+ #define ecb_deprecated_message(msg) ecb_deprecated
864
+ #endif
865
+
866
+ #if _MSC_VER >= 1400
867
+ #define ecb_noinline __declspec (noinline)
868
+ #else
869
+ #define ecb_noinline ecb_attribute ((__noinline__))
769
870
  #endif
770
871
 
771
- #define ecb_noinline ecb_attribute ((__noinline__))
772
872
  #define ecb_unused ecb_attribute ((__unused__))
773
873
  #define ecb_const ecb_attribute ((__const__))
774
874
  #define ecb_pure ecb_attribute ((__pure__))
775
875
 
776
- #if ECB_C11
876
+ #if ECB_C11 || __IBMC_NORETURN
877
+ /* http://www-01.ibm.com/support/knowledgecenter/SSGH3R_13.1.0/com.ibm.xlcpp131.aix.doc/language_ref/noreturn.html */
777
878
  #define ecb_noreturn _Noreturn
879
+ #elif ECB_CPP11
880
+ #define ecb_noreturn [[noreturn]]
881
+ #elif _MSC_VER >= 1200
882
+ /* http://msdn.microsoft.com/en-us/library/k6ktzx3s.aspx */
883
+ #define ecb_noreturn __declspec (noreturn)
778
884
  #else
779
885
  #define ecb_noreturn ecb_attribute ((__noreturn__))
780
886
  #endif
@@ -799,7 +905,10 @@ typedef int ecb_bool;
799
905
  #define ecb_unlikely(expr) ecb_expect_false (expr)
800
906
 
801
907
  /* count trailing zero bits and count # of one bits */
802
- #if ECB_GCC_VERSION(3,4)
908
+ #if ECB_GCC_VERSION(3,4) \
909
+ || (ECB_CLANG_BUILTIN(__builtin_clz) && ECB_CLANG_BUILTIN(__builtin_clzll) \
910
+ && ECB_CLANG_BUILTIN(__builtin_ctz) && ECB_CLANG_BUILTIN(__builtin_ctzll) \
911
+ && ECB_CLANG_BUILTIN(__builtin_popcount))
803
912
  /* we assume int == 32 bit, long == 32 or 64 bit and long long == 64 bit */
804
913
  #define ecb_ld32(x) (__builtin_clz (x) ^ 31)
805
914
  #define ecb_ld64(x) (__builtin_clzll (x) ^ 63)
@@ -808,8 +917,8 @@ typedef int ecb_bool;
808
917
  #define ecb_popcount32(x) __builtin_popcount (x)
809
918
  /* no popcountll */
810
919
  #else
811
- ecb_function_ int ecb_ctz32 (uint32_t x) ecb_const;
812
- ecb_function_ int
920
+ ecb_function_ ecb_const int ecb_ctz32 (uint32_t x);
921
+ ecb_function_ ecb_const int
813
922
  ecb_ctz32 (uint32_t x)
814
923
  {
815
924
  int r = 0;
@@ -833,16 +942,16 @@ typedef int ecb_bool;
833
942
  return r;
834
943
  }
835
944
 
836
- ecb_function_ int ecb_ctz64 (uint64_t x) ecb_const;
837
- ecb_function_ int
945
+ ecb_function_ ecb_const int ecb_ctz64 (uint64_t x);
946
+ ecb_function_ ecb_const int
838
947
  ecb_ctz64 (uint64_t x)
839
948
  {
840
949
  int shift = x & 0xffffffffU ? 0 : 32;
841
950
  return ecb_ctz32 (x >> shift) + shift;
842
951
  }
843
952
 
844
- ecb_function_ int ecb_popcount32 (uint32_t x) ecb_const;
845
- ecb_function_ int
953
+ ecb_function_ ecb_const int ecb_popcount32 (uint32_t x);
954
+ ecb_function_ ecb_const int
846
955
  ecb_popcount32 (uint32_t x)
847
956
  {
848
957
  x -= (x >> 1) & 0x55555555;
@@ -853,8 +962,8 @@ typedef int ecb_bool;
853
962
  return x >> 24;
854
963
  }
855
964
 
856
- ecb_function_ int ecb_ld32 (uint32_t x) ecb_const;
857
- ecb_function_ int ecb_ld32 (uint32_t x)
965
+ ecb_function_ ecb_const int ecb_ld32 (uint32_t x);
966
+ ecb_function_ ecb_const int ecb_ld32 (uint32_t x)
858
967
  {
859
968
  int r = 0;
860
969
 
@@ -867,8 +976,8 @@ typedef int ecb_bool;
867
976
  return r;
868
977
  }
869
978
 
870
- ecb_function_ int ecb_ld64 (uint64_t x) ecb_const;
871
- ecb_function_ int ecb_ld64 (uint64_t x)
979
+ ecb_function_ ecb_const int ecb_ld64 (uint64_t x);
980
+ ecb_function_ ecb_const int ecb_ld64 (uint64_t x)
872
981
  {
873
982
  int r = 0;
874
983
 
@@ -878,20 +987,20 @@ typedef int ecb_bool;
878
987
  }
879
988
  #endif
880
989
 
881
- ecb_function_ ecb_bool ecb_is_pot32 (uint32_t x) ecb_const;
882
- ecb_function_ ecb_bool ecb_is_pot32 (uint32_t x) { return !(x & (x - 1)); }
883
- ecb_function_ ecb_bool ecb_is_pot64 (uint64_t x) ecb_const;
884
- ecb_function_ ecb_bool ecb_is_pot64 (uint64_t x) { return !(x & (x - 1)); }
990
+ ecb_function_ ecb_const ecb_bool ecb_is_pot32 (uint32_t x);
991
+ ecb_function_ ecb_const ecb_bool ecb_is_pot32 (uint32_t x) { return !(x & (x - 1)); }
992
+ ecb_function_ ecb_const ecb_bool ecb_is_pot64 (uint64_t x);
993
+ ecb_function_ ecb_const ecb_bool ecb_is_pot64 (uint64_t x) { return !(x & (x - 1)); }
885
994
 
886
- ecb_function_ uint8_t ecb_bitrev8 (uint8_t x) ecb_const;
887
- ecb_function_ uint8_t ecb_bitrev8 (uint8_t x)
995
+ ecb_function_ ecb_const uint8_t ecb_bitrev8 (uint8_t x);
996
+ ecb_function_ ecb_const uint8_t ecb_bitrev8 (uint8_t x)
888
997
  {
889
998
  return ( (x * 0x0802U & 0x22110U)
890
- | (x * 0x8020U & 0x88440U)) * 0x10101U >> 16;
999
+ | (x * 0x8020U & 0x88440U)) * 0x10101U >> 16;
891
1000
  }
892
1001
 
893
- ecb_function_ uint16_t ecb_bitrev16 (uint16_t x) ecb_const;
894
- ecb_function_ uint16_t ecb_bitrev16 (uint16_t x)
1002
+ ecb_function_ ecb_const uint16_t ecb_bitrev16 (uint16_t x);
1003
+ ecb_function_ ecb_const uint16_t ecb_bitrev16 (uint16_t x)
895
1004
  {
896
1005
  x = ((x >> 1) & 0x5555) | ((x & 0x5555) << 1);
897
1006
  x = ((x >> 2) & 0x3333) | ((x & 0x3333) << 2);
@@ -901,8 +1010,8 @@ ecb_function_ uint16_t ecb_bitrev16 (uint16_t x)
901
1010
  return x;
902
1011
  }
903
1012
 
904
- ecb_function_ uint32_t ecb_bitrev32 (uint32_t x) ecb_const;
905
- ecb_function_ uint32_t ecb_bitrev32 (uint32_t x)
1013
+ ecb_function_ ecb_const uint32_t ecb_bitrev32 (uint32_t x);
1014
+ ecb_function_ ecb_const uint32_t ecb_bitrev32 (uint32_t x)
906
1015
  {
907
1016
  x = ((x >> 1) & 0x55555555) | ((x & 0x55555555) << 1);
908
1017
  x = ((x >> 2) & 0x33333333) | ((x & 0x33333333) << 2);
@@ -915,71 +1024,80 @@ ecb_function_ uint32_t ecb_bitrev32 (uint32_t x)
915
1024
 
916
1025
  /* popcount64 is only available on 64 bit cpus as gcc builtin */
917
1026
  /* so for this version we are lazy */
918
- ecb_function_ int ecb_popcount64 (uint64_t x) ecb_const;
919
- ecb_function_ int
1027
+ ecb_function_ ecb_const int ecb_popcount64 (uint64_t x);
1028
+ ecb_function_ ecb_const int
920
1029
  ecb_popcount64 (uint64_t x)
921
1030
  {
922
1031
  return ecb_popcount32 (x) + ecb_popcount32 (x >> 32);
923
1032
  }
924
1033
 
925
- ecb_inline uint8_t ecb_rotl8 (uint8_t x, unsigned int count) ecb_const;
926
- ecb_inline uint8_t ecb_rotr8 (uint8_t x, unsigned int count) ecb_const;
927
- ecb_inline uint16_t ecb_rotl16 (uint16_t x, unsigned int count) ecb_const;
928
- ecb_inline uint16_t ecb_rotr16 (uint16_t x, unsigned int count) ecb_const;
929
- ecb_inline uint32_t ecb_rotl32 (uint32_t x, unsigned int count) ecb_const;
930
- ecb_inline uint32_t ecb_rotr32 (uint32_t x, unsigned int count) ecb_const;
931
- ecb_inline uint64_t ecb_rotl64 (uint64_t x, unsigned int count) ecb_const;
932
- ecb_inline uint64_t ecb_rotr64 (uint64_t x, unsigned int count) ecb_const;
933
-
934
- ecb_inline uint8_t ecb_rotl8 (uint8_t x, unsigned int count) { return (x >> ( 8 - count)) | (x << count); }
935
- ecb_inline uint8_t ecb_rotr8 (uint8_t x, unsigned int count) { return (x << ( 8 - count)) | (x >> count); }
936
- ecb_inline uint16_t ecb_rotl16 (uint16_t x, unsigned int count) { return (x >> (16 - count)) | (x << count); }
937
- ecb_inline uint16_t ecb_rotr16 (uint16_t x, unsigned int count) { return (x << (16 - count)) | (x >> count); }
938
- ecb_inline uint32_t ecb_rotl32 (uint32_t x, unsigned int count) { return (x >> (32 - count)) | (x << count); }
939
- ecb_inline uint32_t ecb_rotr32 (uint32_t x, unsigned int count) { return (x << (32 - count)) | (x >> count); }
940
- ecb_inline uint64_t ecb_rotl64 (uint64_t x, unsigned int count) { return (x >> (64 - count)) | (x << count); }
941
- ecb_inline uint64_t ecb_rotr64 (uint64_t x, unsigned int count) { return (x << (64 - count)) | (x >> count); }
942
-
943
- #if ECB_GCC_VERSION(4,3)
1034
+ ecb_inline ecb_const uint8_t ecb_rotl8 (uint8_t x, unsigned int count);
1035
+ ecb_inline ecb_const uint8_t ecb_rotr8 (uint8_t x, unsigned int count);
1036
+ ecb_inline ecb_const uint16_t ecb_rotl16 (uint16_t x, unsigned int count);
1037
+ ecb_inline ecb_const uint16_t ecb_rotr16 (uint16_t x, unsigned int count);
1038
+ ecb_inline ecb_const uint32_t ecb_rotl32 (uint32_t x, unsigned int count);
1039
+ ecb_inline ecb_const uint32_t ecb_rotr32 (uint32_t x, unsigned int count);
1040
+ ecb_inline ecb_const uint64_t ecb_rotl64 (uint64_t x, unsigned int count);
1041
+ ecb_inline ecb_const uint64_t ecb_rotr64 (uint64_t x, unsigned int count);
1042
+
1043
+ ecb_inline ecb_const uint8_t ecb_rotl8 (uint8_t x, unsigned int count) { return (x >> ( 8 - count)) | (x << count); }
1044
+ ecb_inline ecb_const uint8_t ecb_rotr8 (uint8_t x, unsigned int count) { return (x << ( 8 - count)) | (x >> count); }
1045
+ ecb_inline ecb_const uint16_t ecb_rotl16 (uint16_t x, unsigned int count) { return (x >> (16 - count)) | (x << count); }
1046
+ ecb_inline ecb_const uint16_t ecb_rotr16 (uint16_t x, unsigned int count) { return (x << (16 - count)) | (x >> count); }
1047
+ ecb_inline ecb_const uint32_t ecb_rotl32 (uint32_t x, unsigned int count) { return (x >> (32 - count)) | (x << count); }
1048
+ ecb_inline ecb_const uint32_t ecb_rotr32 (uint32_t x, unsigned int count) { return (x << (32 - count)) | (x >> count); }
1049
+ ecb_inline ecb_const uint64_t ecb_rotl64 (uint64_t x, unsigned int count) { return (x >> (64 - count)) | (x << count); }
1050
+ ecb_inline ecb_const uint64_t ecb_rotr64 (uint64_t x, unsigned int count) { return (x << (64 - count)) | (x >> count); }
1051
+
1052
+ #if ECB_GCC_VERSION(4,3) || (ECB_CLANG_BUILTIN(__builtin_bswap32) && ECB_CLANG_BUILTIN(__builtin_bswap64))
1053
+ #if ECB_GCC_VERSION(4,8) || ECB_CLANG_BUILTIN(__builtin_bswap16)
1054
+ #define ecb_bswap16(x) __builtin_bswap16 (x)
1055
+ #else
944
1056
  #define ecb_bswap16(x) (__builtin_bswap32 (x) >> 16)
1057
+ #endif
945
1058
  #define ecb_bswap32(x) __builtin_bswap32 (x)
946
1059
  #define ecb_bswap64(x) __builtin_bswap64 (x)
1060
+ #elif _MSC_VER
1061
+ #include <stdlib.h>
1062
+ #define ecb_bswap16(x) ((uint16_t)_byteswap_ushort ((uint16_t)(x)))
1063
+ #define ecb_bswap32(x) ((uint32_t)_byteswap_ulong ((uint32_t)(x)))
1064
+ #define ecb_bswap64(x) ((uint64_t)_byteswap_uint64 ((uint64_t)(x)))
947
1065
  #else
948
- ecb_function_ uint16_t ecb_bswap16 (uint16_t x) ecb_const;
949
- ecb_function_ uint16_t
1066
+ ecb_function_ ecb_const uint16_t ecb_bswap16 (uint16_t x);
1067
+ ecb_function_ ecb_const uint16_t
950
1068
  ecb_bswap16 (uint16_t x)
951
1069
  {
952
1070
  return ecb_rotl16 (x, 8);
953
1071
  }
954
1072
 
955
- ecb_function_ uint32_t ecb_bswap32 (uint32_t x) ecb_const;
956
- ecb_function_ uint32_t
1073
+ ecb_function_ ecb_const uint32_t ecb_bswap32 (uint32_t x);
1074
+ ecb_function_ ecb_const uint32_t
957
1075
  ecb_bswap32 (uint32_t x)
958
1076
  {
959
1077
  return (((uint32_t)ecb_bswap16 (x)) << 16) | ecb_bswap16 (x >> 16);
960
1078
  }
961
1079
 
962
- ecb_function_ uint64_t ecb_bswap64 (uint64_t x) ecb_const;
963
- ecb_function_ uint64_t
1080
+ ecb_function_ ecb_const uint64_t ecb_bswap64 (uint64_t x);
1081
+ ecb_function_ ecb_const uint64_t
964
1082
  ecb_bswap64 (uint64_t x)
965
1083
  {
966
1084
  return (((uint64_t)ecb_bswap32 (x)) << 32) | ecb_bswap32 (x >> 32);
967
1085
  }
968
1086
  #endif
969
1087
 
970
- #if ECB_GCC_VERSION(4,5)
1088
+ #if ECB_GCC_VERSION(4,5) || ECB_CLANG_BUILTIN(__builtin_unreachable)
971
1089
  #define ecb_unreachable() __builtin_unreachable ()
972
1090
  #else
973
1091
  /* this seems to work fine, but gcc always emits a warning for it :/ */
974
- ecb_inline void ecb_unreachable (void) ecb_noreturn;
975
- ecb_inline void ecb_unreachable (void) { }
1092
+ ecb_inline ecb_noreturn void ecb_unreachable (void);
1093
+ ecb_inline ecb_noreturn void ecb_unreachable (void) { }
976
1094
  #endif
977
1095
 
978
1096
  /* try to tell the compiler that some condition is definitely true */
979
1097
  #define ecb_assume(cond) if (!(cond)) ecb_unreachable (); else 0
980
1098
 
981
- ecb_inline unsigned char ecb_byteorder_helper (void) ecb_const;
982
- ecb_inline unsigned char
1099
+ ecb_inline ecb_const unsigned char ecb_byteorder_helper (void);
1100
+ ecb_inline ecb_const unsigned char
983
1101
  ecb_byteorder_helper (void)
984
1102
  {
985
1103
  /* the union code still generates code under pressure in gcc, */
@@ -988,7 +1106,7 @@ ecb_byteorder_helper (void)
988
1106
  /* the reason why we have this horrible preprocessor mess */
989
1107
  /* is to avoid it in all cases, at least on common architectures */
990
1108
  /* or when using a recent enough gcc version (>= 4.6) */
991
- #if __i386 || __i386__ || _M_X86 || __amd64 || __amd64__ || _M_X64
1109
+ #if ((__i386 || __i386__) && !__VOS__) || _M_IX86 || ECB_GCC_AMD64 || ECB_MSVC_AMD64
992
1110
  return 0x44;
993
1111
  #elif __BYTE_ORDER__ && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
994
1112
  return 0x44;
@@ -1004,10 +1122,10 @@ ecb_byteorder_helper (void)
1004
1122
  #endif
1005
1123
  }
1006
1124
 
1007
- ecb_inline ecb_bool ecb_big_endian (void) ecb_const;
1008
- ecb_inline ecb_bool ecb_big_endian (void) { return ecb_byteorder_helper () == 0x11; }
1009
- ecb_inline ecb_bool ecb_little_endian (void) ecb_const;
1010
- ecb_inline ecb_bool ecb_little_endian (void) { return ecb_byteorder_helper () == 0x44; }
1125
+ ecb_inline ecb_const ecb_bool ecb_big_endian (void);
1126
+ ecb_inline ecb_const ecb_bool ecb_big_endian (void) { return ecb_byteorder_helper () == 0x11; }
1127
+ ecb_inline ecb_const ecb_bool ecb_little_endian (void);
1128
+ ecb_inline ecb_const ecb_bool ecb_little_endian (void) { return ecb_byteorder_helper () == 0x44; }
1011
1129
 
1012
1130
  #if ECB_GCC_VERSION(3,0) || ECB_C99
1013
1131
  #define ecb_mod(m,n) ((m) % (n) + ((m) % (n) < 0 ? (n) : 0))
@@ -1015,7 +1133,7 @@ ecb_inline ecb_bool ecb_little_endian (void) { return ecb_byteorder_helper () ==
1015
1133
  #define ecb_mod(m,n) ((m) < 0 ? ((n) - 1 - ((-1 - (m)) % (n))) : ((m) % (n)))
1016
1134
  #endif
1017
1135
 
1018
- #if __cplusplus
1136
+ #if ECB_CPP
1019
1137
  template<typename T>
1020
1138
  static inline T ecb_div_rd (T val, T div)
1021
1139
  {
@@ -1049,27 +1167,70 @@ ecb_inline ecb_bool ecb_little_endian (void) { return ecb_byteorder_helper () ==
1049
1167
  /* the only noteworthy exception is ancient armle, which uses order 43218765 */
1050
1168
  #if 0 \
1051
1169
  || __i386 || __i386__ \
1052
- || __amd64 || __amd64__ || __x86_64 || __x86_64__ \
1170
+ || ECB_GCC_AMD64 \
1053
1171
  || __powerpc__ || __ppc__ || __powerpc64__ || __ppc64__ \
1054
- || defined __arm__ && defined __ARM_EABI__ \
1055
1172
  || defined __s390__ || defined __s390x__ \
1056
1173
  || defined __mips__ \
1057
1174
  || defined __alpha__ \
1058
1175
  || defined __hppa__ \
1059
1176
  || defined __ia64__ \
1060
- || defined _M_IX86 || defined _M_AMD64 || defined _M_IA64
1177
+ || defined __m68k__ \
1178
+ || defined __m88k__ \
1179
+ || defined __sh__ \
1180
+ || defined _M_IX86 || defined ECB_MSVC_AMD64 || defined _M_IA64 \
1181
+ || (defined __arm__ && (defined __ARM_EABI__ || defined __EABI__ || defined __VFP_FP__ || defined _WIN32_WCE || defined __ANDROID__)) \
1182
+ || defined __aarch64__
1061
1183
  #define ECB_STDFP 1
1062
1184
  #include <string.h> /* for memcpy */
1063
1185
  #else
1064
1186
  #define ECB_STDFP 0
1065
- #include <math.h> /* for frexp*, ldexp* */
1066
1187
  #endif
1067
1188
 
1068
1189
  #ifndef ECB_NO_LIBM
1069
1190
 
1191
+ #include <math.h> /* for frexp*, ldexp*, INFINITY, NAN */
1192
+
1193
+ /* only the oldest of old doesn't have this one. solaris. */
1194
+ #ifdef INFINITY
1195
+ #define ECB_INFINITY INFINITY
1196
+ #else
1197
+ #define ECB_INFINITY HUGE_VAL
1198
+ #endif
1199
+
1200
+ #ifdef NAN
1201
+ #define ECB_NAN NAN
1202
+ #else
1203
+ #define ECB_NAN ECB_INFINITY
1204
+ #endif
1205
+
1206
+ #if ECB_C99 || _XOPEN_VERSION >= 600 || _POSIX_VERSION >= 200112L
1207
+ #define ecb_ldexpf(x,e) ldexpf ((x), (e))
1208
+ #define ecb_frexpf(x,e) frexpf ((x), (e))
1209
+ #else
1210
+ #define ecb_ldexpf(x,e) (float) ldexp ((double) (x), (e))
1211
+ #define ecb_frexpf(x,e) (float) frexp ((double) (x), (e))
1212
+ #endif
1213
+
1214
+ /* converts an ieee half/binary16 to a float */
1215
+ ecb_function_ ecb_const float ecb_binary16_to_float (uint16_t x);
1216
+ ecb_function_ ecb_const float
1217
+ ecb_binary16_to_float (uint16_t x)
1218
+ {
1219
+ int e = (x >> 10) & 0x1f;
1220
+ int m = x & 0x3ff;
1221
+ float r;
1222
+
1223
+ if (!e ) r = ecb_ldexpf (m , -24);
1224
+ else if (e != 31) r = ecb_ldexpf (m + 0x400, e - 25);
1225
+ else if (m ) r = ECB_NAN;
1226
+ else r = ECB_INFINITY;
1227
+
1228
+ return x & 0x8000 ? -r : r;
1229
+ }
1230
+
1070
1231
  /* convert a float to ieee single/binary32 */
1071
- ecb_function_ uint32_t ecb_float_to_binary32 (float x) ecb_const;
1072
- ecb_function_ uint32_t
1232
+ ecb_function_ ecb_const uint32_t ecb_float_to_binary32 (float x);
1233
+ ecb_function_ ecb_const uint32_t
1073
1234
  ecb_float_to_binary32 (float x)
1074
1235
  {
1075
1236
  uint32_t r;
@@ -1086,7 +1247,7 @@ ecb_inline ecb_bool ecb_little_endian (void) { return ecb_byteorder_helper () ==
1086
1247
  if (x < -3.40282346638528860e+38f) return 0xff800000U;
1087
1248
  if (x != x ) return 0x7fbfffffU;
1088
1249
 
1089
- m = frexpf (x, &e) * 0x1000000U;
1250
+ m = ecb_frexpf (x, &e) * 0x1000000U;
1090
1251
 
1091
1252
  r = m & 0x80000000U;
1092
1253
 
@@ -1108,8 +1269,8 @@ ecb_inline ecb_bool ecb_little_endian (void) { return ecb_byteorder_helper () ==
1108
1269
  }
1109
1270
 
1110
1271
  /* converts an ieee single/binary32 to a float */
1111
- ecb_function_ float ecb_binary32_to_float (uint32_t x) ecb_const;
1112
- ecb_function_ float
1272
+ ecb_function_ ecb_const float ecb_binary32_to_float (uint32_t x);
1273
+ ecb_function_ ecb_const float
1113
1274
  ecb_binary32_to_float (uint32_t x)
1114
1275
  {
1115
1276
  float r;
@@ -1129,7 +1290,7 @@ ecb_inline ecb_bool ecb_little_endian (void) { return ecb_byteorder_helper () ==
1129
1290
  e = 1;
1130
1291
 
1131
1292
  /* we distrust ldexpf a bit and do the 2**-24 scaling by an extra multiply */
1132
- r = ldexpf (x * (0.5f / 0x800000U), e - 126);
1293
+ r = ecb_ldexpf (x * (0.5f / 0x800000U), e - 126);
1133
1294
 
1134
1295
  r = neg ? -r : r;
1135
1296
  #endif
@@ -1138,8 +1299,8 @@ ecb_inline ecb_bool ecb_little_endian (void) { return ecb_byteorder_helper () ==
1138
1299
  }
1139
1300
 
1140
1301
  /* convert a double to ieee double/binary64 */
1141
- ecb_function_ uint64_t ecb_double_to_binary64 (double x) ecb_const;
1142
- ecb_function_ uint64_t
1302
+ ecb_function_ ecb_const uint64_t ecb_double_to_binary64 (double x);
1303
+ ecb_function_ ecb_const uint64_t
1143
1304
  ecb_double_to_binary64 (double x)
1144
1305
  {
1145
1306
  uint64_t r;
@@ -1178,8 +1339,8 @@ ecb_inline ecb_bool ecb_little_endian (void) { return ecb_byteorder_helper () ==
1178
1339
  }
1179
1340
 
1180
1341
  /* converts an ieee double/binary64 to a double */
1181
- ecb_function_ double ecb_binary64_to_double (uint64_t x) ecb_const;
1182
- ecb_function_ double
1342
+ ecb_function_ ecb_const double ecb_binary64_to_double (uint64_t x);
1343
+ ecb_function_ ecb_const double
1183
1344
  ecb_binary64_to_double (uint64_t x)
1184
1345
  {
1185
1346
  double r;
@@ -2017,7 +2178,7 @@ downheap (ANHE *heap, int N, int k)
2017
2178
 
2018
2179
  heap [k] = heap [c];
2019
2180
  ev_active (ANHE_w (heap [k])) = k;
2020
-
2181
+
2021
2182
  k = c;
2022
2183
  }
2023
2184
 
@@ -2110,8 +2271,6 @@ evpipe_init (EV_P)
2110
2271
  fd_intern (fds [0]);
2111
2272
  }
2112
2273
 
2113
- fd_intern (fds [1]);
2114
-
2115
2274
  evpipe [0] = fds [0];
2116
2275
 
2117
2276
  if (evpipe [1] < 0)
@@ -2127,6 +2286,8 @@ evpipe_init (EV_P)
2127
2286
  close (fds [1]);
2128
2287
  }
2129
2288
 
2289
+ fd_intern (evpipe [1]);
2290
+
2130
2291
  ev_io_set (&pipe_w, evpipe [0] < 0 ? evpipe [1] : evpipe [0], EV_READ);
2131
2292
  ev_io_start (EV_A_ &pipe_w);
2132
2293
  ev_unref (EV_A); /* watcher should not keep loop alive */
@@ -2437,7 +2598,7 @@ ev_supported_backends (void) EV_THROW
2437
2598
  if (EV_USE_EPOLL ) flags |= EVBACKEND_EPOLL;
2438
2599
  if (EV_USE_POLL ) flags |= EVBACKEND_POLL;
2439
2600
  if (EV_USE_SELECT) flags |= EVBACKEND_SELECT;
2440
-
2601
+
2441
2602
  return flags;
2442
2603
  }
2443
2604
 
@@ -2519,7 +2680,7 @@ ev_userdata (EV_P) EV_THROW
2519
2680
  }
2520
2681
 
2521
2682
  void
2522
- ev_set_invoke_pending_cb (EV_P_ void (*invoke_pending_cb)(EV_P)) EV_THROW
2683
+ ev_set_invoke_pending_cb (EV_P_ ev_loop_callback invoke_pending_cb) EV_THROW
2523
2684
  {
2524
2685
  invoke_cb = invoke_pending_cb;
2525
2686
  }
@@ -3243,12 +3404,18 @@ time_update (EV_P_ ev_tstamp max_block)
3243
3404
 
3244
3405
  /* ########## COOLIO PATCHERY HO! ########## */
3245
3406
  #if defined(HAVE_RB_THREAD_BLOCKING_REGION) || defined(HAVE_RB_THREAD_CALL_WITHOUT_GVL)
3407
+ struct ev_poll_args {
3408
+ struct ev_loop *loop;
3409
+ ev_tstamp waittime;
3410
+ };
3411
+
3246
3412
  static
3247
- VALUE ev_backend_poll(void **args)
3413
+ VALUE ev_backend_poll(void *ptr)
3248
3414
  {
3249
- struct ev_loop *loop = (struct ev_loop *)args[0];
3250
- ev_tstamp waittime = *(ev_tstamp *)args[1];
3251
- backend_poll (EV_A_ waittime);
3415
+ struct ev_poll_args *args = (struct ev_poll_args *)ptr;
3416
+ struct ev_loop *loop = args->loop;
3417
+ backend_poll (EV_A_ args->waittime);
3418
+ return Qnil;
3252
3419
  }
3253
3420
  #endif
3254
3421
  /* ######################################## */
@@ -3258,7 +3425,7 @@ ev_run (EV_P_ int flags)
3258
3425
  {
3259
3426
  /* ########## COOLIO PATCHERY HO! ########## */
3260
3427
  #if defined(HAVE_RB_THREAD_BLOCKING_REGION) || defined(HAVE_RB_THREAD_CALL_WITHOUT_GVL)
3261
- void *poll_args[2];
3428
+ struct ev_poll_args poll_args;
3262
3429
  #endif
3263
3430
  /* ######################################## */
3264
3431
 
@@ -3383,9 +3550,6 @@ ev_run (EV_P_ int flags)
3383
3550
  /*
3384
3551
  ########################## COOLIO PATCHERY HO! ##########################
3385
3552
 
3386
- The original patch file is made by Tony Arcieri.
3387
- https://github.com/celluloid/nio4r/blob/680143345726c5a64bb22376ca8fc3c6857019ae/ext/libev/ruby_gil.patch.
3388
-
3389
3553
  According to the grandwizards of Ruby, locking and unlocking of the global
3390
3554
  interpreter lock are apparently too powerful a concept for a mere mortal to
3391
3555
  wield (although redefining what + and - do to numbers is totally cool).
@@ -3410,7 +3574,15 @@ other and thus cannot be composed.
3410
3574
  And thus we are left with no choice but to patch the internals of libev in
3411
3575
  order to release a mutex at just the precise moment.
3412
3576
 
3413
- Let this be a lesson to the all: CALLBACKS FUCKING BLOW
3577
+ This is a great example of a situation where granular locking and unlocking
3578
+ of the GVL is practically required. The goal is to get as close to the
3579
+ system call as possible, and to keep the GVL unlocked for the shortest
3580
+ amount of time possible.
3581
+
3582
+ Perhaps Ruby could benefit from such an API, e.g:
3583
+
3584
+ rb_thread_unsafe_dangerous_crazy_blocking_region_begin(...);
3585
+ rb_thread_unsafe_dangerous_crazy_blocking_region_end(...);
3414
3586
 
3415
3587
  #######################################################################
3416
3588
  */
@@ -3422,19 +3594,17 @@ Let this be a lesson to the all: CALLBACKS FUCKING BLOW
3422
3594
 
3423
3595
  #ifndef HAVE_RB_THREAD_CALL_WITHOUT_GVL
3424
3596
  #ifdef HAVE_RB_THREAD_BLOCKING_REGION
3425
-
3426
3597
  #define rb_thread_call_without_gvl(func, data1, ubf, data2) \
3427
3598
  rb_thread_blocking_region((rb_blocking_function_t *)func, data1, ubf, data2)
3428
-
3429
3599
  #endif
3430
3600
  #endif
3431
3601
 
3432
3602
  #if defined(HAVE_RB_THREAD_BLOCKING_REGION) || defined(HAVE_RB_THREAD_CALL_WITHOUT_GVL)
3433
- poll_args[0] = (void *)loop;
3434
- poll_args[1] = (void *)&waittime;
3603
+ poll_args.loop = loop;
3604
+ poll_args.waittime = waittime;
3435
3605
  rb_thread_call_without_gvl(ev_backend_poll, (void *)&poll_args, RUBY_UBF_IO, 0);
3436
3606
  #else
3437
- backend_poll (EV_A_ waittime);
3607
+ backend_poll (EV_A_ waittime);
3438
3608
  #endif
3439
3609
  /*
3440
3610
  ############################# END PATCHERY ############################
@@ -4882,4 +5052,3 @@ ev_walk (EV_P_ int types, void (*cb)(EV_P_ int type, void *w)) EV_THROW
4882
5052
  #if EV_MULTIPLICITY
4883
5053
  #include "ev_wrap.h"
4884
5054
  #endif
4885
-