On Thu, May 23, 2019 at 12:51 PM Jeff King <peff@xxxxxxxx> wrote: > For fun, here's a constant-time zero-allocation implementation that I > came up with. It passes t0211 with NO_PTHREADS, but I didn't test it > beyond that. > > diff --git a/thread-utils.h b/thread-utils.h > index 4961487ed9..f466215742 100644 > --- a/thread-utils.h > +++ b/thread-utils.h > @@ -18,7 +18,7 @@ > #define pthread_t int > #define pthread_mutex_t int > #define pthread_cond_t int > -#define pthread_key_t int > +#define pthread_key_t git_pthread_key_t > > #define pthread_mutex_init(mutex, attr) dummy_pthread_init(mutex) > #define pthread_mutex_lock(mutex) > @@ -31,16 +31,49 @@ > #define pthread_cond_broadcast(cond) > #define pthread_cond_destroy(cond) > > -#define pthread_key_create(key, attr) dummy_pthread_init(key) > -#define pthread_key_delete(key) > +#define pthread_key_create(key, destroy) git_pthread_key_create(key, destroy) > +#define pthread_key_delete(key) git_pthread_key_delete(key) > > #define pthread_create(thread, attr, fn, data) \ > dummy_pthread_create(thread, attr, fn, data) > #define pthread_join(thread, retval) \ > dummy_pthread_join(thread, retval) > > -#define pthread_setspecific(key, data) > -#define pthread_getspecific(key) NULL > +#define pthread_setspecific(key, data) git_pthread_setspecific(key, data) > +#define pthread_getspecific(key) git_pthread_getspecific(key) > + > +typedef struct { > + void *data; > + /* extra indirection because setspecific is passed key by value */ > + void **vdata; Ha! I was thinking a separate key->value mapping which is complicated in C. But this works pretty well for a single thread, and it even supports multiple keys. > +} git_pthread_key_t; > + > +static inline int git_pthread_key_create(git_pthread_key_t *key, > + void (*destroy)(void *)) > +{ > + key->data = NULL; > + key->vdata = &key->data; > + /* We don't use this; alternatively we could all via atexit(). */ > + if (destroy) > + BUG("NO_PTHREADS does not support pthread key destructors"); > + return 0; > +} > + > +static inline int git_pthread_key_delete(git_pthread_key_t key) > +{ > + /* noop */ > + return 0; > +} > + > +static inline void git_pthread_setspecific(git_pthread_key_t key, void *data) > +{ > + *(key.vdata) = data; > +} > + > +static inline void *git_pthread_getspecific(git_pthread_key_t key) > +{ > + return key.data; > +} > > int dummy_pthread_create(pthread_t *pthread, const void *attr, > void *(*fn)(void *), void *data); -- Duy