Skip to content

Reuse ready callbacks generator#159

Merged
sloretz merged 3 commits intomasterfrom
reuse_callback_generator
Dec 1, 2017
Merged

Reuse ready callbacks generator#159
sloretz merged 3 commits intomasterfrom
reuse_callback_generator

Conversation

@sloretz
Copy link
Copy Markdown
Contributor

@sloretz sloretz commented Nov 28, 2017

This adds a wrapper around wait_for_ready_callbacks that reuses the callback generator when multiple things are ready. It avoids unnecessary wait list construction and waiting. It also prevents one callback (like a very fast timer) from starving other callbacks (similar to ros2/rclcpp#392).

Taken from #140 and improved upon.

CI (New run after fixing a merge conflict)

  • Linux Build Status
  • Linux-aarch64 Build Status
  • macOS Build Status
  • Windows Build Status

@sloretz sloretz added the in review Waiting for review (Kanban column) label Nov 28, 2017
@sloretz sloretz self-assigned this Nov 28, 2017
@sloretz sloretz force-pushed the reuse_callback_generator branch from 211a8dc to 9b072ae Compare November 29, 2017 17:29
self._last_args = args
self._last_kwargs = kwargs
self._cb_iter = self._wait_for_ready_callbacks(*args, **kwargs)
try:
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor nit: I'd put a blank line before this try block, just to visually distinguish it from the if block above.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added in 786b4cf

"""Runs callbacks in the thread which calls :func:`SingleThreadedExecutor.spin`."""

def __init__(self):
super().__init__()
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My understanding is that a method that is not overloaded in the child class means that the parent version of the method is used. I believe this applies to all methods included the __init_ one

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wasn't sure about this, so I just tried it out with the following program:

class Base:
	def __init__(self):
		print("Base init")

class Sub:
	def do_something(self):
		print("Sub do_something")

x = Sub()
x.do_something()

If you run that under python3, the output you get is just "Sub do_something"; you never see the "Base init" printed out.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you try the same thing with Sub inheriting from base ?

class Base:
	def __init__(self):
		print("Base init")

class Sub(Base):
	def do_something(self):
		print("Sub do_something")

x = Sub()
x.do_something()

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

D'oh, sorry. I forgot that bit. Never mind, you are totally correct.

"""Runs callbacks in the thread which calls :func:`SingleThreadedExecutor.spin`."""

def __init__(self):
super().__init__()
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My understanding is that a method that is not overloaded in the child class means that the parent version of the method is used. I believe this applies to all methods included the __init_ one

@clalancette
Copy link
Copy Markdown
Contributor

It also prevents one callback (like a very fast timer) from starving other callbacks (similar to ros2/rclcpp#392).

Does this new code have this property because we always process everything from the previous wait set before constructing a new one? (I just want to make sure I understand)

@sloretz
Copy link
Copy Markdown
Contributor Author

sloretz commented Nov 30, 2017

Does this new code have this property because we always process everything from the previous wait set before constructing a new one?

@clalancette Yup

Edit: Assuming of course that rmw_wait populates the wait set with everything that is ready, rather than returning just the first thing it sees that is ready.

Copy link
Copy Markdown
Member

@mikaelarguedas mikaelarguedas left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm, @clalancette is reviewing as well so let's wait for his feedback as well

Adds wrapper around wait_for_ready_callbacks
Wrapper reuses generator if arguments match while it's still producing
Adds TimeoutException and raises it when waiting times out
@clalancette
Copy link
Copy Markdown
Contributor

The only concern I have is with the recursive nature of wait_for_ready_callbacks, and whether that recursion can go without bounds in some cases. @sloretz thinks that the maximum we can go is one level deep, but he is doing a bit of research/playing around and will report back.

@sloretz sloretz force-pushed the reuse_callback_generator branch from 786b4cf to b7fa6d6 Compare November 30, 2017 23:43
@sloretz
Copy link
Copy Markdown
Contributor Author

sloretz commented Nov 30, 2017

@clalancette eliminated the recursion in b7fa6d6

CI

  • Linux Build Status
  • Linux-aarch64 Build Status
  • macOS Build Status
  • Windows Build Status

"""
# if an old generator is done, this variable makes the loop get a new one before returning
got_generator = False
while not got_generator:
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like the loop a lot better; thanks!

@sloretz sloretz merged commit 890c42b into master Dec 1, 2017
@sloretz sloretz removed the in review Waiting for review (Kanban column) label Dec 1, 2017
@sloretz sloretz deleted the reuse_callback_generator branch December 1, 2017 16:08
sloretz added a commit to ros2/examples that referenced this pull request Dec 6, 2017
ros2/rclpy#159 changed wait_for_ready_callbacks to manage the generator internally and return just a tuple
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

Successfully merging this pull request may close these issues.

3 participants