IPC::loop.

master
Philippe Pittoli 2023-01-24 15:22:51 +01:00
parent 12123b0cb4
commit ae99353c19
1 changed files with 80 additions and 50 deletions

View File

@ -32,36 +32,26 @@ lib LibIPC
fun timer = ipc_context_timer (Void*, LibC::Int)
# Closing connections.
fun ipc_close(Void*, LibC::UInt64T) : LibC::Int
fun ipc_close_all(Void*) : LibC::Int
fun close = ipc_close(Void*, LibC::UInt64T) : LibC::Int
fun close_fd = ipc_close_fd(Void*, LibC::Int) : LibC::Int
fun close_all = ipc_close_all(Void*) : LibC::Int
end
def test_without_wait()
ctx = Pointer(Void).null
LibIPC.init (pointerof(ctx))
fd : Int32 = 0
LibIPC.connect_service(ctx, pointerof(fd), "pong", 4)
pp! fd
LibIPC.write(ctx, fd, "Hello", 5)
buflen : LibC::UInt64T = 10
buffer = uninitialized UInt8[10]
LibIPC.read(ctx, fd, buffer.to_unsafe, pointerof(buflen))
received = String.new(buffer.to_unsafe, buflen)
pp! received
LibIPC.deinit (pointerof(ctx))
# TODO:
module IPCMessage
class TypedMessage
@fd : Int32
@type : UInt8
@payload : Bytes
def initialize(@fd, @type, string : String)
@payload = Bytes.new string
end
def initialize(@fd, @type, @payload)
end
end
end
class IPC
#class Message
# @fd : Int32
# @payload : Bytes
# def initialize(@fd, string : String)
# @payload = Bytes.new string
# end
#end
# Reception buffer with a big capacity.
# Allocated once.
@reception_buffer = Array(UInt8).new 2_000_000
@ -88,6 +78,7 @@ class IPC
at_exit { deinit }
end
# Closes all connections then remove the structure from memory.
def deinit
LibIPC.deinit(pointerof(@context))
end
@ -95,18 +86,50 @@ class IPC
def connect(name : String) : Int
fd = uninitialized Int32
if LibIPC.connect_service(@context, pointerof(fd), name, name.size) != 0
raise "oh noes"
raise "oh noes, 'connect_service' iz brkn"
end
fd
end
def write(fd : Int, message : IPCMessage::TypedMessage)
self.write(fd, message.payload.to_unsafe, message.payload.size)
end
def write(fd : Int, string : String)
self.write(fd, string.to_unsafe, string.size.to_u64)
end
def write(fd : Int, buffer : UInt8*, buflen : UInt64)
if LibIPC.write(@context, fd, buffer, buflen) != 0
raise "oh noes"
raise "oh noes, 'write' iz brkn"
end
end
def schedule(fd : Int, string : String)
self.schedule(fd, string.to_unsafe, string.size.to_u64)
end
def schedule(fd : Int, buffer : UInt8*, buflen : UInt64)
if LibIPC.schedule(@context, fd, buffer, buflen) != 0
raise "oh noes, 'schedule' iz brkn"
end
end
def close(index : LibC::UInt64T)
if LibIPC.close(@context, index) != 0
raise "Oh noes, 'close index' iz brkn"
end
end
def close(fd : LibC::Int)
if LibIPC.close_fd(@context, fd) != 0
raise "Oh noes, 'close fd' iz brkn"
end
end
def close_all()
if LibIPC.close_all(@context) != 0
raise "Oh noes, 'close all' iz brkn"
end
end
@ -128,29 +151,14 @@ class IPC
Event.new(eventtype, index, fd, @reception_buffer, buflen)
end
def loop(&block : Proc(IPC::Event, Nil))
::loop do
yield wait
end
end
end
def test_with_wait()
ctx = Pointer(Void).null
LibIPC.init (pointerof(ctx))
fd : Int32 = 0
LibIPC.connect_service(ctx, pointerof(fd), "pong", 4)
LibIPC.write(ctx, fd, "Hello", 5)
buflen : LibC::UInt64T = 10
buffer = uninitialized UInt8[10]
eventtype : UInt8 = 0
index : LibC::UInt64T = 0
LibIPC.timer(ctx, 2000) # Wait at most 2 seconds.
LibIPC.wait(ctx, pointerof(eventtype), pointerof(index), pointerof(fd), buffer.to_unsafe, pointerof(buflen))
#pp! LibIPC::EventType.new(eventtype), fd, index, buflen
received = String.new(buffer.to_unsafe, buflen)
pp! received
LibIPC.deinit (pointerof(ctx))
end
def test_high_level
ipc = IPC.new
@ -166,11 +174,33 @@ def test_high_level
end
end
def test_loop
ipc = IPC.new
fd = ipc.connect("pong")
ipc.schedule(fd, "hello this is some value")
ipc.loop do |event|
case event.type
when LibIPC::EventType::MessageRx
m = event.message
if m.nil?
puts "No message"
else
pp! String.new(m.to_unsafe, m.size)
end
exit 0
when LibIPC::EventType::MessageTx
puts "A message has been sent"
else
puts "Unexpected: #{event.type}"
exit 1
end
end
end
# TODO: Write documentation for `Some::Crystal::App`
module Some::Crystal::App
VERSION = "0.1.0"
test_without_wait
test_with_wait
test_high_level
test_loop
end