io-event 1.4.3 → 1.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data/ext/io/event/selector/epoll.c +23 -1
- data/ext/io/event/selector/kqueue.c +22 -0
- data/ext/io/event/selector/selector.c +2 -2
- data/ext/io/event/selector/selector.h +3 -1
- data/ext/io/event/selector/uring.c +22 -0
- data/lib/io/event/debug/selector.rb +5 -1
- data/lib/io/event/selector/select.rb +13 -0
- data/lib/io/event/selector.rb +1 -1
- data/lib/io/event/version.rb +2 -2
- data/license.md +3 -2
- data.tar.gz.sig +0 -0
- metadata +5 -4
- metadata.gz.sig +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: aa82f1290f00aaf8cadbae8346653a4291f2e14d4ffec326972507ee69859720
|
4
|
+
data.tar.gz: aaed781d30c999d4cab7be1b3e4056e339d55256802b7c12c9d66fd46d64dcce
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fa1d7ee55e1af2a88d377366b8322a88fddd3c6d918edbcd636ce032e9bcfe98200fae4eb2ff192cbd8c469502a6390f6422ab210bfcd115adff666f6dcd9ca0
|
7
|
+
data.tar.gz: c0e15ecb8c57b9b7d19bf0a4ab7d56b34da728b53608b767d11ae468eadb086237058e75586bc146caac11883197f3cbf9ed491dc86c6e95dc2f3b6e77930a53
|
checksums.yaml.gz.sig
CHANGED
Binary file
|
@@ -59,6 +59,8 @@ struct IO_Event_Selector_EPoll
|
|
59
59
|
int descriptor;
|
60
60
|
int blocked;
|
61
61
|
|
62
|
+
struct timespec idle_duration;
|
63
|
+
|
62
64
|
struct IO_Event_Interrupt interrupt;
|
63
65
|
struct IO_Event_Array descriptors;
|
64
66
|
};
|
@@ -384,6 +386,15 @@ VALUE IO_Event_Selector_EPoll_loop(VALUE self) {
|
|
384
386
|
return selector->backend.loop;
|
385
387
|
}
|
386
388
|
|
389
|
+
VALUE IO_Event_Selector_EPoll_idle_duration(VALUE self) {
|
390
|
+
struct IO_Event_Selector_EPoll *selector = NULL;
|
391
|
+
TypedData_Get_Struct(self, struct IO_Event_Selector_EPoll, &IO_Event_Selector_EPoll_Type, selector);
|
392
|
+
|
393
|
+
double duration = selector->idle_duration.tv_sec + (selector->idle_duration.tv_nsec / 1000000000.0);
|
394
|
+
|
395
|
+
return DBL2NUM(duration);
|
396
|
+
}
|
397
|
+
|
387
398
|
VALUE IO_Event_Selector_EPoll_close(VALUE self) {
|
388
399
|
struct IO_Event_Selector_EPoll *selector = NULL;
|
389
400
|
TypedData_Get_Struct(self, struct IO_Event_Selector_EPoll, &IO_Event_Selector_EPoll_Type, selector);
|
@@ -966,6 +977,9 @@ VALUE IO_Event_Selector_EPoll_select(VALUE self, VALUE duration) {
|
|
966
977
|
struct IO_Event_Selector_EPoll *selector = NULL;
|
967
978
|
TypedData_Get_Struct(self, struct IO_Event_Selector_EPoll, &IO_Event_Selector_EPoll_Type, selector);
|
968
979
|
|
980
|
+
selector->idle_duration.tv_sec = 0;
|
981
|
+
selector->idle_duration.tv_nsec = 0;
|
982
|
+
|
969
983
|
int ready = IO_Event_Selector_queue_flush(&selector->backend);
|
970
984
|
|
971
985
|
struct select_arguments arguments = {
|
@@ -991,8 +1005,15 @@ VALUE IO_Event_Selector_EPoll_select(VALUE self, VALUE duration) {
|
|
991
1005
|
arguments.timeout = make_timeout(duration, &arguments.storage);
|
992
1006
|
|
993
1007
|
if (!timeout_nonblocking(arguments.timeout)) {
|
994
|
-
|
1008
|
+
struct timespec start_time;
|
1009
|
+
IO_Event_Selector_current_time(&start_time);
|
1010
|
+
|
1011
|
+
// Wait for events to occur:
|
995
1012
|
select_internal_without_gvl(&arguments);
|
1013
|
+
|
1014
|
+
struct timespec end_time;
|
1015
|
+
IO_Event_Selector_current_time(&end_time);
|
1016
|
+
IO_Event_Selector_elapsed_time(&start_time, &end_time, &selector->idle_duration);
|
996
1017
|
}
|
997
1018
|
}
|
998
1019
|
|
@@ -1025,6 +1046,7 @@ void Init_IO_Event_Selector_EPoll(VALUE IO_Event_Selector) {
|
|
1025
1046
|
rb_define_method(IO_Event_Selector_EPoll, "initialize", IO_Event_Selector_EPoll_initialize, 1);
|
1026
1047
|
|
1027
1048
|
rb_define_method(IO_Event_Selector_EPoll, "loop", IO_Event_Selector_EPoll_loop, 0);
|
1049
|
+
rb_define_method(IO_Event_Selector_EPoll, "idle_duration", IO_Event_Selector_EPoll_idle_duration, 0);
|
1028
1050
|
|
1029
1051
|
rb_define_method(IO_Event_Selector_EPoll, "transfer", IO_Event_Selector_EPoll_transfer, 0);
|
1030
1052
|
rb_define_method(IO_Event_Selector_EPoll, "resume", IO_Event_Selector_EPoll_resume, -1);
|
@@ -68,6 +68,8 @@ struct IO_Event_Selector_KQueue
|
|
68
68
|
int descriptor;
|
69
69
|
int blocked;
|
70
70
|
|
71
|
+
struct timespec idle_duration;
|
72
|
+
|
71
73
|
#ifdef IO_EVENT_SELECTOR_KQUEUE_USE_INTERRUPT
|
72
74
|
struct IO_Event_Interrupt interrupt;
|
73
75
|
#endif
|
@@ -367,6 +369,15 @@ VALUE IO_Event_Selector_KQueue_loop(VALUE self) {
|
|
367
369
|
return selector->backend.loop;
|
368
370
|
}
|
369
371
|
|
372
|
+
VALUE IO_Event_Selector_KQueue_idle_duration(VALUE self) {
|
373
|
+
struct IO_Event_Selector_KQueue *selector = NULL;
|
374
|
+
TypedData_Get_Struct(self, struct IO_Event_Selector_EPoll, &IO_Event_Selector_KQueue_Type, selector);
|
375
|
+
|
376
|
+
double duration = selector->idle_duration.tv_sec + (selector->idle_duration.tv_nsec / 1000000000.0);
|
377
|
+
|
378
|
+
return DBL2NUM(duration);
|
379
|
+
}
|
380
|
+
|
370
381
|
VALUE IO_Event_Selector_KQueue_close(VALUE self) {
|
371
382
|
struct IO_Event_Selector_KQueue *selector = NULL;
|
372
383
|
TypedData_Get_Struct(self, struct IO_Event_Selector_KQueue, &IO_Event_Selector_KQueue_Type, selector);
|
@@ -949,6 +960,9 @@ VALUE IO_Event_Selector_KQueue_select(VALUE self, VALUE duration) {
|
|
949
960
|
struct IO_Event_Selector_KQueue *selector = NULL;
|
950
961
|
TypedData_Get_Struct(self, struct IO_Event_Selector_KQueue, &IO_Event_Selector_KQueue_Type, selector);
|
951
962
|
|
963
|
+
selector->idle_duration.tv_sec = 0;
|
964
|
+
selector->idle_duration.tv_nsec = 0;
|
965
|
+
|
952
966
|
int ready = IO_Event_Selector_queue_flush(&selector->backend);
|
953
967
|
|
954
968
|
struct select_arguments arguments = {
|
@@ -985,8 +999,15 @@ VALUE IO_Event_Selector_KQueue_select(VALUE self, VALUE duration) {
|
|
985
999
|
if (!timeout_nonblocking(arguments.timeout)) {
|
986
1000
|
arguments.count = KQUEUE_MAX_EVENTS;
|
987
1001
|
|
1002
|
+
struct timespec start_time;
|
1003
|
+
IO_Event_Selector_current_time(&start_time);
|
1004
|
+
|
988
1005
|
if (DEBUG) fprintf(stderr, "IO_Event_Selector_KQueue_select timeout=" PRINTF_TIMESPEC "\n", PRINTF_TIMESPEC_ARGS(arguments.storage));
|
989
1006
|
select_internal_without_gvl(&arguments);
|
1007
|
+
|
1008
|
+
struct timespec end_time;
|
1009
|
+
IO_Event_Selector_current_time(&end_time);
|
1010
|
+
IO_Event_Selector_elapsed_time(&start_time, &end_time, &selector->idle_duration);
|
990
1011
|
}
|
991
1012
|
}
|
992
1013
|
|
@@ -1041,6 +1062,7 @@ void Init_IO_Event_Selector_KQueue(VALUE IO_Event_Selector) {
|
|
1041
1062
|
rb_define_method(IO_Event_Selector_KQueue, "initialize", IO_Event_Selector_KQueue_initialize, 1);
|
1042
1063
|
|
1043
1064
|
rb_define_method(IO_Event_Selector_KQueue, "loop", IO_Event_Selector_KQueue_loop, 0);
|
1065
|
+
rb_define_method(IO_Event_Selector_KQueue, "idle_duration", IO_Event_Selector_KQueue_idle_duration, 0);
|
1044
1066
|
|
1045
1067
|
rb_define_method(IO_Event_Selector_KQueue, "transfer", IO_Event_Selector_KQueue_transfer, 0);
|
1046
1068
|
rb_define_method(IO_Event_Selector_KQueue, "resume", IO_Event_Selector_KQueue_resume, -1);
|
@@ -82,7 +82,7 @@ int IO_Event_Selector_nonblock_set(int file_descriptor)
|
|
82
82
|
{
|
83
83
|
#ifdef _WIN32
|
84
84
|
u_long nonblock = 1;
|
85
|
-
|
85
|
+
ioctlsocket(file_descriptor, FIONBIO, &nonblock);
|
86
86
|
// Windows does not provide any way to know this, so we always restore it back to unset:
|
87
87
|
return 0;
|
88
88
|
#else
|
@@ -103,7 +103,7 @@ void IO_Event_Selector_nonblock_restore(int file_descriptor, int flags)
|
|
103
103
|
#ifdef _WIN32
|
104
104
|
// Yolo...
|
105
105
|
u_long nonblock = flags;
|
106
|
-
|
106
|
+
ioctlsocket(file_descriptor, FIONBIO, &nonblock);
|
107
107
|
#else
|
108
108
|
// The flags didn't have O_NONBLOCK set, so it would have been set, so we need to restore it:
|
109
109
|
if (!(flags & O_NONBLOCK)) {
|
@@ -50,6 +50,8 @@ struct IO_Event_Selector_URing
|
|
50
50
|
size_t pending;
|
51
51
|
int blocked;
|
52
52
|
|
53
|
+
struct timespec idle_duration;
|
54
|
+
|
53
55
|
struct IO_Event_Array completions;
|
54
56
|
struct IO_Event_List free_list;
|
55
57
|
};
|
@@ -266,6 +268,15 @@ VALUE IO_Event_Selector_URing_loop(VALUE self) {
|
|
266
268
|
return selector->backend.loop;
|
267
269
|
}
|
268
270
|
|
271
|
+
VALUE IO_Event_Selector_URing_idle_duration(VALUE self) {
|
272
|
+
struct IO_Event_Selector_URing *selector = NULL;
|
273
|
+
TypedData_Get_Struct(self, struct IO_Event_Selector_URing, &IO_Event_Selector_URing_Type, selector);
|
274
|
+
|
275
|
+
double duration = selector->idle_duration.tv_sec + (selector->idle_duration.tv_nsec / 1000000000.0);
|
276
|
+
|
277
|
+
return DBL2NUM(duration);
|
278
|
+
}
|
279
|
+
|
269
280
|
VALUE IO_Event_Selector_URing_close(VALUE self) {
|
270
281
|
struct IO_Event_Selector_URing *selector = NULL;
|
271
282
|
TypedData_Get_Struct(self, struct IO_Event_Selector_URing, &IO_Event_Selector_URing_Type, selector);
|
@@ -1009,6 +1020,9 @@ VALUE IO_Event_Selector_URing_select(VALUE self, VALUE duration) {
|
|
1009
1020
|
struct IO_Event_Selector_URing *selector = NULL;
|
1010
1021
|
TypedData_Get_Struct(self, struct IO_Event_Selector_URing, &IO_Event_Selector_URing_Type, selector);
|
1011
1022
|
|
1023
|
+
selector->idle_duration.tv_sec = 0;
|
1024
|
+
selector->idle_duration.tv_nsec = 0;
|
1025
|
+
|
1012
1026
|
// Flush any pending events:
|
1013
1027
|
io_uring_submit_flush(selector);
|
1014
1028
|
|
@@ -1031,9 +1045,16 @@ VALUE IO_Event_Selector_URing_select(VALUE self, VALUE duration) {
|
|
1031
1045
|
arguments.timeout = make_timeout(duration, &arguments.storage);
|
1032
1046
|
|
1033
1047
|
if (!selector->backend.ready && !timeout_nonblocking(arguments.timeout)) {
|
1048
|
+
struct timespec start_time;
|
1049
|
+
IO_Event_Selector_current_time(&start_time);
|
1050
|
+
|
1034
1051
|
// This is a blocking operation, we wait for events:
|
1035
1052
|
result = select_internal_without_gvl(&arguments);
|
1036
1053
|
|
1054
|
+
struct timespec end_time;
|
1055
|
+
IO_Event_Selector_current_time(&end_time);
|
1056
|
+
IO_Event_Selector_elapsed_time(&start_time, &end_time, &selector->idle_duration);
|
1057
|
+
|
1037
1058
|
// After waiting/flushing the SQ, check if there are any completions:
|
1038
1059
|
if (result > 0) {
|
1039
1060
|
result = select_process_completions(selector);
|
@@ -1083,6 +1104,7 @@ void Init_IO_Event_Selector_URing(VALUE IO_Event_Selector) {
|
|
1083
1104
|
rb_define_method(IO_Event_Selector_URing, "initialize", IO_Event_Selector_URing_initialize, 1);
|
1084
1105
|
|
1085
1106
|
rb_define_method(IO_Event_Selector_URing, "loop", IO_Event_Selector_URing_loop, 0);
|
1107
|
+
rb_define_method(IO_Event_Selector_URing, "idle_duration", IO_Event_Selector_URing_idle_duration, 0);
|
1086
1108
|
|
1087
1109
|
rb_define_method(IO_Event_Selector_URing, "transfer", IO_Event_Selector_URing_transfer, 0);
|
1088
1110
|
rb_define_method(IO_Event_Selector_URing, "resume", IO_Event_Selector_URing_resume, -1);
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
# Released under the MIT License.
|
4
|
-
# Copyright, 2021-
|
4
|
+
# Copyright, 2021-2024, by Samuel Williams.
|
5
5
|
|
6
6
|
require_relative '../support'
|
7
7
|
|
@@ -33,6 +33,10 @@ module IO::Event
|
|
33
33
|
@log = log
|
34
34
|
end
|
35
35
|
|
36
|
+
def idle_duration
|
37
|
+
@selector.idle_duration
|
38
|
+
end
|
39
|
+
|
36
40
|
def now
|
37
41
|
Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
38
42
|
end
|
@@ -19,10 +19,15 @@ module IO::Event
|
|
19
19
|
|
20
20
|
@ready = Queue.new
|
21
21
|
@interrupt = Interrupt.attach(self)
|
22
|
+
|
23
|
+
@idle_duration = 0.0
|
22
24
|
end
|
23
25
|
|
24
26
|
attr :loop
|
25
27
|
|
28
|
+
# This is the amount of time the event loop was idle during the last select call.
|
29
|
+
attr :idle_duration
|
30
|
+
|
26
31
|
# If the event loop is currently sleeping, wake it up.
|
27
32
|
def wakeup
|
28
33
|
if @blocked
|
@@ -415,6 +420,10 @@ module IO::Event
|
|
415
420
|
duration = 0 unless @ready.empty?
|
416
421
|
error = nil
|
417
422
|
|
423
|
+
if duration && duration > 0.0
|
424
|
+
start_time = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
425
|
+
end
|
426
|
+
|
418
427
|
# We need to handle interrupts on blocking IO. Every other implementation uses EINTR, but that doesn't work with `::IO.select` as it will retry the call on EINTR.
|
419
428
|
Thread.handle_interrupt(::Exception => :on_blocking) do
|
420
429
|
@blocked = true
|
@@ -423,6 +432,10 @@ module IO::Event
|
|
423
432
|
# Requeue below...
|
424
433
|
ensure
|
425
434
|
@blocked = false
|
435
|
+
if start_time
|
436
|
+
end_time = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
437
|
+
@idle_duration = end_time - start_time
|
438
|
+
end
|
426
439
|
end
|
427
440
|
|
428
441
|
if error
|
data/lib/io/event/selector.rb
CHANGED
data/lib/io/event/version.rb
CHANGED
data/license.md
CHANGED
@@ -1,11 +1,12 @@
|
|
1
1
|
# MIT License
|
2
2
|
|
3
|
-
Copyright, 2021-
|
3
|
+
Copyright, 2021-2024, by Samuel Williams.
|
4
4
|
Copyright, 2021, by Delton Ding.
|
5
|
-
Copyright, 2021, by Benoit Daloze.
|
5
|
+
Copyright, 2021-2024, by Benoit Daloze.
|
6
6
|
Copyright, 2022, by Alex Matchneer.
|
7
7
|
Copyright, 2022, by Bruno Sutic.
|
8
8
|
Copyright, 2023, by Math Ieu.
|
9
|
+
Copyright, 2024, by Pavel Rosický.
|
9
10
|
|
10
11
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
11
12
|
of this software and associated documentation files (the "Software"), to deal
|
data.tar.gz.sig
CHANGED
Binary file
|
metadata
CHANGED
@@ -1,15 +1,16 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: io-event
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Samuel Williams
|
8
8
|
- Math Ieu
|
9
|
+
- Benoit Daloze
|
9
10
|
- Bruno Sutic
|
10
11
|
- Alex Matchneer
|
11
|
-
- Benoit Daloze
|
12
12
|
- Delton Ding
|
13
|
+
- Pavel Rosický
|
13
14
|
autorequire:
|
14
15
|
bindir: bin
|
15
16
|
cert_chain:
|
@@ -42,7 +43,7 @@ cert_chain:
|
|
42
43
|
Q2K9NVun/S785AP05vKkXZEFYxqG6EW012U4oLcFl5MySFajYXRYbuUpH6AY+HP8
|
43
44
|
voD0MPg1DssDLKwXyt1eKD/+Fq0bFWhwVM/1XiAXL7lyYUyOq24KHgQ2Csg=
|
44
45
|
-----END CERTIFICATE-----
|
45
|
-
date: 2024-
|
46
|
+
date: 2024-03-04 00:00:00.000000000 Z
|
46
47
|
dependencies: []
|
47
48
|
description:
|
48
49
|
email:
|
@@ -97,7 +98,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
97
98
|
- !ruby/object:Gem::Version
|
98
99
|
version: '0'
|
99
100
|
requirements: []
|
100
|
-
rubygems_version: 3.5.
|
101
|
+
rubygems_version: 3.5.3
|
101
102
|
signing_key:
|
102
103
|
specification_version: 4
|
103
104
|
summary: An event loop.
|
metadata.gz.sig
CHANGED
Binary file
|