io-event 1.4.4 → 1.5.0
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 +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/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 +4 -3
- 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);
|
@@ -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:
|
metadata.gz.sig
CHANGED
Binary file
|