Skip to content
This repository was archived by the owner on Nov 23, 2017. It is now read-only.

Conversation

1st1
Copy link
Member

@1st1 1st1 commented Nov 16, 2015

This PR cleans up Future class by factoring out _copy_state() and _set_result_unless_cancelled() into separate functions.

@1st1 1st1 changed the title Public future Cleanup Future API Nov 16, 2015
@@ -155,6 +155,7 @@ def __init__(self, *, loop=None):
self._source_traceback = traceback.extract_stack(sys._getframe(1))

def _format_callbacks(self):
# Private method, do not rely on its existence.
Copy link
Member

Choose a reason for hiding this comment

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

Would it make sense to rename to __format_callbacks? Or are there subclasses that call it?

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes, this is a good idea. Nothing is using this method besides the base Future class.

@gvanrossum
Copy link
Member

Harmless, but suggesting some changes.

@gvanrossum
Copy link
Member

Ping me when you want me to have another look. (GitHub's PR code review confuses me because it's so different from the tools I've been using for 10 years.)

@@ -174,6 +175,7 @@ def format_cb(callback):
return 'cb=[%s]' % cb

def _repr_info(self):
# Private method, do not rely on its existence.
Copy link
Member

Choose a reason for hiding this comment

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

This and the private methods below can also be given a __ prefix right?

Copy link
Member Author

Choose a reason for hiding this comment

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

It's a bit more complicated. It's "private" in a sense that nobody outside of asyncio shouldn't rely on it. In asyncio, it's overloaded in Task, and in one other place--something that we can address when/if we decide to rewrite Future (and maybe Task) in C.

Copy link
Member

Choose a reason for hiding this comment

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

Oh, yeah. This is what we call "protected" -- subclasses can use/override. So just update the comment (presumably also for the others?).

Copy link
Member Author

Choose a reason for hiding this comment

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

Oh, yeah. This is what we call "protected" -- subclasses can use/override

Yeah, but I don't want for non-asyncio subclasses to rely on this method. "protected" means (at least in c++/java/etc) that it's OK for subclasses to override and/or use. Maybe, instead of "private" I should just put "do not use outside of asyncio" there?

Copy link
Member

Choose a reason for hiding this comment

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

Oh, sounds good.

@1st1
Copy link
Member Author

1st1 commented Nov 16, 2015

Ping me when you want me to have another look. (GitHub's PR code review confuses me because it's so different from the tools I've been using for 10 years.)

I've just pushed this commit that should address your comments: 16851f7

If it looks good, I'll squash all three commits in one and commit the diff by hand.

@1st1
Copy link
Member Author

1st1 commented Nov 16, 2015

Another commit -- 1st1@f63a339. I've fixed the terminology, and also added this comment to Task._step and Task._wakeup

@1st1
Copy link
Member Author

1st1 commented Nov 16, 2015

BTW, Future._loop is used quite frequently in tests and in asyncio code. Should I add Future.get_loop(), or we can do it later?

@gvanrossum
Copy link
Member

Sorry for jerking you around, but looking at this version I think I would like to go back to single underscores. __private is just too much of a pain to deal with in the debugger. And I don't think the comments about not using these things outside asyncio are useful.

Also, what is the purpose of this PR again? Why can't your libuv Future class define _copy_state() and _set_result_unless_cancelled()?

@gvanrossum
Copy link
Member

I think you've used up your review quota for the day. :-(

On Mon, Nov 16, 2015 at 2:33 PM, Yury Selivanov notifications@github.com
wrote:

BTW, Future._loop is used quite frequently in tests and in asyncio code.
Should I add Future.get_loop(), or we can do it later?


Reply to this email directly or view it on GitHub
#292 (comment).

--Guido van Rossum (python.org/~guido)

@1st1
Copy link
Member Author

1st1 commented Nov 16, 2015

Also, what is the purpose of this PR again? Why can't your libuv Future class define _copy_state() and _set_result_unless_cancelled()?

I don't want to reimplement them. There is no need to those methods to be a part of the Future API. I hope that we'll accelerate Futures and Tasks in 3.5.x, and I want it to be as painless as possible.

@gvanrossum
Copy link
Member

gvanrossum commented Nov 16, 2015 via email

@1st1
Copy link
Member Author

1st1 commented Nov 16, 2015

Please describe your proposed strategy in more detail. What's going to be
in the accelerator module, what remains in Python, and what's going to be
in the libuv-specific module?

It would be great if we can merge this PR before 3.5.1, so that I can implement the Future in C without implementing not strictly necessary _copy_state() and _set_result_unless_cancelled(). The less C code I have, the easier it would be to thoroughly review and test it. There is no real reason for those methods to be defined in the Future class.

Sometime after 3.5.1, I plan to have a stable C Future implementation as part of the uvloop project. To make things simpler, I hope that we'll be able to integrate that implementation directly into asyncio for everybody's benefit. Ideally, futures.py can become something like this:

try:
    from ._futures import Future
except ImportError:
    class Future:
        ...

def _copy_future_state(fut, other_fut):
    ...

def _set_result_unless_cancelled(fut, result):
    ...

def _chain_future(source, destination):
    ...

# etc

I still have to play with implementing asyncio.Task in C. If it gives another visible performance boost, we might want to do that too. Or we can simply derive asyncio.Task from Future implemented in C. But this is something quite remote to plan for right now.

@gvanrossum
Copy link
Member

gvanrossum commented Nov 16, 2015 via email

@1st1
Copy link
Member Author

1st1 commented Nov 16, 2015

Well it all sound way too rushed just so you can show off some benchmark
numbers.

Benchmark numbers are great, but the reason why I'm investing a ton of time in asyncio is because we're building a database (based on PostgreSQL) that's built with it. Python allows us to iterate faster. I'm trying to improve things where it's possible, and Future object is one of the core building blocks.

Sure, the changes are very minor and very unlikely to break
anything, but I've lost confidence that this is the end.

I understand. Things that I try to fix/improve are only visible when you're trying to implement a compatible loop/interfaces from the outside of asyncio (most of my recent PR were related to that).

E.g. if you're so
keen on having the minimal amount of C code, wouldn't you want to avoid
having to write _repr_info() and _format_callbacks() in C too?

Those are only used (and usable) in Future.__repr__. Right now, I'm not even implementing __repr__. Same thing about _schedule_callbacks -- there is little reason to call it for anybody. In contrast, helpers like _copy_future_state or _set_result_unless_cancelled can be handy, and thus may be used by someone, therefore I think it's better to keep those things separate.

@gvanrossum
Copy link
Member

gvanrossum commented Nov 17, 2015 via email

1st1 added a commit that referenced this pull request Nov 17, 2015
Makes Future._set_result_unless_cancelled and Future._copy_state
standalone functions.
@1st1
Copy link
Member Author

1st1 commented Nov 17, 2015

Well, but an acceptable C Future should have a compatible __repr__ (or at
least one providing the same level of insight and details).

Absolutely.

Anyway, go ahead and commit the refactor of _copy_state() and
_set_result_unless_cancelled(), but I'm still skeptical about the road
that lies ahead. ;-)

Merged (without "private" comments).

@1st1 1st1 closed this Nov 17, 2015
@gvanrossum
Copy link
Member

Thanks for your understanding! And good luck with libuv -- it sounds really
cool (and it was one of the things PEP 3156 explicitly wanted to encourage).

On Tue, Nov 17, 2015 at 9:15 AM, Yury Selivanov notifications@github.com
wrote:

Well, but an acceptable C Future should have a compatible repr (or at
least one providing the same level of insight and details).

Absolutely.

Anyway, go ahead and commit the refactor of _copy_state() and
_set_result_unless_cancelled(), but I'm still skeptical about the road
that lies ahead. ;-)

Merged (without "private" comments).


Reply to this email directly or view it on GitHub
#292 (comment).

--Guido van Rossum (python.org/~guido)

akheron pushed a commit to akheron/cpython that referenced this pull request Nov 18, 2015
See python/asyncio#292 for details.

--HG--
branch : 3.4
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants