Last active
August 29, 2015 14:07
-
-
Save nicoolas25/9056581168b4657371e5 to your computer and use it in GitHub Desktop.
A small class that allows to loop over a changing set of values
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
require 'set' | |
require 'thread' | |
# A thread safe pool of values that can change. | |
class EquiSet | |
def initialize | |
@sorted_set = SortedSet.new | |
@mutex = Monitor.new | |
end | |
def include?(value) | |
item = Item.new(value) | |
@sorted_set.include?(item) | |
end | |
def append(value) | |
safely do | |
item = Item.new(value) | |
@sorted_set.add(item) | |
end | |
end | |
# Deletes a value in the pool. Returns nil if the | |
# value wasn't there and returns the value otherwise. | |
def delete(value) | |
safely do | |
item = Item.new(value) | |
item = @sorted_set.delete(item) | |
item && item.value | |
end | |
end | |
# Takes the first non-taken item if the pool. | |
def take | |
safely do | |
# If there is a free item, it is at the begining of | |
# the set because the way the set is sorted | |
# see `Item#<=>`. | |
item = @sorted_set.first | |
if item && item.free? | |
# Deletes the matching item | |
@sorted_set.delete(item) | |
# Adds a new but non-free item with the same value | |
new_item = Item.new(item.value, free: false) | |
@sorted_set.add(new_item) | |
# Return the value of the matching item | |
item.value | |
end | |
end | |
end | |
# Release a non-free value if it exists. It append the value | |
# at the end of the pool. It returns nil if the value wasn't | |
# there anymore and the value itself otherwise. | |
def release(value) | |
safely do | |
if delete(value) | |
append(value) | |
value | |
end | |
end | |
end | |
def safely(&block) | |
@mutex.synchronize do | |
block.call | |
end | |
end | |
# Define a class that is used by the EquiSet to sort the elements. | |
# Each item is tagged with its creation date. The Item provide | |
# the adequate methods to be used in a SortedSet: <=>, hash and eql?. | |
class Item | |
attr_reader :value | |
attr_reader :key | |
def initialize(value, free: true) | |
@value = value | |
@key = Time.now | |
@free = !!free | |
end | |
def free? | |
@free | |
end | |
def <=>(other) | |
# Same values are the same item | |
if other.value == @value | |
return 0 | |
end | |
# Free items goes first | |
if other.free? != @free | |
return @free ? -1 : 1 | |
end | |
# Order by key (timestamp) otherwise | |
@key <=> other.key | |
end | |
def hash | |
@value.hash | |
end | |
def ==(other) | |
other.value == @value | |
end | |
alias eql? == | |
end | |
end |
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
require_relative 'equiset' | |
WORKER_COUNT = 5 | |
JOB_COUNT = 10 * WORKER_COUNT | |
DURATION = 60 | |
# Create and fill the pool with integer jobs | |
pool = EquiSet.new | |
(0..JOB_COUNT).each do |i| | |
pool.append(i) | |
end | |
def do_work(pool, thread_id, random) | |
job = pool.take | |
if job | |
puts "<##{thread_id}> taking job ##{job}" | |
sleep_time = 0.5 + random.rand(1.5) | |
sleep sleep_time | |
else | |
puts "<##{thread_id}> no free job, waiting a few seconds..." | |
sleep 3 | |
end | |
ensure | |
if job | |
puts "<##{thread_id}> releasing job ##{job}" | |
pool.release(job) | |
end | |
end | |
# Spawn workers | |
workers = (0...WORKER_COUNT).map do |i| | |
Thread.new do | |
random = Random.new | |
loop do | |
do_work(pool, i, random) | |
end | |
end | |
end | |
# Let the program run during DURATION seconds | |
sleep DURATION | |
workers.each_with_index do |worker, i| | |
puts "Killing worker ##{i}" | |
worker.kill | |
end |
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
<#3> taking job #0 | |
<#1> taking job #1 | |
<#2> taking job #2 | |
<#0> taking job #3 | |
<#4> taking job #4 | |
<#2> releasing job #2 | |
<#2> taking job #5 | |
<#1> releasing job #1 | |
<#1> taking job #6 | |
<#4> releasing job #4 | |
<#4> taking job #7 | |
<#3> releasing job #0 | |
<#3> taking job #8 | |
<#0> releasing job #3 | |
<#0> taking job #9 | |
<#2> releasing job #5 | |
<#2> taking job #10 | |
<#3> releasing job #8 | |
<#3> taking job #11 | |
<#1> releasing job #6 | |
<#1> taking job #12 | |
<#2> releasing job #10 | |
<#2> taking job #13 | |
<#4> releasing job #7 | |
<#4> taking job #14 | |
<#0> releasing job #9 | |
<#0> taking job #15 | |
<#0> releasing job #15 | |
<#0> taking job #16 | |
<#1> releasing job #12 | |
<#1> taking job #17 | |
<#2> releasing job #13 | |
<#2> taking job #18 | |
<#4> releasing job #14 | |
<#4> taking job #19 | |
<#3> releasing job #11 | |
<#3> taking job #20 | |
<#2> releasing job #18 | |
<#2> taking job #21 | |
<#1> releasing job #17 | |
<#1> taking job #22 | |
<#0> releasing job #16 | |
<#0> taking job #23 | |
<#2> releasing job #21 | |
<#2> taking job #24 | |
<#0> releasing job #23 | |
<#0> taking job #25 | |
<#1> releasing job #22 | |
<#1> taking job #26 | |
<#4> releasing job #19 | |
<#4> taking job #27 | |
<#3> releasing job #20 | |
<#3> taking job #28 | |
<#1> releasing job #26 | |
<#1> taking job #29 | |
<#2> releasing job #24 | |
<#2> taking job #30 | |
<#4> releasing job #27 | |
<#4> taking job #31 | |
<#3> releasing job #28 | |
<#3> taking job #32 | |
<#2> releasing job #30 | |
<#2> taking job #33 | |
<#4> releasing job #31 | |
<#4> taking job #34 | |
<#0> releasing job #25 | |
<#0> taking job #35 | |
<#1> releasing job #29 | |
<#1> taking job #36 | |
<#2> releasing job #33 | |
<#2> taking job #37 | |
<#3> releasing job #32 | |
<#3> taking job #38 | |
<#1> releasing job #36 | |
<#1> taking job #39 | |
<#4> releasing job #34 | |
<#4> taking job #40 | |
<#0> releasing job #35 | |
<#0> taking job #41 | |
<#3> releasing job #38 | |
<#3> taking job #42 | |
<#2> releasing job #37 | |
<#2> taking job #43 | |
<#4> releasing job #40 | |
<#4> taking job #44 | |
<#1> releasing job #39 | |
<#1> taking job #45 | |
<#2> releasing job #43 | |
<#2> taking job #46 | |
<#0> releasing job #41 | |
<#0> taking job #47 | |
<#3> releasing job #42 | |
<#3> taking job #48 | |
<#4> releasing job #44 | |
<#4> taking job #49 | |
<#1> releasing job #45 | |
<#1> taking job #50 | |
<#2> releasing job #46 | |
<#2> taking job #2 | |
<#0> releasing job #47 | |
<#0> taking job #1 | |
<#1> releasing job #50 | |
<#1> taking job #4 | |
<#3> releasing job #48 | |
<#3> taking job #0 | |
<#4> releasing job #49 | |
<#4> taking job #3 | |
<#0> releasing job #1 | |
<#0> taking job #5 | |
<#2> releasing job #2 | |
<#2> taking job #8 | |
<#4> releasing job #3 | |
<#4> taking job #6 | |
<#0> releasing job #5 | |
<#0> taking job #10 | |
<#1> releasing job #4 | |
<#1> taking job #7 | |
<#3> releasing job #0 | |
<#3> taking job #9 | |
<#2> releasing job #8 | |
<#2> taking job #15 | |
<#4> releasing job #6 | |
<#4> taking job #12 | |
<#0> releasing job #10 | |
<#0> taking job #13 | |
<#1> releasing job #7 | |
<#1> taking job #14 | |
<#4> releasing job #12 | |
<#4> taking job #11 | |
<#2> releasing job #15 | |
<#2> taking job #18 | |
<#3> releasing job #9 | |
<#3> taking job #17 | |
<#2> releasing job #18 | |
<#2> taking job #16 | |
<#1> releasing job #14 | |
<#1> taking job #21 | |
<#0> releasing job #13 | |
<#0> taking job #23 | |
<#4> releasing job #11 | |
<#4> taking job #22 | |
<#3> releasing job #17 | |
<#3> taking job #19 | |
<#2> releasing job #16 | |
<#2> taking job #20 | |
<#4> releasing job #22 | |
<#4> taking job #26 | |
<#0> releasing job #23 | |
<#0> taking job #24 | |
<#1> releasing job #21 | |
<#1> taking job #27 | |
<#3> releasing job #19 | |
<#3> taking job #28 | |
<#0> releasing job #24 | |
<#0> taking job #30 | |
<#4> releasing job #26 | |
<#4> taking job #31 | |
<#2> releasing job #20 | |
<#2> taking job #25 | |
<#1> releasing job #27 | |
<#1> taking job #29 | |
<#3> releasing job #28 | |
<#3> taking job #33 | |
<#0> releasing job #30 | |
<#0> taking job #32 | |
<#1> releasing job #29 | |
<#1> taking job #36 | |
<#4> releasing job #31 | |
<#4> taking job #34 | |
<#0> releasing job #32 | |
<#0> taking job #35 | |
<#2> releasing job #25 | |
<#2> taking job #38 | |
<#1> releasing job #36 | |
<#1> taking job #37 | |
<#3> releasing job #33 | |
<#3> taking job #40 | |
<#4> releasing job #34 | |
<#4> taking job #39 | |
<#2> releasing job #38 | |
<#2> taking job #43 | |
<#1> releasing job #37 | |
<#1> taking job #41 | |
<#0> releasing job #35 | |
<#0> taking job #42 | |
<#1> releasing job #41 | |
<#1> taking job #44 | |
<#2> releasing job #43 | |
<#2> taking job #45 | |
<#0> releasing job #42 | |
<#0> taking job #46 | |
<#3> releasing job #40 | |
<#3> taking job #47 | |
<#4> releasing job #39 | |
<#4> taking job #50 | |
<#3> releasing job #47 | |
<#3> taking job #48 | |
<#1> releasing job #44 | |
<#1> taking job #49 | |
<#2> releasing job #45 | |
<#2> taking job #1 | |
<#0> releasing job #46 | |
<#4> releasing job #50 | |
<#0> taking job #2 | |
<#4> taking job #3 | |
<#2> releasing job #1 | |
<#2> taking job #5 | |
<#3> releasing job #48 | |
<#3> taking job #4 | |
<#1> releasing job #49 | |
<#1> taking job #0 | |
<#4> releasing job #3 | |
<#4> taking job #8 | |
<#2> releasing job #5 | |
<#2> taking job #6 | |
<#0> releasing job #2 | |
<#0> taking job #10 | |
<#3> releasing job #4 | |
<#3> taking job #7 | |
<#0> releasing job #10 | |
<#0> taking job #12 | |
<#1> releasing job #0 | |
<#1> taking job #15 | |
<#4> releasing job #8 | |
<#4> taking job #9 | |
<#3> releasing job #7 | |
<#3> taking job #18 | |
<#2> releasing job #6 | |
<#2> taking job #14 | |
<#1> releasing job #15 | |
<#1> taking job #13 | |
<#4> releasing job #9 | |
<#4> taking job #11 | |
<#0> releasing job #12 | |
<#0> taking job #17 | |
<#3> releasing job #18 | |
<#3> taking job #16 | |
<#1> releasing job #13 | |
<#1> taking job #22 | |
<#4> releasing job #11 | |
<#4> taking job #23 | |
<#2> releasing job #14 | |
<#2> taking job #21 | |
<#0> releasing job #17 | |
<#0> taking job #19 | |
<#1> releasing job #22 | |
<#1> taking job #24 | |
<#3> releasing job #16 | |
<#3> taking job #26 | |
<#4> releasing job #23 | |
<#4> taking job #20 | |
<#2> releasing job #21 | |
<#2> taking job #27 | |
<#1> releasing job #24 | |
<#1> taking job #28 | |
<#0> releasing job #19 | |
<#0> taking job #30 | |
<#0> releasing job #30 | |
<#0> taking job #29 | |
<#1> releasing job #28 | |
<#1> taking job #31 | |
<#3> releasing job #26 | |
<#3> taking job #32 | |
<#4> releasing job #20 | |
<#4> taking job #25 | |
<#2> releasing job #27 | |
<#2> taking job #36 | |
<#0> releasing job #29 | |
<#0> taking job #33 | |
<#2> releasing job #36 | |
<#2> taking job #34 | |
<#1> releasing job #31 | |
<#1> taking job #38 | |
<#0> releasing job #33 | |
<#0> taking job #37 | |
<#4> releasing job #25 | |
<#4> taking job #35 | |
<#3> releasing job #32 | |
<#3> taking job #41 | |
<#2> releasing job #34 | |
<#2> taking job #43 | |
<#1> releasing job #38 | |
<#1> taking job #42 | |
<#0> releasing job #37 | |
<#0> taking job #40 | |
<#1> releasing job #42 | |
<#1> taking job #39 | |
<#4> releasing job #35 | |
<#4> taking job #47 | |
<#2> releasing job #43 | |
<#2> taking job #44 | |
<#3> releasing job #41 | |
<#3> taking job #45 | |
<#0> releasing job #40 | |
<#0> taking job #46 | |
<#1> releasing job #39 | |
<#1> taking job #50 | |
<#2> releasing job #44 | |
<#2> taking job #1 | |
<#0> releasing job #46 | |
<#0> taking job #48 | |
<#3> releasing job #45 | |
<#3> taking job #49 | |
<#1> releasing job #50 | |
<#1> taking job #3 | |
<#4> releasing job #47 | |
<#4> taking job #5 | |
<#2> releasing job #1 | |
<#2> taking job #2 | |
<#0> releasing job #48 | |
<#0> taking job #4 | |
<#1> releasing job #3 | |
<#1> taking job #10 | |
<#3> releasing job #49 | |
<#3> taking job #0 | |
<#0> releasing job #4 | |
<#0> taking job #8 | |
<#4> releasing job #5 | |
<#4> taking job #7 | |
<#2> releasing job #2 | |
<#2> taking job #6 | |
<#0> releasing job #8 | |
<#0> taking job #15 | |
<#3> releasing job #0 | |
<#3> taking job #9 | |
<#1> releasing job #10 | |
<#1> taking job #12 | |
<#0> releasing job #15 | |
<#0> taking job #18 | |
<#2> releasing job #6 | |
<#2> taking job #13 | |
<#3> releasing job #9 | |
<#3> taking job #11 | |
<#4> releasing job #7 | |
<#4> taking job #14 | |
<#1> releasing job #12 | |
<#1> taking job #17 | |
<#3> releasing job #11 | |
<#3> taking job #22 | |
<#2> releasing job #13 | |
<#2> taking job #16 | |
<#3> releasing job #22 | |
<#3> taking job #23 | |
<#0> releasing job #18 | |
<#0> taking job #21 | |
<#1> releasing job #17 | |
<#1> taking job #24 | |
<#4> releasing job #14 | |
<#4> taking job #19 | |
<#2> releasing job #16 | |
<#2> taking job #30 | |
<#1> releasing job #24 | |
<#1> taking job #28 | |
<#3> releasing job #23 | |
<#3> taking job #26 | |
<#2> releasing job #30 | |
<#2> taking job #20 | |
<#0> releasing job #21 | |
<#0> taking job #27 | |
<#4> releasing job #19 | |
<#4> taking job #29 | |
<#0> releasing job #27 | |
<#0> taking job #36 | |
<#2> releasing job #20 | |
<#2> taking job #31 | |
<#1> releasing job #28 | |
<#1> taking job #33 | |
<#3> releasing job #26 | |
<#3> taking job #25 | |
<#0> releasing job #36 | |
<#0> taking job #32 | |
<#4> releasing job #29 | |
<#4> taking job #34 | |
<#1> releasing job #33 | |
<#1> taking job #38 | |
<#2> releasing job #31 | |
<#2> taking job #37 | |
<#3> releasing job #25 | |
<#3> taking job #42 | |
<#3> releasing job #42 | |
<#3> taking job #35 | |
<#0> releasing job #32 | |
<#0> taking job #43 | |
<#4> releasing job #34 | |
<#4> taking job #41 | |
<#2> releasing job #37 | |
<#2> taking job #40 | |
<#0> releasing job #43 | |
<#0> taking job #39 | |
<#1> releasing job #38 | |
<#1> taking job #44 | |
<#2> releasing job #40 | |
<#2> taking job #46 | |
<#0> releasing job #39 | |
<#0> taking job #45 | |
<#3> releasing job #35 | |
<#3> taking job #50 | |
<#1> releasing job #44 | |
<#1> taking job #47 | |
<#4> releasing job #41 | |
<#4> taking job #1 | |
<#2> releasing job #46 | |
<#2> taking job #48 | |
<#4> releasing job #1 | |
<#4> taking job #3 | |
<#1> releasing job #47 | |
<#1> taking job #49 | |
<#2> releasing job #48 | |
<#2> taking job #4 | |
<#0> releasing job #45 | |
<#0> taking job #5 | |
<#3> releasing job #50 | |
<#3> taking job #2 | |
<#4> releasing job #3 | |
<#4> taking job #8 | |
<#0> releasing job #5 | |
<#0> taking job #0 | |
<#2> releasing job #4 | |
<#2> taking job #10 | |
<#1> releasing job #49 | |
<#1> taking job #15 | |
<#2> releasing job #10 | |
<#2> taking job #6 | |
<#3> releasing job #2 | |
<#3> taking job #9 | |
<#4> releasing job #8 | |
<#4> taking job #7 | |
<#0> releasing job #0 | |
<#0> taking job #12 | |
<#1> releasing job #15 | |
<#1> taking job #11 | |
<#1> releasing job #11 | |
<#1> taking job #13 | |
<#3> releasing job #9 | |
<#3> taking job #22 | |
<#0> releasing job #12 | |
<#0> taking job #18 | |
<#4> releasing job #7 | |
<#4> taking job #17 | |
<#2> releasing job #6 | |
<#2> taking job #14 | |
<#1> releasing job #13 | |
<#1> taking job #16 | |
<#3> releasing job #22 | |
<#3> taking job #24 | |
<#2> releasing job #14 | |
<#2> taking job #23 | |
<#0> releasing job #18 | |
<#0> taking job #30 | |
<#4> releasing job #17 | |
<#4> taking job #21 | |
<#1> releasing job #16 | |
<#1> taking job #19 | |
<#2> releasing job #23 | |
<#2> taking job #27 | |
<#0> releasing job #30 | |
<#0> taking job #20 | |
<#3> releasing job #24 | |
<#3> taking job #28 | |
<#3> releasing job #28 | |
<#3> taking job #26 | |
<#4> releasing job #21 | |
<#4> taking job #36 | |
<#2> releasing job #27 | |
<#2> taking job #29 | |
<#1> releasing job #19 | |
<#1> taking job #33 | |
<#0> releasing job #20 | |
<#0> taking job #31 | |
Killing worker #0 | |
Killing worker #1 | |
Killing worker #2 | |
Killing worker #3 | |
Killing worker #4 | |
<#0> releasing job #31 | |
<#1> releasing job #33 | |
<#2> releasing job #29 | |
<#3> releasing job #26 | |
<#4> releasing job #36 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment