Skip to content

Instantly share code, notes, and snippets.

@ysbaddaden
Created June 4, 2024 16:00
Show Gist options
  • Save ysbaddaden/03e6e05c709a9b8c448e29f6bbdc3e6a to your computer and use it in GitHub Desktop.
Save ysbaddaden/03e6e05c709a9b8c448e29f6bbdc3e6a to your computer and use it in GitHub Desktop.
epoll.cr
lib LibC
EPOLL_CLOEXEC = 0o2000000
EPOLLIN = 0x001_u32
EPOLLPRI = 0x002_u32
EPOLLOUT = 0x004_u32
EPOLLRDNORM = 0x040_u32
EPOLLRDBAND = 0x080_u32
EPOLLWRNORM = 0x100_u32
EPOLLWRBAND = 0x200_u32
EPOLLMSG = 0x400_u32
EPOLLERR = 0x008_u32
EPOLLHUP = 0x010_u32
EPOLLRDHUP = 0x2000_u32
EPOLLEXCLUSIVE = 1_u32 << 28
EPOLLWAKEUP = 1_u32 << 29
EPOLLONESHOT = 1_u32 << 30
EPOLLET = 1_u32 << 31
EPOLL_CTL_ADD = 1
EPOLL_CTL_MOD = 2
EPOLL_CTL_DEL = 3
{% if flag?(:x86_64) %}
# on x86_64 the struct is packed to simplify 32-bit emulation
@[Packed]
{% end %}
struct EpollEvent
events : UInt32
data : Void*
end
fun epoll_create1(flags : Int) : Int
fun epoll_ctl(epfd : Int, op : Int, fd : Int, event : EpollEvent*) : Int
fun epoll_wait(epfd : Int, events : EpollEvent*, maxevents : Int, timeout : Int) : Int
end
{% skip_file unless flag?(:linux) %}
require "./c/sys/epoll"
struct Epoll
def initialize
@epfd = LibC.epoll_create1(LibC::EPOLL_CLOEXEC)
raise RuntimeError.from_errno("epoll_create1") if @epfd == -1
end
def add(fd : Int32, event : LibC::EpollEvent*) : Nil
if LibC.epoll_ctl(@epfd, LibC::EPOLL_CTL_ADD, fd, event) == -1
raise RuntimeError.from_errno("epoll_ctl(EPOLL_CTL_ADD)")
end
end
def modify(fd : Int32, event : LibC::EpollEvent*) : Nil
if LibC.epoll_ctl(@epfd, LibC::EPOLL_CTL_MOD, fd, event) == -1
raise RuntimeError.from_errno("epoll_ctl(EPOLL_CTL_MOD)")
end
end
def delete(fd : Int32) : Nil
if LibC.epoll_ctl(@epfd, LibC::EPOLL_CTL_DEL, fd, nil) == -1
raise RuntimeError.from_errno("epoll_ctl(EPOLL_CTL_DEL)")
end
end
# `timeout` is in milliseconds
def wait(events : Slice(LibC::EpollEvent), timeout : Int32) : Int32
count = LibC.epoll_wait(@epfd, events.to_unsafe, events.size, timeout)
raise RuntimeError.from_errno("epoll_wait") if count == -1
count
end
def close : Nil
if LibC.close(@epfd) == -1
raise RuntimeError.from_errno("close")
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment