Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Handling updates in background #19

Open
yi-jiayu opened this issue Feb 15, 2019 · 2 comments
Open

Handling updates in background #19

yi-jiayu opened this issue Feb 15, 2019 · 2 comments

Comments

@yi-jiayu
Copy link

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.

@vladislav-yashin
Copy link
Contributor

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.

@yi-jiayu
Copy link
Author

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants