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/SSBEI5BD3HNONNSH5RGGPYKZ2LY3DEXR/
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to