nio4r 2.4.0 → 2.5.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 93a1a241691b4115c57d823095030d46f36640184d6dc479ec0c46ac3e730d43
4
- data.tar.gz: c0795ea1c7e4c3d9a0f6347ce69f3d937f0410618e80c217cc5c54c90bf44ddb
3
+ metadata.gz: 3353e688cab0a1d45f509edcb0a5bc5fa3beb6faca9e6e5703fe75ecbb220ed9
4
+ data.tar.gz: d5186d282adfa316128165ca4d2ccae5322a0605b15508d47170f9f7517e3346
5
5
  SHA512:
6
- metadata.gz: 289370e25ed8f9692699a493d7cae6dccb5a24db65af58053c094a529eac7e3a65b9581f7576e46661e02a4ef017defdd1ca3805a7e1e1db38025f4c62513e6e
7
- data.tar.gz: 854804c274c63ef8590164ef733d2a538e004d744e13090b1c60ef0b070617e3a49d3c528d50da940c02855446e057e33674f97c121f73c0295e3ea0d96dcd54
6
+ metadata.gz: 05c2472803019de225a4d813f302bad6810fecf193adad4291c4b58e0e5aaa34d02b60945bc6641be55103324b82eee001988641d2b9937f63d18e7d00a03f8d
7
+ data.tar.gz: fcbb1f1aa622df5e82df481e40567c153d15ca2e59ca21fbd3aff00006326e1f8ec44ff108c59fc8e8124bcc3b8e99f23d6291fe7ca27092d7af6ac22be71eb5
@@ -0,0 +1,43 @@
1
+ name: nio4r
2
+
3
+ on: [push, pull_request]
4
+
5
+ jobs:
6
+ build:
7
+ name: >-
8
+ ${{matrix.os}}, ${{matrix.ruby}}
9
+ env:
10
+ CI: true
11
+ TESTOPTS: -v
12
+
13
+ runs-on: ${{matrix.os}}
14
+ strategy:
15
+ fail-fast: false
16
+ matrix:
17
+ os: [ubuntu-16.04, ubuntu-18.04, macos-latest, windows-latest]
18
+ ruby: [2.4, 2.5, 2.6, 2.7, jruby, truffleruby-head]
19
+ exclude:
20
+ - { os: windows-latest, ruby: jruby }
21
+ - { os: windows-latest, ruby: truffleruby-head }
22
+
23
+ steps:
24
+ - name: repo checkout
25
+ uses: actions/checkout@v2
26
+
27
+ - name: load ruby
28
+ uses: ruby/setup-ruby@v1
29
+ with:
30
+ ruby-version: ${{matrix.ruby}}
31
+
32
+ - name: RubyGems, Bundler Update
33
+ run: gem update --system --no-document --conservative
34
+
35
+ - name: bundle install
36
+ run: bundle install --path .bundle/gems --without development
37
+
38
+ - name: compile
39
+ run: bundle exec rake compile
40
+
41
+ - name: test
42
+ run: bundle exec rake spec
43
+ timeout-minutes: 10
@@ -1,23 +1,40 @@
1
1
  AllCops:
2
- TargetRubyVersion: 2.3
2
+ TargetRubyVersion: 2.4
3
3
  DisplayCopNames: true
4
4
 
5
+ Layout/HashAlignment:
6
+ Enabled: false
7
+
8
+ Layout/LineLength:
9
+ Max: 128
10
+
11
+ Layout/SpaceAroundMethodCallOperator:
12
+ Enabled: false
13
+
5
14
  Layout/SpaceInsideBlockBraces:
6
15
  Enabled: false
7
16
 
8
17
  Style/IfUnlessModifier:
9
18
  Enabled: false
10
19
 
20
+ Style/UnpackFirst:
21
+ Enabled: false
22
+
11
23
  #
12
24
  # Lint
13
25
  #
14
26
 
15
- Lint/HandleExceptions:
27
+ Lint/SuppressedException:
16
28
  Enabled: false
17
29
 
18
30
  Lint/Loop:
19
31
  Enabled: false
20
32
 
33
+ Lint/RaiseException:
34
+ Enabled: false
35
+
36
+ Lint/StructNewOverride:
37
+ Enabled: false
21
38
  #
22
39
  # Metrics
23
40
  #
@@ -32,9 +49,6 @@ Metrics/BlockLength:
32
49
  Metrics/ClassLength:
33
50
  Max: 128
34
51
 
35
- Metrics/LineLength:
36
- Max: 128
37
-
38
52
  Metrics/MethodLength:
39
53
  CountComments: false
40
54
  Max: 50
@@ -46,16 +60,12 @@ Metrics/PerceivedComplexity:
46
60
  Max: 15
47
61
 
48
62
  #
49
- # Performance
63
+ # Style
50
64
  #
51
65
 
52
- Performance/RegexpMatch:
66
+ Style/ExponentialNotation:
53
67
  Enabled: false
54
68
 
55
- #
56
- # Style
57
- #
58
-
59
69
  Style/FormatStringToken:
60
70
  Enabled: false
61
71
 
@@ -65,6 +75,15 @@ Style/FrozenStringLiteralComment:
65
75
  Style/GlobalVars:
66
76
  Enabled: false
67
77
 
78
+ Style/HashEachMethods:
79
+ Enabled: false
80
+
81
+ Style/HashTransformKeys:
82
+ Enabled: false
83
+
84
+ Style/HashTransformValues:
85
+ Enabled: false
86
+
68
87
  Style/NumericPredicate:
69
88
  Enabled: false
70
89
 
data/CHANGES.md CHANGED
@@ -1,3 +1,46 @@
1
+ ## 2.5.4 (2020-09-16)
2
+
3
+ * [#251](https://github.com/socketry/nio4r/issues/251)
4
+ Intermittent SEGV during GC.
5
+ ([@boazsegev])
6
+
7
+ ## 2.5.3 (2020-09-07)
8
+
9
+ * [#241](https://github.com/socketry/nio4r/issues/241)
10
+ Possible bug with Ruby >= 2.7.0 and `GC.compact`.
11
+ ([@boazsegev])
12
+
13
+ ## 2.5.2 (2019-09-24)
14
+
15
+ * [#220](https://github.com/socketry/nio4r/issues/220)
16
+ Update to libev-4.27 & fix assorted warnings.
17
+ ([@ioquatix])
18
+
19
+ * [#225](https://github.com/socketry/nio4r/issues/225)
20
+ Avoid need for linux headers.
21
+ ([@ioquatix])
22
+
23
+ ## 2.4.0 (2019-07-07)
24
+
25
+ * [#211](https://github.com/socketry/nio4r/pull/211)
26
+ Enable KQUEUE on macOS 10.14+.
27
+ ([@ioquatix])
28
+
29
+ * Bump minimum supported Ruby to 2.3.
30
+ ([@ioquatix])
31
+
32
+ * Assorted fixes for TruffleRuby & JRuby.
33
+ ([@eregon], [@olleolleolle])
34
+ Possible bug with Ruby >= 2.7.0 and `GC.compact`
35
+ * Update libev to v4.25.
36
+ ([@ioquatix])
37
+
38
+ * Bind to ephemeral (port 0) for more reliable specs.
39
+ ([@ioquatix])
40
+
41
+ * Improve handling of SSL sockets and related specs.
42
+ ([@MSP-Greg])
43
+
1
44
  ## 2.3.1 (2018-05-03)
2
45
 
3
46
  * [#188](https://github.com/socketry/nio4r/pull/188)
@@ -219,3 +262,6 @@
219
262
  [@HoneyryderChuck]: https://github.com/HoneyryderChuck
220
263
  [@tompng]: https://github.com/tompng
221
264
  [@ioquatix]: https://github.com/ioquatix
265
+ [@eregon]: https://github.com/eregon
266
+ [@olleolleolle]: https://github.com/olleolleolle
267
+ [@boazsegev]: https://github.com/boazsegev
data/Gemfile CHANGED
@@ -15,5 +15,5 @@ group :development, :test do
15
15
  gem "coveralls", require: false
16
16
  gem "rake-compiler", require: false
17
17
  gem "rspec", "~> 3.7", require: false
18
- gem "rubocop", "0.52.1", require: false
18
+ gem "rubocop", "0.82.0", require: false
19
19
  end
data/README.md CHANGED
@@ -1,17 +1,10 @@
1
1
  # ![nio4r](https://raw.github.com/socketry/nio4r/master/logo.png)
2
2
 
3
3
  [![Gem Version](https://badge.fury.io/rb/nio4r.svg)](http://rubygems.org/gems/nio4r)
4
- [![Travis CI Status](https://secure.travis-ci.org/socketry/nio4r.svg?branch=master)](http://travis-ci.org/socketry/nio4r)
5
- [![Appveyor Status](https://ci.appveyor.com/api/projects/status/1ru8x81v91vaewax/branch/master?svg=true)](https://ci.appveyor.com/project/tarcieri/nio4r/branch/master)
4
+ [![Build Status](https://github.com/socketry/nio4r/workflows/nio4r/badge.svg?branch=master&event=push)](https://github.com/socketry/nio4r/actions?query=workflow:nio4r)
6
5
  [![Code Climate](https://codeclimate.com/github/socketry/nio4r.svg)](https://codeclimate.com/github/socketry/nio4r)
7
6
  [![Coverage Status](https://coveralls.io/repos/socketry/nio4r/badge.svg?branch=master)](https://coveralls.io/r/socketry/nio4r)
8
7
  [![Yard Docs](https://img.shields.io/badge/yard-docs-blue.svg)](http://www.rubydoc.info/gems/nio4r/2.2.0)
9
- [![MIT licensed](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/socketry/nio4r/blob/master/LICENSE.txt)
10
-
11
- _NOTE: This is the 2.x **stable** branch of nio4r. For the 1.x **legacy** branch,
12
- please see:_
13
-
14
- https://github.com/socketry/nio4r/tree/1-x-stable
15
8
 
16
9
  **New I/O for Ruby (nio4r)**: cross-platform asynchronous I/O primitives for
17
10
  scalable network clients and servers. Modeled after the Java NIO API, but
@@ -25,12 +18,14 @@ writing.
25
18
  ## Projects using nio4r
26
19
 
27
20
  * [ActionCable]: Rails 5 WebSocket protocol, uses nio4r for a WebSocket server
28
- * [Celluloid::IO]: Actor-based concurrency framework, uses nio4r for async I/O
29
- * [Socketry Async]: Asynchronous I/O framework for Ruby
21
+ * [Celluloid]: Actor-based concurrency framework, uses nio4r for async I/O
22
+ * [Async]: Asynchronous I/O framework for Ruby
23
+ * [Puma]: Ruby/Rack web server built for concurrency
30
24
 
31
25
  [ActionCable]: https://rubygems.org/gems/actioncable
32
- [Celluloid::IO]: https://github.com/celluloid/celluloid-io
33
- [Socketry Async]: https://github.com/socketry/async
26
+ [Celluloid]: https://github.com/celluloid/celluloid-io
27
+ [Async]: https://github.com/socketry/async
28
+ [Puma]: https://github.com/puma/puma
34
29
 
35
30
  ## Goals
36
31
 
@@ -41,11 +36,12 @@ writing.
41
36
 
42
37
  ## Supported platforms
43
38
 
44
- * Ruby 2.3
45
39
  * Ruby 2.4
46
40
  * Ruby 2.5
47
41
  * Ruby 2.6
48
- * JRuby 9000
42
+ * Ruby 2.7
43
+ * [JRuby](https://github.com/jruby/jruby)
44
+ * [TruffleRuby](https://github.com/oracle/truffleruby)
49
45
 
50
46
  ## Supported backends
51
47
 
@@ -53,17 +49,6 @@ writing.
53
49
  * **Java NIO**: JRuby extension which wraps the Java NIO subsystem
54
50
  * **Pure Ruby**: `Kernel.select`-based backend that should work on any Ruby interpreter
55
51
 
56
- ## Discussion
57
-
58
- For discussion and general help with nio4r, email
59
- [socketry+subscribe@googlegroups.com][subscribe]
60
- or join on the web via the [Google Group].
61
-
62
- We're also on IRC at ##socketry on irc.freenode.net.
63
-
64
- [subscribe]: mailto:socketry+subscribe@googlegroups.com
65
- [google group]: https://groups.google.com/group/socketry
66
-
67
52
  ## Documentation
68
53
 
69
54
  [Please see the nio4r wiki](https://github.com/socketry/nio4r/wiki)
@@ -94,13 +79,54 @@ to maintain a large codebase.
94
79
  [EventMachine]: https://github.com/eventmachine/eventmachine
95
80
  [Cool.io]: https://coolio.github.io/
96
81
 
82
+ ## Releases
83
+
84
+ ### CRuby
85
+
86
+ ```
87
+ rake clean
88
+ rake release
89
+ ```
90
+
91
+ ### JRuby
92
+
93
+ You might need to delete `Gemfile.lock` before trying to `bundle install`.
94
+
95
+ ```
96
+ rake clean
97
+ rake compile
98
+ rake release
99
+ ```
100
+
97
101
  ## License
98
102
 
99
- Copyright (c) 2011-2018 Tony Arcieri. Distributed under the MIT License.
100
- See [LICENSE.txt] for further details.
103
+ Released under the MIT license.
104
+
105
+ Copyright, 2019, by Tony Arcieri.
106
+ Copyright, 2019, by [Samuel G. D. Williams](http://www.codeotaku.com/samuel-williams).
107
+
108
+ Permission is hereby granted, free of charge, to any person obtaining a copy
109
+ of this software and associated documentation files (the "Software"), to deal
110
+ in the Software without restriction, including without limitation the rights
111
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
112
+ copies of the Software, and to permit persons to whom the Software is
113
+ furnished to do so, subject to the following conditions:
114
+
115
+ The above copyright notice and this permission notice shall be included in
116
+ all copies or substantial portions of the Software.
117
+
118
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
119
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
120
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
121
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
122
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
123
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
124
+ THE SOFTWARE.
125
+
126
+ ### libev
127
+
128
+ Released under the BSD license. See [ext/libev/LICENSE] for details.
101
129
 
102
- Includes libev 4.24. Copyright (c) 2007-2016 Marc Alexander Lehmann.
103
- Distributed under the BSD license. See [ext/libev/LICENSE] for details.
130
+ Copyright, 2007-2019, by Marc Alexander Lehmann.
104
131
 
105
- [LICENSE.txt]: https://github.com/socketry/nio4r/blob/master/LICENSE.txt
106
132
  [ext/libev/LICENSE]: https://github.com/socketry/nio4r/blob/master/ext/libev/LICENSE
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env ruby
2
2
  # frozen_string_literal: true
3
3
 
4
- $LOAD_PATH.push File.expand_path("../../lib", __FILE__)
4
+ $LOAD_PATH.push File.expand_path("../lib", __dir__)
5
5
  require "nio"
6
6
  require "socket"
7
7
 
@@ -19,7 +19,7 @@ class EchoServer
19
19
 
20
20
  def run
21
21
  loop do
22
- @selector.select { |monitor| monitor.value.call(monitor) }
22
+ @selector.select { |monitor| monitor.value.call }
23
23
  end
24
24
  end
25
25
 
@@ -1,8 +1,27 @@
1
1
  Revision history for libev, a high-performance and full-featured event loop.
2
2
 
3
+ 4.27 Thu Jun 27 22:43:44 CEST 2019
4
+ - linux aio backend almost complete rewritten to work around its
5
+ limitations.
6
+ - epoll backend now mandatory for linux aio backend.
7
+ - fail assertions more aggressively on invalid fd's detected
8
+ in the event loop, do not just silently fd_kill in case of
9
+ user error.
10
+ - ev_io_start/ev_io_stop now verify the watcher fd using
11
+ a syscall when EV_VERIFY is 2 or higher.
12
+
13
+ 4.26 (EV only)
14
+ - update to libecb 0x00010006.
15
+ - new experimental linux aio backend (linux 4.18+).
16
+ - removed redundant 0-ptr check in ev_once.
17
+ - updated/extended ev_set_allocator documentation.
18
+ - replaced EMPTY2 macro by array_needsize_noinit.
19
+ - minor code cleanups.
20
+ - epoll backend now uses epoll_create1 also after fork.
21
+
3
22
  4.25 Fri Dec 21 07:49:20 CET 2018
4
23
  - INCOMPATIBLE CHANGE: EV_THROW was renamed to EV_NOEXCEPT
5
- (EV_THROW sitll provided) and now uses noexcept on C++11 or newer.
24
+ (EV_THROW still provided) and now uses noexcept on C++11 or newer.
6
25
  - move the darwin select workaround highe rin ev.c, as newer versions of
7
26
  darwin managed to break their broken select even more.
8
27
  - ANDROID => __ANDROID__ (reported by enh@google.com).
@@ -18,7 +18,8 @@ ABOUT
18
18
  - extensive and detailed, readable documentation (not doxygen garbage).
19
19
  - fully supports fork, can detect fork in various ways and automatically
20
20
  re-arms kernel mechanisms that do not support fork.
21
- - highly optimised select, poll, epoll, kqueue and event ports backends.
21
+ - highly optimised select, poll, linux epoll, linux aio, bsd kqueue
22
+ and solaris event ports backends.
22
23
  - filesystem object (path) watching (with optional linux inotify support).
23
24
  - wallclock-based times (using absolute time, cron-like).
24
25
  - relative timers/timeouts (handle time jumps).
@@ -1,7 +1,7 @@
1
1
  /*
2
2
  * libev event processing core, watcher management
3
3
  *
4
- * Copyright (c) 2007-2018 Marc Alexander Lehmann <libev@schmorp.de>
4
+ * Copyright (c) 2007-2019 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-
@@ -126,6 +126,15 @@
126
126
  # define EV_USE_EPOLL 0
127
127
  # endif
128
128
 
129
+ # if HAVE_LINUX_AIO_ABI_H
130
+ # ifndef EV_USE_LINUXAIO
131
+ # define EV_USE_LINUXAIO EV_FEATURE_BACKENDS
132
+ # endif
133
+ # else
134
+ # undef EV_USE_LINUXAIO
135
+ # define EV_USE_LINUXAIO 0
136
+ # endif
137
+
129
138
  # if HAVE_KQUEUE && HAVE_SYS_EVENT_H
130
139
  # ifndef EV_USE_KQUEUE
131
140
  # define EV_USE_KQUEUE EV_FEATURE_BACKENDS
@@ -430,6 +439,14 @@
430
439
  # endif
431
440
  #endif
432
441
 
442
+ #if EV_USE_LINUXAIO
443
+ # include <sys/syscall.h>
444
+ # if !SYS_io_getevents || !EV_USE_EPOLL /* ev_linxaio uses ev_poll.c:ev_epoll_create */
445
+ # undef EV_USE_LINUXAIO
446
+ # define EV_USE_LINUXAIO 0
447
+ # endif
448
+ #endif
449
+
433
450
  #if EV_USE_INOTIFY
434
451
  # include <sys/statfs.h>
435
452
  # include <sys/inotify.h>
@@ -545,7 +562,7 @@ struct signalfd_siginfo
545
562
  #define ECB_H
546
563
 
547
564
  /* 16 bits major, 16 bits minor */
548
- #define ECB_VERSION 0x00010005
565
+ #define ECB_VERSION 0x00010006
549
566
 
550
567
  #ifdef _WIN32
551
568
  typedef signed char int8_t;
@@ -669,6 +686,7 @@ struct signalfd_siginfo
669
686
 
670
687
  #ifndef ECB_MEMORY_FENCE
671
688
  #if ECB_GCC_VERSION(2,5) || defined __INTEL_COMPILER || (__llvm__ && __GNUC__) || __SUNPRO_C >= 0x5110 || __SUNPRO_CC >= 0x5110
689
+ #define ECB_MEMORY_FENCE_RELAXED __asm__ __volatile__ ("" : : : "memory")
672
690
  #if __i386 || __i386__
673
691
  #define ECB_MEMORY_FENCE __asm__ __volatile__ ("lock; orb $0, -1(%%esp)" : : : "memory")
674
692
  #define ECB_MEMORY_FENCE_ACQUIRE __asm__ __volatile__ ("" : : : "memory")
@@ -728,12 +746,14 @@ struct signalfd_siginfo
728
746
  #define ECB_MEMORY_FENCE __atomic_thread_fence (__ATOMIC_SEQ_CST)
729
747
  #define ECB_MEMORY_FENCE_ACQUIRE __atomic_thread_fence (__ATOMIC_ACQUIRE)
730
748
  #define ECB_MEMORY_FENCE_RELEASE __atomic_thread_fence (__ATOMIC_RELEASE)
749
+ #define ECB_MEMORY_FENCE_RELAXED __atomic_thread_fence (__ATOMIC_RELAXED)
731
750
 
732
751
  #elif ECB_CLANG_EXTENSION(c_atomic)
733
752
  /* see comment below (stdatomic.h) about the C11 memory model. */
734
753
  #define ECB_MEMORY_FENCE __c11_atomic_thread_fence (__ATOMIC_SEQ_CST)
735
754
  #define ECB_MEMORY_FENCE_ACQUIRE __c11_atomic_thread_fence (__ATOMIC_ACQUIRE)
736
755
  #define ECB_MEMORY_FENCE_RELEASE __c11_atomic_thread_fence (__ATOMIC_RELEASE)
756
+ #define ECB_MEMORY_FENCE_RELAXED __c11_atomic_thread_fence (__ATOMIC_RELAXED)
737
757
 
738
758
  #elif ECB_GCC_VERSION(4,4) || defined __INTEL_COMPILER || defined __clang__
739
759
  #define ECB_MEMORY_FENCE __sync_synchronize ()
@@ -753,9 +773,10 @@ struct signalfd_siginfo
753
773
  #define ECB_MEMORY_FENCE MemoryBarrier () /* actually just xchg on x86... scary */
754
774
  #elif __SUNPRO_C >= 0x5110 || __SUNPRO_CC >= 0x5110
755
775
  #include <mbarrier.h>
756
- #define ECB_MEMORY_FENCE __machine_rw_barrier ()
757
- #define ECB_MEMORY_FENCE_ACQUIRE __machine_r_barrier ()
758
- #define ECB_MEMORY_FENCE_RELEASE __machine_w_barrier ()
776
+ #define ECB_MEMORY_FENCE __machine_rw_barrier ()
777
+ #define ECB_MEMORY_FENCE_ACQUIRE __machine_acq_barrier ()
778
+ #define ECB_MEMORY_FENCE_RELEASE __machine_rel_barrier ()
779
+ #define ECB_MEMORY_FENCE_RELAXED __compiler_barrier ()
759
780
  #elif __xlC__
760
781
  #define ECB_MEMORY_FENCE __sync ()
761
782
  #endif
@@ -766,15 +787,9 @@ struct signalfd_siginfo
766
787
  /* we assume that these memory fences work on all variables/all memory accesses, */
767
788
  /* not just C11 atomics and atomic accesses */
768
789
  #include <stdatomic.h>
769
- /* Unfortunately, neither gcc 4.7 nor clang 3.1 generate any instructions for */
770
- /* any fence other than seq_cst, which isn't very efficient for us. */
771
- /* Why that is, we don't know - either the C11 memory model is quite useless */
772
- /* for most usages, or gcc and clang have a bug */
773
- /* I *currently* lean towards the latter, and inefficiently implement */
774
- /* all three of ecb's fences as a seq_cst fence */
775
- /* Update, gcc-4.8 generates mfence for all c++ fences, but nothing */
776
- /* for all __atomic_thread_fence's except seq_cst */
777
790
  #define ECB_MEMORY_FENCE atomic_thread_fence (memory_order_seq_cst)
791
+ #define ECB_MEMORY_FENCE_ACQUIRE atomic_thread_fence (memory_order_acquire)
792
+ #define ECB_MEMORY_FENCE_RELEASE atomic_thread_fence (memory_order_release)
778
793
  #endif
779
794
  #endif
780
795
 
@@ -804,6 +819,10 @@ struct signalfd_siginfo
804
819
  #define ECB_MEMORY_FENCE_RELEASE ECB_MEMORY_FENCE
805
820
  #endif
806
821
 
822
+ #if !defined ECB_MEMORY_FENCE_RELAXED && defined ECB_MEMORY_FENCE
823
+ #define ECB_MEMORY_FENCE_RELAXED ECB_MEMORY_FENCE /* very heavy-handed */
824
+ #endif
825
+
807
826
  /*****************************************************************************/
808
827
 
809
828
  #if ECB_CPP
@@ -1554,8 +1573,7 @@ ecb_binary32_to_binary16 (uint32_t x)
1554
1573
  # define ABSPRI(w) (((W)w)->priority - EV_MINPRI)
1555
1574
  #endif
1556
1575
 
1557
- #define EMPTY /* required for microsofts broken pseudo-c compiler */
1558
- #define EMPTY2(a,b) /* used to suppress some warnings */
1576
+ #define EMPTY /* required for microsofts broken pseudo-c compiler */
1559
1577
 
1560
1578
  typedef ev_watcher *W;
1561
1579
  typedef ev_watcher_list *WL;
@@ -1590,6 +1608,10 @@ static EV_ATOMIC_T have_monotonic; /* did clock_gettime (CLOCK_MONOTONIC) work?
1590
1608
 
1591
1609
  /*****************************************************************************/
1592
1610
 
1611
+ #if EV_USE_LINUXAIO
1612
+ # include <linux/aio_abi.h> /* probably only needed for aio_context_t */
1613
+ #endif
1614
+
1593
1615
  /* define a suitable floor function (only used by periodics atm) */
1594
1616
 
1595
1617
  #if EV_USE_FLOOR
@@ -1724,7 +1746,7 @@ ev_syserr (const char *msg)
1724
1746
  }
1725
1747
 
1726
1748
  static void *
1727
- ev_realloc_emul (void *ptr, long size) EV_NOEXCEPT
1749
+ ev_realloc_emul (void *ptr, size_t size) EV_NOEXCEPT
1728
1750
  {
1729
1751
  /* some systems, notably openbsd and darwin, fail to properly
1730
1752
  * implement realloc (x, 0) (as required by both ansi c-89 and
@@ -1740,17 +1762,17 @@ ev_realloc_emul (void *ptr, long size) EV_NOEXCEPT
1740
1762
  return 0;
1741
1763
  }
1742
1764
 
1743
- static void *(*alloc)(void *ptr, long size) EV_NOEXCEPT = ev_realloc_emul;
1765
+ static void *(*alloc)(void *ptr, size_t size) EV_NOEXCEPT = ev_realloc_emul;
1744
1766
 
1745
1767
  ecb_cold
1746
1768
  void
1747
- ev_set_allocator (void *(*cb)(void *ptr, long size) EV_NOEXCEPT) EV_NOEXCEPT
1769
+ ev_set_allocator (void *(*cb)(void *ptr, size_t size) EV_NOEXCEPT) EV_NOEXCEPT
1748
1770
  {
1749
1771
  alloc = cb;
1750
1772
  }
1751
1773
 
1752
1774
  inline_speed void *
1753
- ev_realloc (void *ptr, long size)
1775
+ ev_realloc (void *ptr, size_t size)
1754
1776
  {
1755
1777
  ptr = alloc (ptr, size);
1756
1778
 
@@ -1781,7 +1803,7 @@ typedef struct
1781
1803
  WL head;
1782
1804
  unsigned char events; /* the events watched for */
1783
1805
  unsigned char reify; /* flag set when this ANFD needs reification (EV_ANFD_REIFY, EV__IOFDSET) */
1784
- unsigned char emask; /* the epoll backend stores the actual kernel mask in here */
1806
+ unsigned char emask; /* some backends store the actual kernel mask in here */
1785
1807
  unsigned char unused;
1786
1808
  #if EV_USE_EPOLL
1787
1809
  unsigned int egen; /* generation counter to counter epoll bugs */
@@ -1972,8 +1994,10 @@ array_realloc (int elem, void *base, int *cur, int cnt)
1972
1994
  return ev_realloc (base, elem * *cur);
1973
1995
  }
1974
1996
 
1975
- #define array_init_zero(base,count) \
1976
- memset ((void *)(base), 0, sizeof (*(base)) * (count))
1997
+ #define array_needsize_noinit(base,offset,count)
1998
+
1999
+ #define array_needsize_zerofill(base,offset,count) \
2000
+ memset ((void *)(base + offset), 0, sizeof (*(base)) * (count))
1977
2001
 
1978
2002
  #define array_needsize(type,base,cur,cnt,init) \
1979
2003
  if (expect_false ((cnt) > (cur))) \
@@ -1981,7 +2005,7 @@ array_realloc (int elem, void *base, int *cur, int cnt)
1981
2005
  ecb_unused int ocur_ = (cur); \
1982
2006
  (base) = (type *)array_realloc \
1983
2007
  (sizeof (type), (base), &(cur), (cnt)); \
1984
- init ((base) + (ocur_), (cur) - ocur_); \
2008
+ init ((base), ocur_, ((cur) - ocur_)); \
1985
2009
  }
1986
2010
 
1987
2011
  #if 0
@@ -2018,7 +2042,7 @@ ev_feed_event (EV_P_ void *w, int revents) EV_NOEXCEPT
2018
2042
  else
2019
2043
  {
2020
2044
  w_->pending = ++pendingcnt [pri];
2021
- array_needsize (ANPENDING, pendings [pri], pendingmax [pri], w_->pending, EMPTY2);
2045
+ array_needsize (ANPENDING, pendings [pri], pendingmax [pri], w_->pending, array_needsize_noinit);
2022
2046
  pendings [pri][w_->pending - 1].w = w_;
2023
2047
  pendings [pri][w_->pending - 1].events = revents;
2024
2048
  }
@@ -2029,7 +2053,7 @@ ev_feed_event (EV_P_ void *w, int revents) EV_NOEXCEPT
2029
2053
  inline_speed void
2030
2054
  feed_reverse (EV_P_ W w)
2031
2055
  {
2032
- array_needsize (W, rfeeds, rfeedmax, rfeedcnt + 1, EMPTY2);
2056
+ array_needsize (W, rfeeds, rfeedmax, rfeedcnt + 1, array_needsize_noinit);
2033
2057
  rfeeds [rfeedcnt++] = w;
2034
2058
  }
2035
2059
 
@@ -2126,7 +2150,7 @@ fd_reify (EV_P)
2126
2150
  unsigned char o_events = anfd->events;
2127
2151
  unsigned char o_reify = anfd->reify;
2128
2152
 
2129
- anfd->reify = 0;
2153
+ anfd->reify = 0;
2130
2154
 
2131
2155
  /*if (expect_true (o_reify & EV_ANFD_REIFY)) probably a deoptimisation */
2132
2156
  {
@@ -2157,7 +2181,7 @@ fd_change (EV_P_ int fd, int flags)
2157
2181
  if (expect_true (!reify))
2158
2182
  {
2159
2183
  ++fdchangecnt;
2160
- array_needsize (int, fdchanges, fdchangemax, fdchangecnt, EMPTY2);
2184
+ array_needsize (int, fdchanges, fdchangemax, fdchangecnt, array_needsize_noinit);
2161
2185
  fdchanges [fdchangecnt - 1] = fd;
2162
2186
  }
2163
2187
  }
@@ -2717,6 +2741,9 @@ childcb (EV_P_ ev_signal *sw, int revents)
2717
2741
  #if EV_USE_EPOLL
2718
2742
  # include "ev_epoll.c"
2719
2743
  #endif
2744
+ #if EV_USE_LINUXAIO
2745
+ # include "ev_linuxaio.c"
2746
+ #endif
2720
2747
  #if EV_USE_POLL
2721
2748
  # include "ev_poll.c"
2722
2749
  #endif
@@ -2754,11 +2781,16 @@ ev_supported_backends (void) EV_NOEXCEPT
2754
2781
  {
2755
2782
  unsigned int flags = 0;
2756
2783
 
2757
- if (EV_USE_PORT ) flags |= EVBACKEND_PORT;
2758
- if (EV_USE_KQUEUE) flags |= EVBACKEND_KQUEUE;
2759
- if (EV_USE_EPOLL ) flags |= EVBACKEND_EPOLL;
2760
- if (EV_USE_POLL ) flags |= EVBACKEND_POLL;
2761
- if (EV_USE_SELECT) flags |= EVBACKEND_SELECT;
2784
+ if (EV_USE_PORT ) flags |= EVBACKEND_PORT;
2785
+ if (EV_USE_KQUEUE ) flags |= EVBACKEND_KQUEUE;
2786
+ if (EV_USE_EPOLL ) flags |= EVBACKEND_EPOLL;
2787
+
2788
+ #ifdef EV_USE_LINUXAIO
2789
+ if (EV_USE_LINUXAIO) flags |= EVBACKEND_LINUXAIO;
2790
+ #endif
2791
+
2792
+ if (EV_USE_POLL ) flags |= EVBACKEND_POLL;
2793
+ if (EV_USE_SELECT ) flags |= EVBACKEND_SELECT;
2762
2794
 
2763
2795
  return flags;
2764
2796
  }
@@ -2784,6 +2816,11 @@ ev_recommended_backends (void) EV_NOEXCEPT
2784
2816
  flags &= ~EVBACKEND_POLL; /* poll return value is unusable (http://forums.freebsd.org/archive/index.php/t-10270.html) */
2785
2817
  #endif
2786
2818
 
2819
+ /* TODO: linuxaio is very experimental */
2820
+ #if !EV_RECOMMEND_LINUXAIO
2821
+ flags &= ~EVBACKEND_LINUXAIO;
2822
+ #endif
2823
+
2787
2824
  return flags;
2788
2825
  }
2789
2826
 
@@ -2928,22 +2965,25 @@ loop_init (EV_P_ unsigned int flags) EV_NOEXCEPT
2928
2965
  flags |= ev_recommended_backends ();
2929
2966
 
2930
2967
  #if EV_USE_IOCP
2931
- if (!backend && (flags & EVBACKEND_IOCP )) backend = iocp_init (EV_A_ flags);
2968
+ if (!backend && (flags & EVBACKEND_IOCP )) backend = iocp_init (EV_A_ flags);
2932
2969
  #endif
2933
2970
  #if EV_USE_PORT
2934
- if (!backend && (flags & EVBACKEND_PORT )) backend = port_init (EV_A_ flags);
2971
+ if (!backend && (flags & EVBACKEND_PORT )) backend = port_init (EV_A_ flags);
2935
2972
  #endif
2936
2973
  #if EV_USE_KQUEUE
2937
- if (!backend && (flags & EVBACKEND_KQUEUE)) backend = kqueue_init (EV_A_ flags);
2974
+ if (!backend && (flags & EVBACKEND_KQUEUE )) backend = kqueue_init (EV_A_ flags);
2975
+ #endif
2976
+ #if EV_USE_LINUXAIO
2977
+ if (!backend && (flags & EVBACKEND_LINUXAIO)) backend = linuxaio_init (EV_A_ flags);
2938
2978
  #endif
2939
2979
  #if EV_USE_EPOLL
2940
- if (!backend && (flags & EVBACKEND_EPOLL )) backend = epoll_init (EV_A_ flags);
2980
+ if (!backend && (flags & EVBACKEND_EPOLL )) backend = epoll_init (EV_A_ flags);
2941
2981
  #endif
2942
2982
  #if EV_USE_POLL
2943
- if (!backend && (flags & EVBACKEND_POLL )) backend = poll_init (EV_A_ flags);
2983
+ if (!backend && (flags & EVBACKEND_POLL )) backend = poll_init (EV_A_ flags);
2944
2984
  #endif
2945
2985
  #if EV_USE_SELECT
2946
- if (!backend && (flags & EVBACKEND_SELECT)) backend = select_init (EV_A_ flags);
2986
+ if (!backend && (flags & EVBACKEND_SELECT )) backend = select_init (EV_A_ flags);
2947
2987
  #endif
2948
2988
 
2949
2989
  ev_prepare_init (&pending_w, pendingcb);
@@ -3008,22 +3048,25 @@ ev_loop_destroy (EV_P)
3008
3048
  close (backend_fd);
3009
3049
 
3010
3050
  #if EV_USE_IOCP
3011
- if (backend == EVBACKEND_IOCP ) iocp_destroy (EV_A);
3051
+ if (backend == EVBACKEND_IOCP ) iocp_destroy (EV_A);
3012
3052
  #endif
3013
3053
  #if EV_USE_PORT
3014
- if (backend == EVBACKEND_PORT ) port_destroy (EV_A);
3054
+ if (backend == EVBACKEND_PORT ) port_destroy (EV_A);
3015
3055
  #endif
3016
3056
  #if EV_USE_KQUEUE
3017
- if (backend == EVBACKEND_KQUEUE) kqueue_destroy (EV_A);
3057
+ if (backend == EVBACKEND_KQUEUE ) kqueue_destroy (EV_A);
3058
+ #endif
3059
+ #if EV_USE_LINUXAIO
3060
+ if (backend == EVBACKEND_LINUXAIO) linuxaio_destroy (EV_A);
3018
3061
  #endif
3019
3062
  #if EV_USE_EPOLL
3020
- if (backend == EVBACKEND_EPOLL ) epoll_destroy (EV_A);
3063
+ if (backend == EVBACKEND_EPOLL ) epoll_destroy (EV_A);
3021
3064
  #endif
3022
3065
  #if EV_USE_POLL
3023
- if (backend == EVBACKEND_POLL ) poll_destroy (EV_A);
3066
+ if (backend == EVBACKEND_POLL ) poll_destroy (EV_A);
3024
3067
  #endif
3025
3068
  #if EV_USE_SELECT
3026
- if (backend == EVBACKEND_SELECT) select_destroy (EV_A);
3069
+ if (backend == EVBACKEND_SELECT ) select_destroy (EV_A);
3027
3070
  #endif
3028
3071
 
3029
3072
  for (i = NUMPRI; i--; )
@@ -3075,13 +3118,16 @@ inline_size void
3075
3118
  loop_fork (EV_P)
3076
3119
  {
3077
3120
  #if EV_USE_PORT
3078
- if (backend == EVBACKEND_PORT ) port_fork (EV_A);
3121
+ if (backend == EVBACKEND_PORT ) port_fork (EV_A);
3079
3122
  #endif
3080
3123
  #if EV_USE_KQUEUE
3081
- if (backend == EVBACKEND_KQUEUE) kqueue_fork (EV_A);
3124
+ if (backend == EVBACKEND_KQUEUE ) kqueue_fork (EV_A);
3125
+ #endif
3126
+ #if EV_USE_LINUXAIO
3127
+ if (backend == EVBACKEND_LINUXAIO) linuxaio_fork (EV_A);
3082
3128
  #endif
3083
3129
  #if EV_USE_EPOLL
3084
- if (backend == EVBACKEND_EPOLL ) epoll_fork (EV_A);
3130
+ if (backend == EVBACKEND_EPOLL ) epoll_fork (EV_A);
3085
3131
  #endif
3086
3132
  #if EV_USE_INOTIFY
3087
3133
  infy_fork (EV_A);
@@ -3586,11 +3632,13 @@ struct ev_poll_args {
3586
3632
  };
3587
3633
 
3588
3634
  static
3589
- VALUE ev_backend_poll(void *ptr)
3635
+ void * ev_backend_poll(void *ptr)
3590
3636
  {
3591
3637
  struct ev_poll_args *args = (struct ev_poll_args *)ptr;
3592
3638
  struct ev_loop *loop = args->loop;
3593
3639
  backend_poll (EV_A_ args->waittime);
3640
+
3641
+ return NULL;
3594
3642
  }
3595
3643
  /* ######################################## */
3596
3644
 
@@ -3598,7 +3646,7 @@ int
3598
3646
  ev_run (EV_P_ int flags)
3599
3647
  {
3600
3648
  /* ########## NIO4R PATCHERY HO! ########## */
3601
- struct ev_poll_args poll_args;
3649
+ struct ev_poll_args poll_args;
3602
3650
  /* ######################################## */
3603
3651
 
3604
3652
  #if EV_FEATURE_API
@@ -3951,10 +3999,13 @@ ev_io_start (EV_P_ ev_io *w) EV_NOEXCEPT
3951
3999
  assert (("libev: ev_io_start called with negative fd", fd >= 0));
3952
4000
  assert (("libev: ev_io_start called with illegal event mask", !(w->events & ~(EV__IOFDSET | EV_READ | EV_WRITE))));
3953
4001
 
4002
+ #if EV_VERIFY >= 2
4003
+ assert (("libev: ev_io_start called on watcher with invalid fd", fd_valid (fd)));
4004
+ #endif
3954
4005
  EV_FREQUENT_CHECK;
3955
4006
 
3956
4007
  ev_start (EV_A_ (W)w, 1);
3957
- array_needsize (ANFD, anfds, anfdmax, fd + 1, array_init_zero);
4008
+ array_needsize (ANFD, anfds, anfdmax, fd + 1, array_needsize_zerofill);
3958
4009
  wlist_add (&anfds[fd].head, (WL)w);
3959
4010
 
3960
4011
  /* common bug, apparently */
@@ -3976,6 +4027,9 @@ ev_io_stop (EV_P_ ev_io *w) EV_NOEXCEPT
3976
4027
 
3977
4028
  assert (("libev: ev_io_stop called with illegal fd (must stay constant after start!)", w->fd >= 0 && w->fd < anfdmax));
3978
4029
 
4030
+ #if EV_VERIFY >= 2
4031
+ assert (("libev: ev_io_stop called on watcher with invalid fd", fd_valid (w->fd)));
4032
+ #endif
3979
4033
  EV_FREQUENT_CHECK;
3980
4034
 
3981
4035
  wlist_del (&anfds[w->fd].head, (WL)w);
@@ -4001,7 +4055,7 @@ ev_timer_start (EV_P_ ev_timer *w) EV_NOEXCEPT
4001
4055
 
4002
4056
  ++timercnt;
4003
4057
  ev_start (EV_A_ (W)w, timercnt + HEAP0 - 1);
4004
- array_needsize (ANHE, timers, timermax, ev_active (w) + 1, EMPTY2);
4058
+ array_needsize (ANHE, timers, timermax, ev_active (w) + 1, array_needsize_noinit);
4005
4059
  ANHE_w (timers [ev_active (w)]) = (WT)w;
4006
4060
  ANHE_at_cache (timers [ev_active (w)]);
4007
4061
  upheap (timers, ev_active (w));
@@ -4098,7 +4152,7 @@ ev_periodic_start (EV_P_ ev_periodic *w) EV_NOEXCEPT
4098
4152
 
4099
4153
  ++periodiccnt;
4100
4154
  ev_start (EV_A_ (W)w, periodiccnt + HEAP0 - 1);
4101
- array_needsize (ANHE, periodics, periodicmax, ev_active (w) + 1, EMPTY2);
4155
+ array_needsize (ANHE, periodics, periodicmax, ev_active (w) + 1, array_needsize_noinit);
4102
4156
  ANHE_w (periodics [ev_active (w)]) = (WT)w;
4103
4157
  ANHE_at_cache (periodics [ev_active (w)]);
4104
4158
  upheap (periodics, ev_active (w));
@@ -4693,7 +4747,7 @@ ev_idle_start (EV_P_ ev_idle *w) EV_NOEXCEPT
4693
4747
  ++idleall;
4694
4748
  ev_start (EV_A_ (W)w, active);
4695
4749
 
4696
- array_needsize (ev_idle *, idles [ABSPRI (w)], idlemax [ABSPRI (w)], active, EMPTY2);
4750
+ array_needsize (ev_idle *, idles [ABSPRI (w)], idlemax [ABSPRI (w)], active, array_needsize_noinit);
4697
4751
  idles [ABSPRI (w)][active - 1] = w;
4698
4752
  }
4699
4753
 
@@ -4733,7 +4787,7 @@ ev_prepare_start (EV_P_ ev_prepare *w) EV_NOEXCEPT
4733
4787
  EV_FREQUENT_CHECK;
4734
4788
 
4735
4789
  ev_start (EV_A_ (W)w, ++preparecnt);
4736
- array_needsize (ev_prepare *, prepares, preparemax, preparecnt, EMPTY2);
4790
+ array_needsize (ev_prepare *, prepares, preparemax, preparecnt, array_needsize_noinit);
4737
4791
  prepares [preparecnt - 1] = w;
4738
4792
 
4739
4793
  EV_FREQUENT_CHECK;
@@ -4771,7 +4825,7 @@ ev_check_start (EV_P_ ev_check *w) EV_NOEXCEPT
4771
4825
  EV_FREQUENT_CHECK;
4772
4826
 
4773
4827
  ev_start (EV_A_ (W)w, ++checkcnt);
4774
- array_needsize (ev_check *, checks, checkmax, checkcnt, EMPTY2);
4828
+ array_needsize (ev_check *, checks, checkmax, checkcnt, array_needsize_noinit);
4775
4829
  checks [checkcnt - 1] = w;
4776
4830
 
4777
4831
  EV_FREQUENT_CHECK;
@@ -4919,7 +4973,7 @@ ev_fork_start (EV_P_ ev_fork *w) EV_NOEXCEPT
4919
4973
  EV_FREQUENT_CHECK;
4920
4974
 
4921
4975
  ev_start (EV_A_ (W)w, ++forkcnt);
4922
- array_needsize (ev_fork *, forks, forkmax, forkcnt, EMPTY2);
4976
+ array_needsize (ev_fork *, forks, forkmax, forkcnt, array_needsize_noinit);
4923
4977
  forks [forkcnt - 1] = w;
4924
4978
 
4925
4979
  EV_FREQUENT_CHECK;
@@ -4957,7 +5011,7 @@ ev_cleanup_start (EV_P_ ev_cleanup *w) EV_NOEXCEPT
4957
5011
  EV_FREQUENT_CHECK;
4958
5012
 
4959
5013
  ev_start (EV_A_ (W)w, ++cleanupcnt);
4960
- array_needsize (ev_cleanup *, cleanups, cleanupmax, cleanupcnt, EMPTY2);
5014
+ array_needsize (ev_cleanup *, cleanups, cleanupmax, cleanupcnt, array_needsize_noinit);
4961
5015
  cleanups [cleanupcnt - 1] = w;
4962
5016
 
4963
5017
  /* cleanup watchers should never keep a refcount on the loop */
@@ -5002,7 +5056,7 @@ ev_async_start (EV_P_ ev_async *w) EV_NOEXCEPT
5002
5056
  EV_FREQUENT_CHECK;
5003
5057
 
5004
5058
  ev_start (EV_A_ (W)w, ++asynccnt);
5005
- array_needsize (ev_async *, asyncs, asyncmax, asynccnt, EMPTY2);
5059
+ array_needsize (ev_async *, asyncs, asyncmax, asynccnt, array_needsize_noinit);
5006
5060
  asyncs [asynccnt - 1] = w;
5007
5061
 
5008
5062
  EV_FREQUENT_CHECK;
@@ -5081,12 +5135,6 @@ ev_once (EV_P_ int fd, int events, ev_tstamp timeout, void (*cb)(int revents, vo
5081
5135
  {
5082
5136
  struct ev_once *once = (struct ev_once *)ev_malloc (sizeof (struct ev_once));
5083
5137
 
5084
- if (expect_false (!once))
5085
- {
5086
- cb (EV_ERROR | EV_READ | EV_WRITE | EV_TIMER, arg);
5087
- return;
5088
- }
5089
-
5090
5138
  once->cb = cb;
5091
5139
  once->arg = arg;
5092
5140