aboutsummaryrefslogtreecommitdiffstats
path: root/c_src/nif_helpers.c
diff options
context:
space:
mode:
Diffstat (limited to 'c_src/nif_helpers.c')
-rw-r--r--c_src/nif_helpers.c195
1 files changed, 0 insertions, 195 deletions
diff --git a/c_src/nif_helpers.c b/c_src/nif_helpers.c
deleted file mode 100644
index f29d76d..0000000
--- a/c_src/nif_helpers.c
+++ /dev/null
@@ -1,195 +0,0 @@
-// Copyright (c) 2014-2015, Loïc Hoguin <[email protected]>
-//
-// Permission to use, copy, modify, and/or distribute this software for any
-// purpose with or without fee is hereby granted, provided that the above
-// copyright notice and this permission notice appear in all copies.
-//
-// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
-// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
-// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
-#include "nif_helpers.h"
-#include <sys/queue.h>
-#include <stdarg.h>
-
-extern ERL_NIF_TERM atom_ok;
-extern ERL_NIF_TERM atom__nif_thread_ret_;
-
-typedef struct nif_thread_message {
- TAILQ_ENTRY(nif_thread_message) next_entry;
-
- ErlNifPid* from_pid;
- void* function;
- nif_thread_arg* args;
-} nif_thread_message;
-
-typedef TAILQ_HEAD(nif_thread_mailbox, nif_thread_message) nif_thread_mailbox;
-
-typedef struct {
- ErlNifTid tid;
- ErlNifMutex* lock;
- ErlNifCond* cond;
- nif_thread_mailbox* mailbox;
-} nif_thread_state;
-
-// Message.
-
-static nif_thread_message* nif_thread_message_alloc(void* f, nif_thread_arg* args, ErlNifPid* pid)
-{
- nif_thread_message* msg = (nif_thread_message*)enif_alloc(sizeof(nif_thread_message));
-
- msg->from_pid = pid;
- msg->function = f;
- msg->args = args;
-
- return msg;
-}
-
-static void nif_thread_message_free(nif_thread_message* msg)
-{
- enif_free(msg->from_pid);
- enif_free(msg->args);
- enif_free(msg);
-}
-
-// Calls and casts.
-
-static ERL_NIF_TERM nif_thread_send(nif_thread_state* st, nif_thread_message* msg)
-{
- enif_mutex_lock(st->lock);
-
- TAILQ_INSERT_TAIL(st->mailbox, msg, next_entry);
-
- enif_cond_signal(st->cond);
- enif_mutex_unlock(st->lock);
-
- return atom_ok;
-}
-
-ERL_NIF_TERM nif_thread_cast(ErlNifEnv* env, void (*f)(nif_thread_arg*), int a, ...)
-{
- va_list ap;
- int i;
-
- nif_thread_arg* args = (nif_thread_arg*)enif_alloc(a * sizeof(nif_thread_arg));
-
- va_start(ap, a);
- for (i = 0; i < a; i++)
- args[i] = va_arg(ap, void*);
- va_end(ap);
-
- nif_thread_message* msg = nif_thread_message_alloc(f, args, NULL);
-
- return nif_thread_send((nif_thread_state*)enif_priv_data(env), msg);
-}
-
-ERL_NIF_TERM nif_thread_call(ErlNifEnv* env, ERL_NIF_TERM (*f)(ErlNifEnv*, nif_thread_arg*), int a, ...)
-{
- va_list ap;
- int i;
-
- nif_thread_arg* args = (nif_thread_arg*)enif_alloc(a * sizeof(nif_thread_arg));
-
- va_start(ap, a);
- for (i = 0; i < a; i++)
- args[i] = va_arg(ap, void*);
- va_end(ap);
-
- ErlNifPid* pid = (ErlNifPid*)enif_alloc(sizeof(ErlNifPid));
- nif_thread_message* msg = nif_thread_message_alloc((void*)f, args, enif_self(env, pid));
-
- return nif_thread_send((nif_thread_state*)enif_priv_data(env), msg);
-}
-
-// Main thread loop.
-
-static int nif_thread_receive(nif_thread_state* st, nif_thread_message** msg)
-{
- enif_mutex_lock(st->lock);
-
- while (TAILQ_EMPTY(st->mailbox))
- enif_cond_wait(st->cond, st->lock);
-
- *msg = TAILQ_FIRST(st->mailbox);
- TAILQ_REMOVE(st->mailbox, TAILQ_FIRST(st->mailbox), next_entry);
-
- enif_mutex_unlock(st->lock);
-
- if ((*msg)->function == NULL)
- return 0;
-
- return 1;
-}
-
-static void nif_thread_handle(ErlNifEnv* env, nif_thread_state* st, nif_thread_message* msg)
-{
- if (msg->from_pid == NULL) {
- void (*cast)(nif_thread_arg*) = msg->function;
- cast(msg->args);
- } else {
- ERL_NIF_TERM (*call)(ErlNifEnv*, nif_thread_arg*) = msg->function;
- ERL_NIF_TERM ret = call(env, msg->args);
-
- enif_send(NULL, msg->from_pid, env,
- enif_make_tuple2(env, atom__nif_thread_ret_, ret));
-
- enif_clear_env(env);
- }
-
- nif_thread_message_free(msg);
-}
-
-static void* nif_main_thread(void* obj)
-{
- ErlNifEnv* env = enif_alloc_env();
- nif_thread_state* st = (nif_thread_state*)obj;
- nif_thread_message* msg;
-
- while (nif_thread_receive(st, &msg))
- nif_thread_handle(env, st, msg);
-
- enif_free_env(env);
-
- return NULL;
-}
-
-// Main thread creation/destruction.
-
-void* nif_create_main_thread(char* name)
-{
- nif_thread_state* st = (nif_thread_state*)enif_alloc(sizeof(nif_thread_state));
-
- st->lock = enif_mutex_create("nif_thread_mailbox_lock");
- st->cond = enif_cond_create("nif_thread_mailbox_cond");
- st->mailbox = (nif_thread_mailbox*)enif_alloc(sizeof(nif_thread_mailbox));
- TAILQ_INIT(st->mailbox);
-
-#if defined(__APPLE__) && defined(__MACH__)
- // On OSX we identify ourselves as the main thread to ensure that
- // we are compatible with libraries that require it. For example
- // this is necessary with SDL2 in order to receive input events.
- erl_drv_steal_main_thread(name, &(st->tid), nif_main_thread, st, NULL);
-#else
- enif_thread_create(name, &(st->tid), nif_main_thread, st, NULL);
-#endif
-
- return (void*)st;
-}
-
-void nif_destroy_main_thread(void* void_st)
-{
- nif_thread_state* st = (nif_thread_state*)void_st;
- nif_thread_message* msg = nif_thread_message_alloc(NULL, NULL, NULL);
-
- nif_thread_send(st, msg);
- enif_thread_join(st->tid, NULL);
-
- enif_cond_destroy(st->cond);
- enif_mutex_destroy(st->lock);
- enif_free(st->mailbox);
- enif_free(st);
-}