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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 63a99f0ea7e4724f1e54fba08e89c0724c62e5ba145458ce7633dd50ba24a6cc
4
- data.tar.gz: eaa732bdf869288cc22a5b70d158dabe022c39cde249ede5859233eb08262c0e
3
+ metadata.gz: aa82f1290f00aaf8cadbae8346653a4291f2e14d4ffec326972507ee69859720
4
+ data.tar.gz: aaed781d30c999d4cab7be1b3e4056e339d55256802b7c12c9d66fd46d64dcce
5
5
  SHA512:
6
- metadata.gz: 55a1d36a58b3182cc38a5043cfb53d2207a1810d848a3ab2d95830fd17b7925996d6a0de397fd15be56fcf6447cea7d40534b2241b902d0150e3d0553f98936f
7
- data.tar.gz: 87d5ab721c535429ee5271c810715eb5685ec9acd57cc22a6ad98ca2fe91451bfee5bbcd06f3d6d50a6db6914013965d24cefd79122cebdb907e6de5951643f8
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);
@@ -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.4"
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.4
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-16 00:00:00.000000000 Z
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