Class: Event::Backend::KQueue

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

Instance Method Summary collapse

Constructor Details

#initialize(loop) ⇒ Object



81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
# File 'ext/event/backend/kqueue.c', line 81

VALUE Event_Backend_KQueue_initialize(VALUE self, VALUE loop) {
	struct Event_Backend_KQueue *data = NULL;
	TypedData_Get_Struct(self, struct Event_Backend_KQueue, &Event_Backend_KQueue_Type, data);
	
	data->loop = loop;
	int result = kqueue();
	
	if (result == -1) {
		rb_sys_fail("kqueue");
	} else {
		ioctl(result, FIOCLEX);
		data->descriptor = result;
		
		rb_update_max_fd(data->descriptor);
	}
	
	return self;
}

Instance Method Details

#io_wait(fiber, io, events) ⇒ Object



122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
# File 'ext/event/backend/kqueue.c', line 122

VALUE Event_Backend_KQueue_io_wait(VALUE self, VALUE fiber, VALUE io, VALUE events) {
	struct Event_Backend_KQueue *data = NULL;
	TypedData_Get_Struct(self, struct Event_Backend_KQueue, &Event_Backend_KQueue_Type, data);
	
	struct kevent event = {0};
	
	int descriptor = NUM2INT(rb_funcall(io, id_fileno, 0));
	
	event.ident = descriptor;
	event.filter = kqueue_filters_from_events(events);
	event.flags = EV_ADD | EV_ENABLE | EV_ONESHOT;
	event.udata = (void*)fiber;
	
	// A better approach is to batch all changes:
	int result = kevent(data->descriptor, &event, 1, NULL, 0, NULL);
	
	if (result == -1) {
		rb_sys_fail("kevent");
	}
	
	VALUE result = rb_funcall(data->loop, id_transfer, 0);
	return INT2NUM(events_from_kqueue_filter(NUM2INT(result)));
}

#select(duration) ⇒ Object



172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
# File 'ext/event/backend/kqueue.c', line 172

VALUE Event_Backend_KQueue_select(VALUE self, VALUE duration) {
	struct Event_Backend_KQueue *data = NULL;
	TypedData_Get_Struct(self, struct Event_Backend_KQueue, &Event_Backend_KQueue_Type, data);
	
	struct kevent events[KQUEUE_MAX_EVENTS];
	struct timespec storage;
	
	int count = kevent(data->descriptor, NULL, 0, events, KQUEUE_MAX_EVENTS, make_timeout(duration, &storage));
	
	if (count == -1) {
		rb_sys_fail("kevent");
	}
	
	for (int i = 0; i < count; i += 1) {
		VALUE fiber = (VALUE)events[i].udata;
		VALUE result = INT2NUM(events[i].filter);
		rb_funcall(fiber, id_transfer, 1, result);
	}
	
	return INT2NUM(count);
}