Skip to content

Commit

Permalink
Fix: global arena accessor (class vars aren't inherited)
Browse files Browse the repository at this point in the history
  • Loading branch information
ysbaddaden committed Sep 3, 2024
1 parent 4586892 commit 07220b2
Show file tree
Hide file tree
Showing 4 changed files with 15 additions and 13 deletions.
2 changes: 1 addition & 1 deletion src/crystal/arena.cr
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# OPTIMIZE: can the generation help to avoid the mutation lock (atomic)?
# OPTIMIZE: consider a memory map (mmap, VirtualAlloc) with a maximum capacity
struct Crystal::Arena(T)
class Crystal::Arena(T)
struct Allocation(T)
property generation = 0_u32
property? allocated = false
Expand Down
4 changes: 2 additions & 2 deletions src/crystal/system/unix/epoll/event_loop.cr
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ class Crystal::Epoll::EventLoop < Crystal::Evented::EventLoop
system_set_timer(@timers.next_ready?)

# re-add all registered fds
@@arena.each { |fd, gen_index| system_add(fd, gen_index) }
Evented.arena.each { |fd, gen_index| system_add(fd, gen_index) }
end
{% end %}

Expand Down Expand Up @@ -97,7 +97,7 @@ class Crystal::Epoll::EventLoop < Crystal::Evented::EventLoop
Crystal.trace :evloop, "event", fd: fd, gen_index: gen_index, events: events
{% end %}

pd = @@arena.get(gen_index)
pd = Evented.arena.get(gen_index)

if (events & (LibC::EPOLLERR | LibC::EPOLLHUP)) != 0
pd.value.@readers.consume_each { |event| resume_io(event) }
Expand Down
18 changes: 10 additions & 8 deletions src/crystal/system/unix/evented/event_loop.cr
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
require "./*"
require "../../../arena"

module Crystal::Evented
protected class_getter arena = Arena(PollDescriptor).new
end

# OPTIMIZE: collect fibers & canceled timers, delete canceled timers when
# processing timers, and eventually enqueue all fibers; it would avoid repeated
# lock/unlock timers on each #resume_io and allow to replace individual fiber
Expand All @@ -10,8 +14,6 @@ abstract class Crystal::Evented::EventLoop < Crystal::EventLoop
@run_lock = Atomic::Flag.new
{% end %}

@@arena = Arena(PollDescriptor).new

def initialize
@lock = SpinLock.new
@timers = Timers.new
Expand Down Expand Up @@ -75,7 +77,7 @@ abstract class Crystal::Evented::EventLoop < Crystal::EventLoop

def delete(file_descriptor : System::FileDescriptor) : Nil
fd = file_descriptor.fd
@@arena.free(fd) { |pd| pd.value.release(fd) }
Evented.arena.free(fd) { |pd| pd.value.release(fd) }
end

def read(file_descriptor : System::FileDescriptor, slice : Bytes) : Int32
Expand Down Expand Up @@ -114,7 +116,7 @@ abstract class Crystal::Evented::EventLoop < Crystal::EventLoop

def delete(socket : ::Socket) : Nil
fd = socket.fd
@@arena.free(fd) { |pd| pd.value.release(fd) }
Evented.arena.free(fd) { |pd| pd.value.release(fd) }
end

def read(socket : ::Socket, slice : Bytes) : Int32
Expand Down Expand Up @@ -241,7 +243,7 @@ abstract class Crystal::Evented::EventLoop < Crystal::EventLoop
end

protected def evented_close(io)
@@arena.free(io.fd) do |pd|
Evented.arena.free(io.fd) do |pd|
pd.value.@readers.consume_each { |event| resume_io(event) }
pd.value.@writers.consume_each { |event| resume_io(event) }
pd.value.release(io.fd)
Expand All @@ -266,7 +268,7 @@ abstract class Crystal::Evented::EventLoop < Crystal::EventLoop

private macro wait(type, fd, waiters, timeout, &)
# lazily register the fd
%pd, %gen_index = @@arena.lazy_allocate({{fd}}) do |pd, gen_index|
%pd, %gen_index = Evented.arena.lazy_allocate({{fd}}) do |pd, gen_index|
# register the fd with the event loop (once), it should usually merely add
# the fd to the current evloop but may "transfer" the ownership from
# another event loop:
Expand Down Expand Up @@ -354,12 +356,12 @@ abstract class Crystal::Evented::EventLoop < Crystal::EventLoop
when .io_read?
# reached read timeout: cancel io event
event.value.timed_out!
pd = @@arena.get(event.value.gen_index)
pd = Evented.arena.get(event.value.gen_index)
pd.value.@readers.delete(event)
when .io_write?
# reached write timeout: cancel io event
event.value.timed_out!
pd = @@arena.get(event.value.gen_index)
pd = Evented.arena.get(event.value.gen_index)
pd.value.@writers.delete(event)
when .select_timeout?
# always dequeue the event but only enqueue the fiber if we win the
Expand Down
4 changes: 2 additions & 2 deletions src/crystal/system/unix/kqueue/event_loop.cr
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ class Crystal::Kqueue::EventLoop < Crystal::Evented::EventLoop
system_set_timer(@timers.next_ready?)

# re-add all registered fds
@@arena.each { |fd, gen_index| system_add(fd, gen_index) }
Evented.arena.each { |fd, gen_index| system_add(fd, gen_index) }
end
{% end %}

Expand Down Expand Up @@ -120,7 +120,7 @@ class Crystal::Kqueue::EventLoop < Crystal::Evented::EventLoop
filter: kevent.value.filter, flags: kevent.value.flags, fflags: kevent.value.fflags
{% end %}

pd = @@arena.get(gen_index)
pd = Evented.arena.get(gen_index)

if (kevent.value.fflags & LibC::EV_EOF) == LibC::EV_EOF
# apparently some systems may report EOF on write with EVFILT_READ instead
Expand Down

0 comments on commit 07220b2

Please sign in to comment.