Class: Event::Backend::EPoll

Inherits:
Object
  • Object
show all
Defined in:
ext/event/backend/epoll.c

Instance Method Summary collapse

Constructor Details

#initialize(loop) ⇒ Object



87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
# File 'ext/event/backend/epoll.c', line 87

VALUE Event_Backend_EPoll_initialize(VALUE self, VALUE loop) {
  struct Event_Backend_EPoll *data = NULL;
  TypedData_Get_Struct(self, struct Event_Backend_EPoll, &Event_Backend_EPoll_Type, data);
  
  data->loop = loop;
  int result = epoll_create1(EPOLL_CLOEXEC);
  
  if (result == -1) {
    rb_sys_fail("epoll_create");
  } else {
    data->descriptor = result;
    
    rb_update_max_fd(data->descriptor);
  }
  
  return self;
}

Instance Method Details

#closeObject



105
106
107
108
109
110
111
112
# File 'ext/event/backend/epoll.c', line 105

VALUE Event_Backend_EPoll_close(VALUE self) {
  struct Event_Backend_EPoll *data = NULL;
  TypedData_Get_Struct(self, struct Event_Backend_EPoll, &Event_Backend_EPoll_Type, data);
  
  close_internal(data);
  
  return Qnil;
}

#io_wait(fiber, io, events) ⇒ Object



169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
# File 'ext/event/backend/epoll.c', line 169

VALUE Event_Backend_EPoll_io_wait(VALUE self, VALUE fiber, VALUE io, VALUE events) {
  struct Event_Backend_EPoll *data = NULL;
  TypedData_Get_Struct(self, struct Event_Backend_EPoll, &Event_Backend_EPoll_Type, data);
  
  struct epoll_event event = {0};
  
  int descriptor = NUM2INT(rb_funcall(io, id_fileno, 0));
  int duplicate = -1;
  
  event.events = epoll_flags_from_events(NUM2INT(events));
  event.data.ptr = (void*)fiber;
  
  // fprintf(stderr, "<- fiber=%p descriptor=%d\n", (void*)fiber, descriptor);
  
  // A better approach is to batch all changes:
  int result = epoll_ctl(data->descriptor, EPOLL_CTL_ADD, descriptor, &event);
  
  if (result == -1 && errno == EEXIST) {
    // The file descriptor was already inserted into epoll.
    duplicate = descriptor = dup(descriptor);
    
    rb_update_max_fd(duplicate);
    
    if (descriptor == -1)
      rb_sys_fail("dup");
    
    result = epoll_ctl(data->descriptor, EPOLL_CTL_ADD, descriptor, &event);
  }
  
  if (result == -1) {
    rb_sys_fail("epoll_ctl");
  }
  
  struct io_wait_arguments io_wait_arguments = {
    .data = data,
    .descriptor = descriptor,
    .duplicate = duplicate
  };
  
  return rb_ensure(io_wait_transfer, (VALUE)&io_wait_arguments, io_wait_ensure, (VALUE)&io_wait_arguments);
}

#select(duration) ⇒ Object



266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
# File 'ext/event/backend/epoll.c', line 266

VALUE Event_Backend_EPoll_select(VALUE self, VALUE duration) {
  struct Event_Backend_EPoll *data = NULL;
  TypedData_Get_Struct(self, struct Event_Backend_EPoll, &Event_Backend_EPoll_Type, data);
  
  struct select_arguments arguments = {
    .data = data,
    .timeout = 0
  };
  
  select_internal_without_gvl(&arguments);
  
  if (arguments.count == 0) {
    arguments.timeout = make_timeout(duration);
    
    if (arguments.timeout != 0) {
      select_internal_with_gvl(&arguments);
    }
  }
  
  for (int i = 0; i < arguments.count; i += 1) {
    VALUE fiber = (VALUE)arguments.events[i].data.ptr;
    VALUE result = INT2NUM(arguments.events[i].events);
    
    // fprintf(stderr, "-> fiber=%p descriptor=%d\n", (void*)fiber, events[i].data.fd);
    
    rb_funcall(fiber, id_transfer, 1, result);
  }
  
  return INT2NUM(arguments.count);
}