Skip to content

Instantly share code, notes, and snippets.

@itarato
Created February 19, 2023 04:28
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save itarato/82ddb50afbd8d49d63324ea533df5ed9 to your computer and use it in GitHub Desktop.
Save itarato/82ddb50afbd8d49d63324ea533df5ed9 to your computer and use it in GitHub Desktop.
Thread step management enhanced testing
require("thread")
class Foo
def initialize(arr)
@arr = arr
end
def update
i = @arr[-1]
@arr.push(i + 1)
end
end
class ThreadRunManager
SLEEP_THRESHOLD = 8
def initialize
@main_thread_id = Thread.current.object_id
@mutex = Mutex.new
@threads_passes = {}
end
def thread_id = Thread.current.object_id
def first? = @threads_passes.keys.index(thread_id) == 0
def pass_count = @threads_passes[thread_id]
def other_pass_count
other_thread_keys = @threads_passes.keys - [thread_id]
if other_thread_keys.size == 0
0
else
@threads_passes[other_thread_keys[0]]
end
end
def on_line(tp)
return unless Thread.current.object_id != @main_thread_id
@mutex.synchronize do
if !@threads_passes.key?(thread_id)
@threads_passes[thread_id] = 0
end
end
can_pass = false
sleep_count = 0
while !can_pass do
@mutex.synchronize do
if first?
if other_pass_count == pass_count
can_pass = true
end
else
if other_pass_count > pass_count
can_pass = true
end
end
end
if sleep_count >= SLEEP_THRESHOLD
puts("Sleep threshold reached - forcing execution")
break
end
sleep_count += 1
sleep(0.001)
end
puts("Called line #{tp.lineno} in #{tp.path} with #{tp.binding.class} in thread #{thread_id}")
@mutex.synchronize do
@threads_passes[thread_id] += 1
end
end
end
arr = [3]
puts("Main thread: #{Thread.current.object_id}")
tm = ThreadRunManager.new
tp = TracePoint.new(:line) do |tp|
# puts("Called line #{tp.lineno} in #{tp.path} with #{tp.binding.class} in thread #{Thread.current.object_id}")
# p [tp.lineno, tp.event, tp.binding.local_variables]
# sleep(1) if tp.lineno == 19
tm.on_line(tp)
end
tp.enable
t1 = Thread.new do
f = Foo.new(arr)
f.update
end
t2 = Thread.new do
f = Foo.new(arr)
f.update
end
t2.join
t1.join
tp.disable
puts("Arr: #{arr}")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment