wait_event function: first draft okay
This commit is contained in:
parent
bc0fe07990
commit
1f5ac951cb
@ -5,6 +5,8 @@ const net = std.net;
|
|||||||
const os = std.os;
|
const os = std.os;
|
||||||
const fmt = std.fmt;
|
const fmt = std.fmt;
|
||||||
|
|
||||||
|
const Timer = std.time.Timer;
|
||||||
|
|
||||||
const print = std.debug.print;
|
const print = std.debug.print;
|
||||||
|
|
||||||
const CBEvent = @import("./callback.zig").CBEvent;
|
const CBEvent = @import("./callback.zig").CBEvent;
|
||||||
@ -138,7 +140,7 @@ pub const Context = struct {
|
|||||||
self.tx.append(m);
|
self.tx.append(m);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn read (self: *Self, index: u32) !Message {
|
pub fn read (self: *Self, index: usize) !Message {
|
||||||
if (index >= self.pollfd.items.len) {
|
if (index >= self.pollfd.items.len) {
|
||||||
return error.IndexOutOfBounds;
|
return error.IndexOutOfBounds;
|
||||||
}
|
}
|
||||||
@ -158,7 +160,7 @@ pub const Context = struct {
|
|||||||
|
|
||||||
// Wait an event.
|
// Wait an event.
|
||||||
pub fn wait_event(self: *Self) !Event {
|
pub fn wait_event(self: *Self) !Event {
|
||||||
var current_event: Event = undefined;
|
var current_event: Event = Event.init(Event.Type.NOT_SET, 0, 0, null);
|
||||||
var wait_duration: i32 = -1; // -1 == unlimited
|
var wait_duration: i32 = -1; // -1 == unlimited
|
||||||
|
|
||||||
if (self.timer) |t| { wait_duration = t; }
|
if (self.timer) |t| { wait_duration = t; }
|
||||||
@ -170,50 +172,106 @@ pub const Context = struct {
|
|||||||
// setting POLLIN & POLLOUT flags.
|
// setting POLLIN & POLLOUT flags.
|
||||||
for (self.pollfd.items) |*fd| {
|
for (self.pollfd.items) |*fd| {
|
||||||
// print("listening to fd {}\n", .{fd.fd});
|
// print("listening to fd {}\n", .{fd.fd});
|
||||||
fd.events = std.os.linux.POLL.IN; // just to make sure
|
fd.events |= std.os.linux.POLL.IN; // just to make sure
|
||||||
}
|
}
|
||||||
|
|
||||||
for (self.tx.items) |m| {
|
for (self.tx.items) |m| {
|
||||||
print("wait for writing a message to fd {}\n", .{m.fd});
|
print("wait for writing a message to fd {}\n", .{m.fd});
|
||||||
for (self.pollfd.items) |*fd| {
|
for (self.pollfd.items) |*fd| {
|
||||||
if (fd.fd == m.fd) {
|
if (fd.fd == m.fd) {
|
||||||
fd.events = std.os.linux.POLL.OUT; // just to make sure
|
fd.events |= std.os.linux.POLL.OUT; // just to make sure
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: before initiate a timer
|
// TODO: before initiate a timer
|
||||||
|
var timer = try Timer.start();
|
||||||
|
|
||||||
// Polling.
|
// Polling.
|
||||||
var count: usize = undefined;
|
var count: usize = undefined;
|
||||||
|
|
||||||
// print("Let's wait for an event (either stdin or unix socket)\n", .{});
|
// print("Let's wait for an event (either stdin or unix socket)\n", .{});
|
||||||
print("fds: {any}\n", .{self.pollfd.items});
|
print("fds: {any}\n", .{self.pollfd.items});
|
||||||
count = try os.poll(self.pollfd.items, wait_duration);
|
count = try os.poll(self.pollfd.items, wait_duration);
|
||||||
print("fds NOW: {any}\n", .{self.pollfd.items});
|
print("fds NOW: {any}\n", .{self.pollfd.items});
|
||||||
|
|
||||||
// TODO: timer = end - start; if 0 => return timer event
|
if (count < 0) {
|
||||||
|
print("there is a problem: poll < 0\n", .{});
|
||||||
|
current_event = Event.init(Event.Type.ERROR, 0, 0, null);
|
||||||
|
return current_event;
|
||||||
|
}
|
||||||
|
|
||||||
|
var duration = timer.read() / 1000000; // ns -> ms
|
||||||
if (count == 0) {
|
if (count == 0) {
|
||||||
current_event = Event.init(Event.Type.TIMER, 0, 0, null);
|
print("wait: configured {} measured {}\n", .{wait_duration, duration});
|
||||||
|
if (duration >= wait_duration) {
|
||||||
|
current_event = Event.init(Event.Type.TIMER, 0, 0, null);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// In case nothing happened, and poll wasn't triggered by time out.
|
||||||
|
current_event = Event.init(Event.Type.ERROR, 0, 0, null);
|
||||||
|
}
|
||||||
return current_event;
|
return current_event;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: handle messages
|
// TODO: handle messages
|
||||||
// => loop over ctx.size
|
// => loop over self.pollfd.items
|
||||||
// => if pollfd[i].revents is set to POLLIN
|
for (self.pollfd.items) |*fd, i| {
|
||||||
// => if fd is SERVER => new connection
|
// .revents is POLLIN
|
||||||
// => if fd is SWITCHED => msg to exchange (or drop the switch)
|
if(fd.revents & std.os.linux.POLL.IN > 0) {
|
||||||
// => if fd is EXTERNAL => let user handle IO operations
|
// SERVER = new connection
|
||||||
// => otherwise => new message or disconnection
|
if (self.connections.items[i].t == .SERVER) {
|
||||||
// => if fd revent is POLLOUT
|
// TODO: ipc_accept_add
|
||||||
// => if SWITCHED => write message for its switch buddy
|
current_event = Event.init(Event.Type.CONNECTION, i, fd.fd, null);
|
||||||
// => otherwise => write message for the msg.fd
|
}
|
||||||
// if fd revent is POLLHUP
|
// SWITCHED = send message to the right dest (or drop the switch)
|
||||||
// => handle disconnection:
|
else if (self.connections.items[i].t == .SWITCHED) {
|
||||||
// close + remove fd from pollfd + return event
|
// TODO: send message to SWITCH dest
|
||||||
// if fd revent is POLLERR or POLLNVAL
|
// TODO: handle_switched_message
|
||||||
// => return error event
|
current_event = Event.init(Event.Type.SWITCH, i, fd.fd, null);
|
||||||
|
}
|
||||||
|
// EXTERNAL = user handles IO
|
||||||
|
else if (self.connections.items[i].t == .EXTERNAL) {
|
||||||
|
current_event = Event.init(Event.Type.EXTERNAL, i, fd.fd, null);
|
||||||
|
}
|
||||||
|
// otherwise = new message or disconnection
|
||||||
|
else {
|
||||||
|
// TODO: handle incoming message
|
||||||
|
// TODO: handle_new_message
|
||||||
|
current_event = Event.init(Event.Type.MESSAGE, i, fd.fd, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// .revent is POLLOUT
|
||||||
|
if(fd.revents & std.os.linux.POLL.OUT > 0) {
|
||||||
|
fd.events &= ~ @as(i16, std.os.linux.POLL.OUT);
|
||||||
|
|
||||||
|
// SWITCHED = write message for its switch buddy (callbacks)
|
||||||
|
if (self.connections.items[i].t == .SWITCHED) {
|
||||||
|
// TODO: handle_writing_switched_message
|
||||||
|
current_event = Event.init(Event.Type.SWITCH, i, fd.fd, null);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// otherwise = write message for the msg.fd
|
||||||
|
// TODO: handle_writing_message
|
||||||
|
current_event = Event.init(Event.Type.TX, i, fd.fd, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// .revent is POLLHUP
|
||||||
|
if(fd.revents & std.os.linux.POLL.HUP > 0) {
|
||||||
|
// handle disconnection
|
||||||
|
current_event = Event.init(Event.Type.DISCONNECTION, i, fd.fd, null);
|
||||||
|
try self.close(i);
|
||||||
|
}
|
||||||
|
// if fd revent is POLLERR or POLLNVAL
|
||||||
|
if ((fd.revents & std.os.linux.POLL.HUP > 0) or
|
||||||
|
(fd.revents & std.os.linux.POLL.HUP > 0)) {
|
||||||
|
current_event = Event.init(Event.Type.ERROR, i, fd.fd, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: check for LOOKUP events.
|
||||||
|
// LOOKUP = Client asking for a service through ipcd.
|
||||||
|
|
||||||
return current_event;
|
return current_event;
|
||||||
}
|
}
|
||||||
|
@ -36,7 +36,7 @@ pub const Event = struct {
|
|||||||
pub const Type = enum {
|
pub const Type = enum {
|
||||||
NOT_SET, // Default. TODO: should we keep this?
|
NOT_SET, // Default. TODO: should we keep this?
|
||||||
ERROR, // A problem occured.
|
ERROR, // A problem occured.
|
||||||
EXTRA_SOCKET, // Message received from a non IPC socket.
|
EXTERNAL, // Message received from a non IPC socket.
|
||||||
SWITCH, // Message to send to a corresponding fd.
|
SWITCH, // Message to send to a corresponding fd.
|
||||||
CONNECTION, // New user.
|
CONNECTION, // New user.
|
||||||
DISCONNECTION, // User disconnected.
|
DISCONNECTION, // User disconnected.
|
||||||
@ -47,17 +47,17 @@ pub const Event = struct {
|
|||||||
};
|
};
|
||||||
|
|
||||||
t: Event.Type,
|
t: Event.Type,
|
||||||
index: u32,
|
index: usize,
|
||||||
origin: usize, // socket fd
|
origin: i32, // socket fd
|
||||||
m: ?*Message, // message pointer
|
m: ?*Message, // message pointer
|
||||||
|
|
||||||
const Self = @This();
|
const Self = @This();
|
||||||
|
|
||||||
pub fn init(t: Event.Type, index: u32, origin: usize, m: ?*Message) Self {
|
pub fn init(t: Event.Type, index: usize, origin: i32, m: ?*Message) Self {
|
||||||
return Self { .t = t, .index = index, .origin = origin, .m = m, };
|
return Self { .t = t, .index = index, .origin = origin, .m = m, };
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set(self: *Self, t: Event.Type, index: u32, origin: usize, m: ?*Message) void {
|
pub fn set(self: *Self, t: Event.Type, index: usize, origin: i32, m: ?*Message) void {
|
||||||
self.t = t;
|
self.t = t;
|
||||||
self.index = index;
|
self.index = index;
|
||||||
self.origin = origin;
|
self.origin = origin;
|
||||||
@ -66,8 +66,8 @@ pub const Event = struct {
|
|||||||
|
|
||||||
pub fn clean(self: *Self) void {
|
pub fn clean(self: *Self) void {
|
||||||
self.t = Event.Type.NOT_SET;
|
self.t = Event.Type.NOT_SET;
|
||||||
self.index = @as(u8,0);
|
self.index = @as(usize,0);
|
||||||
self.origin = @as(usize,0);
|
self.origin = @as(i32,0);
|
||||||
if (self.m) |message| {
|
if (self.m) |message| {
|
||||||
message.deinit();
|
message.deinit();
|
||||||
}
|
}
|
||||||
|
@ -54,7 +54,7 @@ fn create_service() !void {
|
|||||||
|
|
||||||
var count_down: i16 = 5;
|
var count_down: i16 = 5;
|
||||||
var some_event: Event = undefined;
|
var some_event: Event = undefined;
|
||||||
ctx.timer = 1000; // 1 second
|
ctx.timer = 2000; // 1 second
|
||||||
while(true) {
|
while(true) {
|
||||||
some_event = try ctx.wait_event();
|
some_event = try ctx.wait_event();
|
||||||
switch (some_event.t) {
|
switch (some_event.t) {
|
||||||
@ -70,7 +70,7 @@ fn create_service() !void {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
.EXTRA_SOCKET => {
|
.EXTERNAL => {
|
||||||
print("Message received from a non IPC socket.", .{});
|
print("Message received from a non IPC socket.", .{});
|
||||||
break;
|
break;
|
||||||
},
|
},
|
||||||
|
@ -4,10 +4,12 @@ const testing = std.testing;
|
|||||||
const net = std.net;
|
const net = std.net;
|
||||||
const fmt = std.fmt;
|
const fmt = std.fmt;
|
||||||
|
|
||||||
|
const Timer = std.time.Timer;
|
||||||
|
|
||||||
const print = std.debug.print;
|
const print = std.debug.print;
|
||||||
const P = std.ArrayList(std.os.pollfd);
|
const P = std.ArrayList(std.os.pollfd);
|
||||||
|
|
||||||
fn create_service() !void {
|
fn arraylist_test() !void {
|
||||||
const config = .{.safety = true};
|
const config = .{.safety = true};
|
||||||
var gpa = std.heap.GeneralPurposeAllocator(config){};
|
var gpa = std.heap.GeneralPurposeAllocator(config){};
|
||||||
defer _ = gpa.deinit();
|
defer _ = gpa.deinit();
|
||||||
@ -21,7 +23,22 @@ fn create_service() !void {
|
|||||||
for(p.items) |i| { print("fd: {}\n", .{i.fd}); }
|
for(p.items) |i| { print("fd: {}\n", .{i.fd}); }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn timer_test() !void {
|
||||||
|
var timer = try Timer.start();
|
||||||
|
|
||||||
|
var count: u64 = 0;
|
||||||
|
while (count < 100000) {
|
||||||
|
count += 1;
|
||||||
|
print("\rcount = {}", .{count});
|
||||||
|
}
|
||||||
|
print("\n", .{});
|
||||||
|
|
||||||
|
var duration = timer.read();
|
||||||
|
print("took {} us\n", .{duration / 1000});
|
||||||
|
}
|
||||||
|
|
||||||
pub fn main() !u8 {
|
pub fn main() !u8 {
|
||||||
try create_service();
|
// try arraylist_test();
|
||||||
|
try timer_test();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user