<div dir="ltr"><div>I have read the discussion and I'm sure that use structure as Py_tss_t instead of platform-specific data type. Just as Steve said that Py_tss_t should be genuinely treated as an opaque type, the key state checking should provide macros or inline functions with name like PyThread_tss_is_created. Well, I'd resolve the specification a bit more :)<br><br>If PyThread_tss_create is called with the created key, it is no-op but which the function should succeed or fail? In my opinion, It is better to return a failure because it is a high possibility that the code is incorrect for multiple callings of PyThread_tss_create for One key.<br><br>In this opinion PyThread_tss_is_created should return a value as follows:<br>(A) False while from after defining with Py_tss_NEED_INIT to before calling PyThread_tss_create<br>(B) True after calling PyThread_tss_create succeeded<br>(C) Unchanging before and after calling PyThread_tss_create failed<br>(D) False after calling PyThread_tss_delete regardless of timing<br>(E) For other functions, the return value of PyThread_tss_is_created does not change before and after calling<br><br>I think that it is better to write a test about the state of the Py_tss_t.<br><br>Kind regards,<br></div>Masayuki<br><div class="gmail_extra"><br><div class="gmail_quote">2016-12-31 2:38 GMT+09:00 Erik Bray <span dir="ltr"><<a href="mailto:erik.m.bray@gmail.com" target="_blank">erik.m.bray@gmail.com</a>></span>:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><span class="">On Fri, Dec 30, 2016 at 5:05 PM, Nick Coghlan <<a href="mailto:ncoghlan@gmail.com">ncoghlan@gmail.com</a>> wrote:<br>
> On 29 December 2016 at 22:12, Erik Bray <<a href="mailto:erik.m.bray@gmail.com">erik.m.bray@gmail.com</a>> wrote:<br>
>><br>
>> 1) CPython's TLS: Defines -1 as an uninitialized key (by fact of the<br>
>> implementation--that the keys are integers starting from zero)<br>
>> 2) pthreads: Does not definite an uninitialized default value for<br>
>> keys, for reasons described at [1] under "Non-Idempotent Data Key<br>
>> Creation".  I understand their reasoning, though I can't claim to know<br>
>> specifically what they mean when they say that some implementations<br>
>> would require the mutual-exclusion to be performed on<br>
>> pthread_getspecific() as well.  I don't know that it applies here.<br>
><br>
><br>
> That section is a little weird, as they describe two requests (one for a<br>
> known-NULL default value, the other for implicit synchronisation of key<br>
> creation to prevent race conditions), and only provide the justification for<br>
> rejecting one of them (the second one).<br>
<br>
</span>Right, that is confusing to me as well. I'm guessing the reason for<br>
rejecting the first is in part a way to force us to recognize the<br>
second issue.<br>
<span class=""><br>
> If I've understood correctly, the situation they're worried about there is<br>
> that pthread_key_create() has to be called at least once-per-process, but<br>
> must be called before *any* call to pthread_getspecific or<br>
> pthread_setspecific for a given key. If you do "implicit init" rather than<br>
> requiring the use of an explicit mechanism like pthread_once (or our own<br>
> Py_Initialize and module import locks), then you may take a small<br>
> performance hit as either *every* thread then has to call<br>
> pthread_key_create() to ensure the key exists before using it, or else<br>
> pthread_getspecific() and pthread_setspecific() have to become potentially<br>
> blocking calls. Neither of those is desirable, so it makes sense to leave<br>
> that part of the problem to the API client.<br>
><br>
> In our case, we don't want the implicit synchronisation, we just want the<br>
> known-NULL default value so the "Is it already set?" check can be moved<br>
> inside the library function.<br>
<br>
</span>Okay, we're on the same page here then.  I just wanted to make sure<br>
there wasn't anything else I was missing in Python's case.<br>
<div><div class="h5"><br>
>> 3) windows: The return value of TlsAlloc() is a DWORD (unsigned int)<br>
>> and [2] states that its value should be opaque.<br>
>><br>
>> So in principle we can cover all cases with an opaque struct that<br>
>> contains, as its first member, an is_initialized flag.  The tricky<br>
>> part is how to initialize the rest of the struct (containing the<br>
>> underlying implementation-specific key).  For 1) and 3) it doesn't<br>
>> matter--it can just be zero.  For 2) it's trickier because there's no<br>
>> defined constant value to initialize a pthread_key_t to.<br>
>><br>
>> Per Nick's suggestion this can be worked around by relying on C99's<br>
>> initialization semantics. Per [3] section 6.7.8, clause 21:<br>
>><br>
>> """<br>
>> If there are fewer initializers in a brace-enclosed list than there<br>
>> are elements or members of an aggregate, or fewer characters in a<br>
>> string literal used to initialize an array of known size than there<br>
>> are elements in the array, the remainder of the aggregate shall be<br>
>> initialized implicitly the same as objects that have static storage<br>
>> duration.<br>
>> """<br>
>><br>
>> How objects with static storage are initialized is described in the<br>
>> previous page under clause 10, but in practice it boils down to what<br>
>> you would expect: Everything is initialized to zero, including nested<br>
>> structs and arrays.<br>
>><br>
>> So as long as we can use this feature of C99 then I think that's the<br>
>> best approach.<br>
><br>
><br>
><br>
> I checked PEP 7 to see exactly which features we've added to the approved C<br>
> dialect, and designated initialisers are already on the list:<br>
> <a href="https://gcc.gnu.org/onlinedocs/gcc/Designated-Inits.html" rel="noreferrer" target="_blank">https://gcc.gnu.org/<wbr>onlinedocs/gcc/Designated-<wbr>Inits.html</a><br>
><br>
> So I believe that would allow the initializer to be declared as something<br>
> like:<br>
><br>
>     #define Py_tss_NEEDS_INIT {.is_initialized = false}<br>
<br>
</div></div>Great!  One could argue about whether or not the designated<br>
initializer syntax also incorporates omitted fields, but it would seem<br>
strange to insist that it doesn't.<br>
<br>
Have a happy new year,<br>
<br>
Erik<br>
</blockquote></div><br></div></div>