diff options
Diffstat (limited to 'src/channel.moon')
| -rw-r--r-- | src/channel.moon | 73 |
1 files changed, 73 insertions, 0 deletions
diff --git a/src/channel.moon b/src/channel.moon new file mode 100644 index 0000000..968ae09 --- /dev/null +++ b/src/channel.moon @@ -0,0 +1,73 @@ + +-- Implements a channels, an abstraction for sending data + +class Channel + new: (settings) => + settings = settings or {} + --Every channel has at least a buffer, the messages to be read on recv() + @buffer = {} + for setting_name, setting_value in pairs settings + @[setting_name] = setting_value + poll: => + error("Channel must implement poll") + send: (message) => + error("Channel must implement message") + recv: => + error("Channel must implement recv") + +class SimpleChannel extends Channel + @time = 0 + new: (settings) => + super(settings) + poll: => + #@buffer > 0 + send: (message) => + table.insert(@buffer, message) + recv: => + table.remove(@buffer, 1) + +class FaultyChannel extends Channel + -- Mock channel for testing + @time = 0 + new: (settings) => + @to_deliver = {} + @avg_latency = 0 -- in ms + @latency_std = 0 + -- Latency can never be below 0, but can go up as much as it likes + @avg_loss = 0 -- between 0 (never) and 1 (always) + @loss_std = 0.1 + -- Loss is always a percentage between 0 and 1 + super(settings) + normal: (avg, std, n) => + assert(avg and std and n, string.format("normal(avg, std, n) called with %q %q %q", tostring(avg), tostring(std), tostring(n))) + -- Normal curve probability at N + (1/ (math.sqrt(2*math.pi) * avg)) * math.exp(-(n - avg)^2 / (2 * (std^2))) + poll: => + @pump! + #@buffer > 0 + send: (message) => + -- Do we deliver? + if @normal(@avg_loss, @loss_std, math.random()) < 0.5 + return + -- How long does it take? + time = @normal(@avg_latency, @latency_std, math.random()) + if time < 0 then + time = 0 -- We can't deliver messages in the past + table.insert(@to_deliver, {message,time}) + recv: => + @pump! + table.remove(@buffer, 1) + pump: => + defrag = 1 + deliver_len = #@to_deliver + for k,tbl in ipairs(@to_deliver) + {m, t} = tbl + if @@time > t + @to_deliver[k] = nil + table.insert(@buffer, m) + if @to_deliver[defrag] == nil + @to_deliver[defrag] = tbl + for i = defrag, deliver_len do + @to_deliver[i] = nil + +{:Channel, :SimpleChannel, :FaultyChannel} |
