summaryrefslogtreecommitdiff
path: root/c/misc_thread_posix.h
diff options
context:
space:
mode:
Diffstat (limited to 'c/misc_thread_posix.h')
-rw-r--r--c/misc_thread_posix.h49
1 files changed, 49 insertions, 0 deletions
diff --git a/c/misc_thread_posix.h b/c/misc_thread_posix.h
new file mode 100644
index 0000000..bcc0177
--- /dev/null
+++ b/c/misc_thread_posix.h
@@ -0,0 +1,49 @@
+/*
+ Logic for a better replacement of PyGILState_Ensure().
+
+ This version is ready to handle the case of a non-Python-started
+ thread in which we do a large number of calls to CFFI callbacks. If
+ we were to rely on PyGILState_Ensure() for that, we would constantly
+ be creating and destroying PyThreadStates---it is slow, and
+ PyThreadState_Delete() will actually walk the list of all thread
+ states, making it O(n). :-(
+
+ This version only creates one PyThreadState object the first time we
+ see a given thread, and keep it alive until the thread is really
+ shut down, using a destructor on the tls key.
+*/
+
+#include <pthread.h>
+#include "misc_thread_common.h"
+
+
+static pthread_key_t cffi_tls_key;
+
+static void init_cffi_tls(void)
+{
+ if (pthread_key_create(&cffi_tls_key, &cffi_thread_shutdown) != 0)
+ PyErr_SetString(PyExc_OSError, "pthread_key_create() failed");
+}
+
+static struct cffi_tls_s *_make_cffi_tls(void)
+{
+ void *p = calloc(1, sizeof(struct cffi_tls_s));
+ if (p == NULL)
+ return NULL;
+ if (pthread_setspecific(cffi_tls_key, p) != 0) {
+ free(p);
+ return NULL;
+ }
+ return p;
+}
+
+static struct cffi_tls_s *get_cffi_tls(void)
+{
+ void *p = pthread_getspecific(cffi_tls_key);
+ if (p == NULL)
+ p = _make_cffi_tls();
+ return (struct cffi_tls_s *)p;
+}
+
+#define save_errno save_errno_only
+#define restore_errno restore_errno_only