Created
September 24, 2019 17:53
-
-
Save ytnk531/4be3ba9a72da2fe024ce9c98508562f8 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# frozen_string_literal: true | |
require 'fiber' | |
# Manage packet. | |
class Packets | |
def initialize | |
@packets = [] | |
end | |
def add(packet) | |
@packets << packet | |
end | |
def delete(packet) | |
@packets.delete(packet) | |
end | |
def find_by_dest(node) | |
@packets.select { |packet| packet.dest == node }.first | |
end | |
def for?(node) | |
@packets.select { |packet| packet.dest == node }.first | |
end | |
end | |
# Network. | |
# This presents behaviroes of network seen from layer 5. | |
class Network | |
def initialize | |
@packets = Packets.new | |
@blocked_nodes = {} | |
end | |
def send_packet(packet) | |
@blocked_nodes.key?(packet.dest) | |
@packets.add(packet) | |
return unless (fiber = @blocked_nodes[packet.dest.id]) | |
fiber.resume(packet) | |
end | |
def receive(node) | |
unless @packets.for?(node) | |
schedule_receive(node.id, Fiber.current) | |
Fiber.yield | |
end | |
packet = @packets.find_by_dest(node) | |
@packets.delete(packet) | |
end | |
def schedule_receive(id, fiber) | |
@blocked_nodes.merge!(id => fiber) | |
end | |
end | |
# Packet. | |
class Packet | |
attr_accessor :dest, :sender, :data | |
def initialize(dest: nil, sender: nil, data: nil) | |
@dest = dest | |
@sender = sender | |
@data = data | |
end | |
def to_s | |
"dest: #{@dest.id}, sender: #{@sender.id}, data: #{@data}" | |
end | |
end | |
# Node. | |
class Node | |
@id_counter = 0 | |
attr_reader :id | |
def self.new_id | |
@id_counter += 1 | |
end | |
def initialize(network) | |
@network = network | |
@id = self.class.new_id | |
end | |
def send_to(node, data) | |
@network.send_packet(Packet.new(dest: node, sender: self, data: data)) | |
end | |
def receive | |
@network.receive(self) | |
end | |
def execute(&block) | |
Fiber.new do | |
block.call(self) | |
end.resume | |
end | |
def print_log(message) | |
puts "node:#{@id} #{message}" | |
end | |
end | |
network = Network.new | |
n1 = Node.new(network) | |
n2 = Node.new(network) | |
n3 = Node.new(network) | |
n1.execute do |node| | |
node.send_to(n2, 'Hello.') | |
packet = node.receive | |
node.print_log("received packet: #{packet}") | |
end | |
n2.execute do |node| | |
packet = node.receive | |
node.print_log("received packet: #{packet}") | |
node.send_to(n1, "I received your message. You said #{packet.data}") | |
packet = node.receive | |
node.print_log(packet) | |
end | |
n3.execute do |node| | |
node.send_to(n2, "I'm node3") | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment