<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On 29 December 2016 at 22:12, Erik Bray <span dir="ltr"><<a href="mailto:erik.m.bray@gmail.com" target="_blank">erik.m.bray@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">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></blockquote><div><br></div><div>That section is a little weird, as they describe two requests (one for a known-NULL default value, the other for implicit synchronisation of key creation to prevent race conditions), and only provide the justification for rejecting one of them (the second one). <br></div><div><br></div><div>If I've understood correctly, the situation they're worried about there is that pthread_key_create() has to be called at least once-per-process, but must be called before *any* call to pthread_getspecific or pthread_setspecific for a given key. If you do "implicit init" rather than requiring the use of an explicit mechanism like pthread_once (or our own Py_Initialize and module import locks), then you may take a small performance hit as either *every* thread then has to call pthread_key_create() to ensure the key exists before using it, or else pthread_getspecific() and pthread_setspecific() have to become potentially blocking calls. Neither of those is desirable, so it makes sense to leave that part of the problem to the API client.<br><br></div><div>In our case, we don't want the implicit synchronisation, we just want the known-NULL default value so the "Is it already set?" check can be moved inside the library function.<br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
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></blockquote><br><div><br></div><div>I 
checked PEP 7 to see exactly which features we've added to the approved C
 dialect, and designated initialisers are already on the list: 
<a href="https://gcc.gnu.org/onlinedocs/gcc/Designated-Inits.html">https://gcc.gnu.org/onlinedocs/gcc/Designated-Inits.html</a><br><br></div><div>So I believe that would allow the initializer to be declared as something like:<br><br></div><div>    #define Py_tss_NEEDS_INIT {.is_initialized = false}<br></div><div><br></div>Cheers,<br><div class="gmail_extra">Nick.<br></div><br clear="all"></div>-- <br><div class="gmail_signature">Nick Coghlan   |   <a href="mailto:ncoghlan@gmail.com" target="_blank">ncoghlan@gmail.com</a>   |   Brisbane, Australia</div>
</div></div>