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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 48833d95b36913a471c49a15933705c021582488d4f0a83ab26b2cc08a39b092
4
- data.tar.gz: c2ad33420135a7a72315e71362b4663503bf6bc8c6561cf4416bfc8e42f5398c
3
+ metadata.gz: aa82f1290f00aaf8cadbae8346653a4291f2e14d4ffec326972507ee69859720
4
+ data.tar.gz: aaed781d30c999d4cab7be1b3e4056e339d55256802b7c12c9d66fd46d64dcce
5
5
  SHA512:
6
- metadata.gz: ebc42847281fc77b058ab6b66c582ea7b58889eb28739c0d25f252b76c037d6341d53b06695595eae413fe67b1f9d10f564c110f01b379ccd10cc628a92e309c
7
- data.tar.gz: a6d0dc1b314cc5c05e5284bfd5d981436ae932bc399355c4cd9d1e9f2ea033c794d4f526c23de64cfbb9f7df5f39058e2511b79fcaebaeec0365c1a5aca919f6
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
- // Wait for events to occur
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
- int result = ioctlsocket(file_descriptor, FIONBIO, &nonblock);
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
- int result = ioctlsocket(file_descriptor, FIONBIO, &nonblock);
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)) {
@@ -34,7 +34,9 @@
34
34
  #endif
35
35
 
36
36
  #include <time.h>
37
- #include <sys/wait.h>
37
+ #ifdef HAVE_RB_PROCESS_STATUS_WAIT
38
+ #include <sys/wait.h>
39
+ #endif
38
40
 
39
41
  enum IO_Event {
40
42
  IO_EVENT_READABLE = 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-2022, by Samuel Williams.
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
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # Released under the MIT License.
4
- # Copyright, 2021-2023, by Samuel Williams.
4
+ # Copyright, 2021-2024, by Samuel Williams.
5
5
 
6
6
  require_relative 'selector/select'
7
7
  require_relative 'debug/selector'
@@ -1,10 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # Released under the MIT License.
4
- # Copyright, 2021-2023, by Samuel Williams.
4
+ # Copyright, 2021-2024, by Samuel Williams.
5
5
 
6
6
  class IO
7
7
  module Event
8
- VERSION = "1.4.3"
8
+ VERSION = "1.5.0"
9
9
  end
10
10
  end
data/license.md CHANGED
@@ -1,11 +1,12 @@
1
1
  # MIT License
2
2
 
3
- Copyright, 2021-2023, by Samuel Williams.
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.3
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-02-05 00:00:00.000000000 Z
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.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