summaryrefslogtreecommitdiffstats
path: root/src/jv_dtoa_tsd.c
blob: 85d5beb45ea9bc5b9a2eb768af45dc698c7534d8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>

#include "jv_dtoa_tsd.h"
#include "jv_dtoa.h"
#include "jv_alloc.h"


static pthread_key_t dtoa_ctx_key;
static pthread_once_t dtoa_ctx_once = PTHREAD_ONCE_INIT;

static void tsd_dtoa_ctx_dtor(void *ctx) {
  if (ctx) {
    jvp_dtoa_context_free((struct dtoa_context *)ctx);
    jv_mem_free(ctx);
  }
}

static void tsd_dtoa_ctx_fini() {
  struct dtoa_context *ctx = pthread_getspecific(dtoa_ctx_key);
  tsd_dtoa_ctx_dtor(ctx);
  pthread_setspecific(dtoa_ctx_key, NULL);
}

static void tsd_dtoa_ctx_init() {
  if (pthread_key_create(&dtoa_ctx_key, tsd_dtoa_ctx_dtor) != 0) {
    fprintf(stderr, "error: cannot create thread specific key");
    abort();
  }
  atexit(tsd_dtoa_ctx_fini);
}

inline struct dtoa_context *tsd_dtoa_context_get() {
  pthread_once(&dtoa_ctx_once, tsd_dtoa_ctx_init); // cannot fail
  struct dtoa_context *ctx = (struct dtoa_context*)pthread_getspecific(dtoa_ctx_key);
  if (!ctx) {
    ctx = malloc(sizeof(struct dtoa_context));
    jvp_dtoa_context_init(ctx);
    if (pthread_setspecific(dtoa_ctx_key, ctx) != 0) {
      fprintf(stderr, "error: cannot set thread specific data");
      abort();
    }
  }
  return ctx;
}