Skip to content

Instantly share code, notes, and snippets.

@octosteve
Created December 11, 2020 00:22
Show Gist options
  • Save octosteve/ae231bc03a420be7fdcdc49b725cb65a to your computer and use it in GitHub Desktop.
Save octosteve/ae231bc03a420be7fdcdc49b725cb65a to your computer and use it in GitHub Desktop.
GenServer implementation in Ruby
class Stack
def self.start_link(state)
GenServer.start_link(new(state))
end
def self.push(ractor, value)
GenServer.cast(ractor, [:push, value])
end
def self.pop(ractor)
GenServer.call(ractor, :pop)
end
def initialize(state)
@state = state
end
def handle_cast(msg)
case msg
in [:push, value]
push(value)
[:noreply, self]
end
end
def handle_call(msg, _from)
case msg
when :pop
[:reply, pop(), self]
end
end
def push(value)
state.unshift(value)
end
def pop
state.shift
end
private
attr_reader :state
end
module GenServer
def self.start_link(state)
r = Ractor.new(state) do |state|
GenServer.receive(state)
end
[:ok, r]
end
def self.cast(ractor, msg)
ractor.send(['$gen_cast', msg])
end
def self.call(ractor, msg)
ractor.send(['$gen_call', Ractor.current, msg])
case Ractor.receive
in [:ok, res]
res
end
end
def self.receive(state)
case Ractor.receive
in ['$gen_cast', msg]
case state.handle_cast(msg)
in [:noreply, state]
GenServer.receive(state)
end
in ['$gen_call', from, msg]
case state.handle_call(msg, from)
in [:reply, reply, state]
from.send([:ok, reply])
GenServer.receive(state)
end
end
end
end
Stack.start_link([:hello]) => [:ok, ractor] # In line pattern matching
Stack.pop(ractor) # => :hello
Stack.push(ractor, :world)
Stack.pop(ractor) # => :world
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment