#include "enlfq.h" #include "enlfq_nif.h" #include "nif_utils.h" #include "concurrentqueue.h" struct q_item { ErlNifEnv *env; ERL_NIF_TERM term; }; struct squeue { moodycamel::ConcurrentQueue *queue; }; void nif_enlfq_free(ErlNifEnv *, void *obj) { squeue *inst = static_cast(obj); if (inst != nullptr) { q_item item; while (inst->queue->try_dequeue(item)) { enif_free_env(item.env); } delete inst->queue; } } ERL_NIF_TERM nif_enlfq_new(ErlNifEnv *env, int, const ERL_NIF_TERM *) { shared_data *data = static_cast(enif_priv_data(env)); squeue *qinst = static_cast(enif_alloc_resource(data->resQueueInstance, sizeof(squeue))); qinst->queue = new moodycamel::ConcurrentQueue; if (qinst == NULL) return make_error(env, "enif_alloc_resource failed"); ERL_NIF_TERM term = enif_make_resource(env, qinst); enif_release_resource(qinst); return enif_make_tuple2(env, ATOMS.atomOk, term); } ERL_NIF_TERM nif_enlfq_push(ErlNifEnv *env, int, const ERL_NIF_TERM argv[]) { shared_data *data = static_cast(enif_priv_data(env)); squeue *inst; if (!enif_get_resource(env, argv[0], data->resQueueInstance, (void **) &inst)) { return enif_make_badarg(env); } q_item item; item.env = enif_alloc_env(); item.term = enif_make_copy(item.env, argv[1]); inst->queue->enqueue(item); return ATOMS.atomTrue; } ERL_NIF_TERM nif_enlfq_pop(ErlNifEnv *env, int, const ERL_NIF_TERM argv[]) { shared_data *data = static_cast(enif_priv_data(env)); squeue *inst = NULL; if (!enif_get_resource(env, argv[0], data->resQueueInstance, (void **) &inst)) { return enif_make_badarg(env); } ERL_NIF_TERM term; q_item item; if (inst->queue->try_dequeue(item)) { term = enif_make_copy(env, item.term); enif_free_env(item.env); return enif_make_tuple2(env, ATOMS.atomOk, term); } else { return ATOMS.atomEmpty; } }