ever 0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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: []
|