ever 0.1
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 +7 -0
- data/.github/workflows/test.yml +29 -0
- data/.gitignore +57 -0
- data/CHANGELOG.md +3 -0
- data/Gemfile +3 -0
- data/Gemfile.lock +25 -0
- data/LICENSE +21 -0
- data/README.md +167 -0
- data/Rakefile +18 -0
- data/ever.gemspec +26 -0
- data/examples/http_server.rb +124 -0
- data/ext/ever/ever.h +49 -0
- data/ext/ever/ever_ext.c +12 -0
- data/ext/ever/extconf.rb +22 -0
- data/ext/ever/libev.c +2 -0
- data/ext/ever/libev.h +11 -0
- data/ext/ever/loop.c +257 -0
- data/ext/ever/watcher.c +137 -0
- data/ext/libev/Changes +548 -0
- data/ext/libev/LICENSE +37 -0
- data/ext/libev/README +59 -0
- data/ext/libev/README.embed +3 -0
- data/ext/libev/ev.c +5279 -0
- data/ext/libev/ev.h +856 -0
- data/ext/libev/ev_epoll.c +296 -0
- data/ext/libev/ev_kqueue.c +224 -0
- data/ext/libev/ev_linuxaio.c +642 -0
- data/ext/libev/ev_poll.c +156 -0
- data/ext/libev/ev_port.c +192 -0
- data/ext/libev/ev_select.c +316 -0
- data/ext/libev/ev_vars.h +215 -0
- data/ext/libev/ev_win32.c +162 -0
- data/ext/libev/ev_wrap.h +216 -0
- data/ext/libev/test_libev_win32.c +123 -0
- data/lib/ever/version.rb +5 -0
- data/lib/ever.rb +3 -0
- data/test/helper.rb +13 -0
- data/test/run.rb +0 -0
- data/test/test_loop.rb +87 -0
- metadata +131 -0
@@ -0,0 +1,123 @@
|
|
1
|
+
// a single header file is required
|
2
|
+
#include <ev.h>
|
3
|
+
#include <stdio.h>
|
4
|
+
#include <io.h>
|
5
|
+
|
6
|
+
// every watcher type has its own typedef'd struct
|
7
|
+
// with the name ev_TYPE
|
8
|
+
ev_io stdin_watcher;
|
9
|
+
ev_timer timeout_watcher;
|
10
|
+
|
11
|
+
// all watcher callbacks have a similar signature
|
12
|
+
// this callback is called when data is readable on stdin
|
13
|
+
static void
|
14
|
+
stdin_cb (EV_P_ ev_io *w, int revents)
|
15
|
+
{
|
16
|
+
puts ("stdin ready or done or something");
|
17
|
+
// for one-shot events, one must manually stop the watcher
|
18
|
+
// with its corresponding stop function.
|
19
|
+
//ev_io_stop (EV_A_ w);
|
20
|
+
|
21
|
+
// this causes all nested ev_loop's to stop iterating
|
22
|
+
//ev_unloop (EV_A_ EVUNLOOP_ALL);
|
23
|
+
}
|
24
|
+
|
25
|
+
// another callback, this time for a time-out
|
26
|
+
static void
|
27
|
+
timeout_cb (EV_P_ ev_timer *w, int revents)
|
28
|
+
{
|
29
|
+
puts ("timeout");
|
30
|
+
// this causes the innermost ev_loop to stop iterating
|
31
|
+
ev_unloop (EV_A_ EVUNLOOP_ONE);
|
32
|
+
}
|
33
|
+
|
34
|
+
|
35
|
+
|
36
|
+
#include <winsock.h>
|
37
|
+
|
38
|
+
#include <stdlib.h>
|
39
|
+
#include <iostream>
|
40
|
+
int get_server_fd()
|
41
|
+
{
|
42
|
+
|
43
|
+
//----------------------
|
44
|
+
// Initialize Winsock.
|
45
|
+
WSADATA wsaData;
|
46
|
+
int iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
|
47
|
+
if (iResult != NO_ERROR) {
|
48
|
+
printf("Error at WSAStartup()\n");
|
49
|
+
return 1;
|
50
|
+
}
|
51
|
+
|
52
|
+
//----------------------
|
53
|
+
// Create a SOCKET for listening for
|
54
|
+
// incoming connection requests.
|
55
|
+
SOCKET ListenSocket;
|
56
|
+
ListenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
57
|
+
if (ListenSocket == INVALID_SOCKET) {
|
58
|
+
printf("Error at socket(): %ld\n", WSAGetLastError());
|
59
|
+
WSACleanup();
|
60
|
+
return 1;
|
61
|
+
}
|
62
|
+
printf("socket returned %d\n", ListenSocket);
|
63
|
+
|
64
|
+
//----------------------
|
65
|
+
// The sockaddr_in structure specifies the address family,
|
66
|
+
// IP address, and port for the socket that is being bound.
|
67
|
+
sockaddr_in service;
|
68
|
+
service.sin_family = AF_INET;
|
69
|
+
service.sin_addr.s_addr = inet_addr("127.0.0.1");
|
70
|
+
service.sin_port = htons(4444);
|
71
|
+
|
72
|
+
if (bind( ListenSocket,
|
73
|
+
(SOCKADDR*) &service,
|
74
|
+
sizeof(service)) == SOCKET_ERROR) {
|
75
|
+
printf("bind() failed.\n");
|
76
|
+
closesocket(ListenSocket);
|
77
|
+
WSACleanup();
|
78
|
+
return 1;
|
79
|
+
}
|
80
|
+
|
81
|
+
//----------------------
|
82
|
+
// Listen for incoming connection requests.
|
83
|
+
// on the created socket
|
84
|
+
if (listen( ListenSocket, 1 ) == SOCKET_ERROR) {
|
85
|
+
printf("Error listening on socket.\n");
|
86
|
+
closesocket(ListenSocket);
|
87
|
+
WSACleanup();
|
88
|
+
return 1;
|
89
|
+
}
|
90
|
+
|
91
|
+
|
92
|
+
printf("sock and osf handle are %d %d, error is \n", ListenSocket, _get_osfhandle (ListenSocket)); // -1 is invalid file handle: http://msdn.microsoft.com/en-us/library/ks2530z6.aspx
|
93
|
+
printf("err was %d\n", WSAGetLastError());
|
94
|
+
//----------------------
|
95
|
+
return ListenSocket;
|
96
|
+
}
|
97
|
+
|
98
|
+
|
99
|
+
int
|
100
|
+
main (void)
|
101
|
+
{
|
102
|
+
struct ev_loop *loopy = ev_default_loop(0);
|
103
|
+
int fd = get_server_fd();
|
104
|
+
int fd_real = _open_osfhandle(fd, NULL);
|
105
|
+
int conv = _get_osfhandle(fd_real);
|
106
|
+
printf("got server fd %d, loop %d, fd_real %d, that converted %d\n", fd, loopy, fd_real, conv);
|
107
|
+
// accept(fd, NULL, NULL);
|
108
|
+
// initialise an io watcher, then start it
|
109
|
+
// this one will watch for stdin to become readable
|
110
|
+
ev_io_init (&stdin_watcher, stdin_cb, /*STDIN_FILENO*/ conv, EV_READ);
|
111
|
+
ev_io_start (loopy, &stdin_watcher);
|
112
|
+
|
113
|
+
// initialise a timer watcher, then start it
|
114
|
+
// simple non-repeating 5.5 second timeout
|
115
|
+
//ev_timer_init (&timeout_watcher, timeout_cb, 15.5, 0.);
|
116
|
+
//ev_timer_start (loopy, &timeout_watcher);
|
117
|
+
printf("starting loop\n");
|
118
|
+
// now wait for events to arrive
|
119
|
+
ev_loop (loopy, 0);
|
120
|
+
|
121
|
+
// unloop was called, so exit
|
122
|
+
return 0;
|
123
|
+
}
|
data/lib/ever/version.rb
ADDED
data/lib/ever.rb
ADDED
data/test/helper.rb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'bundler/setup'
|
4
|
+
|
5
|
+
require 'fileutils'
|
6
|
+
require 'minitest/autorun'
|
7
|
+
|
8
|
+
module Minitest::Assertions
|
9
|
+
def assert_in_range exp_range, act
|
10
|
+
msg = message(msg) { "Expected #{mu_pp(act)} to be in range #{mu_pp(exp_range)}" }
|
11
|
+
assert exp_range.include?(act), msg
|
12
|
+
end
|
13
|
+
end
|
data/test/run.rb
ADDED
File without changes
|
data/test/test_loop.rb
ADDED
@@ -0,0 +1,87 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'helper'
|
4
|
+
require 'ever'
|
5
|
+
|
6
|
+
class LoopTest < MiniTest::Test
|
7
|
+
def setup
|
8
|
+
super
|
9
|
+
@loop = Ever::Loop.new
|
10
|
+
end
|
11
|
+
|
12
|
+
def test_no_watchers
|
13
|
+
@loop.emit(1)
|
14
|
+
@loop.emit(2)
|
15
|
+
@loop.emit(3)
|
16
|
+
buf = []
|
17
|
+
@loop.each do |key|
|
18
|
+
buf << key
|
19
|
+
@loop.emit(:stop) if key == 3
|
20
|
+
end
|
21
|
+
assert_equal [1, 2, 3], buf
|
22
|
+
end
|
23
|
+
|
24
|
+
def test_io
|
25
|
+
i, o = IO.pipe
|
26
|
+
|
27
|
+
@loop.watch_io('foo', i, false, true)
|
28
|
+
|
29
|
+
o << 'foo'
|
30
|
+
buf = []
|
31
|
+
@loop.each do |key|
|
32
|
+
buf << key
|
33
|
+
@loop.stop
|
34
|
+
end
|
35
|
+
|
36
|
+
assert_equal ['foo'], buf
|
37
|
+
end
|
38
|
+
|
39
|
+
def test_cross_thread_signalling
|
40
|
+
i, o = IO.pipe
|
41
|
+
@loop.watch_io('foo', i, false, true)
|
42
|
+
|
43
|
+
Thread.new { @loop.signal }
|
44
|
+
|
45
|
+
event = @loop.next_event
|
46
|
+
assert_nil nil, event
|
47
|
+
end
|
48
|
+
|
49
|
+
def test_emit
|
50
|
+
i, o = IO.pipe
|
51
|
+
@loop.watch_io('foo', i, false, true)
|
52
|
+
|
53
|
+
Thread.new { o << 'bar'; @loop.emit('baz') }
|
54
|
+
|
55
|
+
event = @loop.next_event
|
56
|
+
assert_equal 'baz', event
|
57
|
+
|
58
|
+
event = @loop.next_event
|
59
|
+
assert_equal 'foo', event
|
60
|
+
end
|
61
|
+
|
62
|
+
def test_timer_oneshot
|
63
|
+
@loop.watch_timer('foo', 0.01, 0)
|
64
|
+
|
65
|
+
t0 = Time.now
|
66
|
+
(event = @loop.next_event) until event;
|
67
|
+
t1 = Time.now
|
68
|
+
|
69
|
+
assert_equal 'foo', event
|
70
|
+
assert_in_range 0.005..0.02, t1 - t0
|
71
|
+
end
|
72
|
+
|
73
|
+
def test_timer_recurring
|
74
|
+
@loop.watch_timer('foo', 0.01, 0.01)
|
75
|
+
|
76
|
+
t0 = Time.now
|
77
|
+
buf = []
|
78
|
+
@loop.each do |key|
|
79
|
+
buf << Time.now if key == 'foo'
|
80
|
+
@loop.stop if buf.size == 3
|
81
|
+
end
|
82
|
+
t1 = Time.now
|
83
|
+
|
84
|
+
assert_equal 3, buf.size
|
85
|
+
assert_in_range 0.005..0.04, t1 - t0
|
86
|
+
end
|
87
|
+
end
|
metadata
ADDED
@@ -0,0 +1,131 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: ever
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: '0.1'
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Sharon Rosner
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2021-08-30 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rake-compiler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - '='
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 1.1.1
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - '='
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 1.1.1
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: minitest
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - '='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 5.14.4
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - '='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 5.14.4
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: http_parser.rb
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - '='
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 0.7.0
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - '='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 0.7.0
|
55
|
+
description:
|
56
|
+
email: sharon@noteflakes.com
|
57
|
+
executables: []
|
58
|
+
extensions:
|
59
|
+
- ext/ever/extconf.rb
|
60
|
+
extra_rdoc_files:
|
61
|
+
- README.md
|
62
|
+
files:
|
63
|
+
- ".github/workflows/test.yml"
|
64
|
+
- ".gitignore"
|
65
|
+
- CHANGELOG.md
|
66
|
+
- Gemfile
|
67
|
+
- Gemfile.lock
|
68
|
+
- LICENSE
|
69
|
+
- README.md
|
70
|
+
- Rakefile
|
71
|
+
- ever.gemspec
|
72
|
+
- examples/http_server.rb
|
73
|
+
- ext/ever/ever.h
|
74
|
+
- ext/ever/ever_ext.c
|
75
|
+
- ext/ever/extconf.rb
|
76
|
+
- ext/ever/libev.c
|
77
|
+
- ext/ever/libev.h
|
78
|
+
- ext/ever/loop.c
|
79
|
+
- ext/ever/watcher.c
|
80
|
+
- ext/libev/Changes
|
81
|
+
- ext/libev/LICENSE
|
82
|
+
- ext/libev/README
|
83
|
+
- ext/libev/README.embed
|
84
|
+
- ext/libev/ev.c
|
85
|
+
- ext/libev/ev.h
|
86
|
+
- ext/libev/ev_epoll.c
|
87
|
+
- ext/libev/ev_kqueue.c
|
88
|
+
- ext/libev/ev_linuxaio.c
|
89
|
+
- ext/libev/ev_poll.c
|
90
|
+
- ext/libev/ev_port.c
|
91
|
+
- ext/libev/ev_select.c
|
92
|
+
- ext/libev/ev_vars.h
|
93
|
+
- ext/libev/ev_win32.c
|
94
|
+
- ext/libev/ev_wrap.h
|
95
|
+
- ext/libev/test_libev_win32.c
|
96
|
+
- lib/ever.rb
|
97
|
+
- lib/ever/version.rb
|
98
|
+
- test/helper.rb
|
99
|
+
- test/run.rb
|
100
|
+
- test/test_loop.rb
|
101
|
+
homepage: https://digital-fabric.github.io/ever
|
102
|
+
licenses:
|
103
|
+
- MIT
|
104
|
+
metadata:
|
105
|
+
source_code_uri: https://github.com/digital-fabric/ever
|
106
|
+
homepage_uri: https://github.com/digital-fabric/ever
|
107
|
+
changelog_uri: https://github.com/digital-fabric/ever/blob/master/CHANGELOG.md
|
108
|
+
post_install_message:
|
109
|
+
rdoc_options:
|
110
|
+
- "--title"
|
111
|
+
- ever
|
112
|
+
- "--main"
|
113
|
+
- README.md
|
114
|
+
require_paths:
|
115
|
+
- lib
|
116
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
117
|
+
requirements:
|
118
|
+
- - ">="
|
119
|
+
- !ruby/object:Gem::Version
|
120
|
+
version: '2.6'
|
121
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
122
|
+
requirements:
|
123
|
+
- - ">="
|
124
|
+
- !ruby/object:Gem::Version
|
125
|
+
version: '0'
|
126
|
+
requirements: []
|
127
|
+
rubygems_version: 3.1.4
|
128
|
+
signing_key:
|
129
|
+
specification_version: 4
|
130
|
+
summary: Callback-less event reactor for Ruby
|
131
|
+
test_files: []
|