> Does that sound good enough to dismiss the problem?

Sure, tangibly related issues with other implementations from a discussion in 
the 00’s doesn’t seem like a fantastic argument, especially given that we use 
this exact pattern already in the stdlib without issue: 
https://github.com/python/cpython/blob/master/Lib/functools.py#L1200

> they waste time and maybe deadlock every 10000 startups for no benefit 
> whatsoever. Why is that acceptable for a general purpose function?

Acquiring a lock once (or even a couple of times when contested) in order to 
make a general purpose function work in single and multi threaded contexts does 
seem acceptable to me. There would be no deadlocks (assuming an RLock is used 
instead) nor any real perceivable performance issue. 

Basically, in the grand scheme of things some single threaded code acquiring a 
lock once is not really important especially when it’s more performant in the 
general case. And clearly the current use of this pattern in the stdlib means 
others have come to the same conclusion.

> On 2 May 2020, at 06:45, Andrew Barnert <abarn...@yahoo.com> wrote:
> 
> On May 1, 2020, at 09:51, Tom Forbes <t...@tomforb.es> wrote:
>> 
>>> You’ve written an exactly equIvalent to the double-checked locking for 
>>> singletons examples that broke Java 1.4 and C++03 and led to us having once 
>>> functions in the first place.
>>> … but what about on Jython, or PyPy-STM, or a future GIL-less Python?
>> 
>> While I truly do appreciate your feedback on this idea, I’m really not clear 
>> on your line of reasoning here. What specifically do you propose would be 
>> the issue with the *Python* implementation? Are you proposing that under 
>> some Python implementations `cache = func()` could be… the result of half a 
>> function call? I could buy an issue with some implementations meaning that 
>> `cache` still appears as `sentinel` in specific situations, but I feel that 
>> would constitute a pretty obvious bug in the implementation that would 
>> impact a _lot_ of other multithreaded code rather than a glaring issue with 
>> this snippet. Both the issues you’ve referenced valid, but also are rather 
>> specific to the languages that they affect. I don’t believe they apply to 
>> Python.
> 
> But the issues really aren’t specific to C++ and Java. The only reason C#, 
> Swift, Go, etc. don’t have the same problem is that their memory models were 
> designed from the start to provide a way to do this correctly. Python was 
> not. There was an attempt to define a memory model in the 00’s (PEP 583), but 
> it was withdrawn.
> 
> According to the discussion around that PEP about when you can see 
> uninitialized variables (not exactly the same issue, but closely related), 
> Jython is safe when they’re globals or instance attributes and you haven’t 
> replaced the module or object dict, but otherwise probably not; IronPython is 
> probably safe in the same cases and more but nobody’s actually sure. Does 
> that sound good enough to dismiss the problem?
> 
>> I still think the point stands. With your two-separate-decorators approach 
>> you’re paying it on every call. As a general purpose `call_once()` 
>> implementation I think the snippet works well, but obviously if you have 
>> some very specific use-case where it’s not appropriate - well then you are 
>> probably able to write a very specific and suitable decorator.
> 
> Being willing to trade safety or portability for speed is sometimes a good 
> tradeoff, but that’s the special use case, not the other way around. People 
> who don’t know exactly what they need should get something safe and portable.
> 
> Plus, there’s still the huge issue with single-threaded programs. It’s not 
> like multi-threaded programs are ubiquitous in Python but, e.g., asyncio is 
> some rare niche thing that the stdlib doesn’t have to worry about. A bunch of 
> coroutines using a once function needs either nothing, or a coro lock; if you 
> build a threading lock into the function, they waste time and maybe deadlock 
> every 10000 startups for no benefit whatsoever. Why is that acceptable for a 
> general purpose function?
> 
> 
_______________________________________________
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/XSBKP2XVGT2WLS66DTI7LVI47UZFFXI2/
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to