Handling updates in background
Is there a way to register handlers and then loop forever while processing them?
I tried this naive way of doing so:
while client.alive?
end
However this pegs the CPU at 100%.
Here's something I've tried instead:
diff --git a/lib/tdlib/client.rb b/lib/tdlib/client.rb
index 54356a9..3d8279f 100644
--- a/lib/tdlib/client.rb
+++ b/lib/tdlib/client.rb
@@ -49,10 +49,14 @@ class TD::Client
end
end
- @update_manager.run
+ @thread = @update_manager.run
ready
end
+ def wait
+ @thread.join if @thread
+ end
+
# Sends asynchronous request to the TDLib client and returns Promise object
# @see TD::ClientMethods List of available queries as methods
# @see https://github.com/ruby-concurrency/concurrent-ruby/blob/master/docs-source/promises.in.md
This assigns the thread returned by UpdateManager#run to an instance variable so that it can be joined in the Client#wait method.
Then I create some signal handlers to call Client#dispose on interrupt (which causes the thread started by UpdateManager to return), and wait on the client:
diff --git a/README.md b/README.md
index 5e1ba88..b3a162c 100644
--- a/README.md
+++ b/README.md
@@ -75,7 +75,7 @@ begin
nil
end
end
-
+
client.connect
loop do
@@ -99,6 +99,25 @@ begin
sleep 0.1
end
+ client.on(TD::Types::Update) do |update|
+ puts 'Got update:'
+ puts update
+ end
+
+ Signal.trap("INT") {
+ Thread.start do
+ client.dispose
+ end
+ }
+
+ Signal.trap("TERM") {
+ Thread.start do
+ client.dispose
+ end
+ }
+
+ client.wait
+
ensure
client.dispose
end
This processes updates continuously without spinning.
Would this work for you?
while client.alive?
sleep 1
end
sleep will put the current running thread to sleep and schedule the execution of another thread.
But I agree that we should think about implementing the built-in way of doing this. Joining UpdateManager thread is a good idea, but I will think a bit more about the public API.
Cool, that works.
Did a simple comparison between the three methods:
Modified Client:
$ time timeout 5 bundle exec ruby example.rb
real 0m5.020s
user 0m0.496s
sys 0m0.211s
While loop without sleep:
$ time timeout 5 bundle exec ruby example.rb
real 0m5.017s
user 0m4.720s
sys 0m0.182s
While loop with sleep 1:
$ time timeout 5 bundle exec ruby example.rb
real 0m5.025s
user 0m0.454s
sys 0m0.175s
The while loop without sleep spends almost all of its time in user mode, while both joining the UpdateManager thread and a while loop with sleep 1 perform similarly.