static ERL_NIF_TERM cqueue_withdraw(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { ERL_NIF_TERM result; cqueue_handle* handle = NULL; int list_id = get_list_id(enif_thread_self()); if (list_id == -1) return enif_make_badarg(env); if (enif_get_resource(env, argv[0], cqueue_RESOURCE, (void**)&handle) == 0) { return enif_make_badarg(env); } result = handle->queue->Withdraw(env, list_id); return result; }
static ERL_NIF_TERM cqueue_deposit(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { cqueue_handle* handle = NULL; int list_id = get_list_id(enif_thread_self()); ErlNifPid pid; if (list_id == -1) return enif_make_badarg(env); if (enif_get_resource(env, argv[0], cqueue_RESOURCE, (void**)&handle) == 0) { return enif_make_badarg(env); } if (enif_get_local_pid(env, argv[1], &pid) == 0) { return enif_make_badarg(env); } handle->queue->Deposit(pid, list_id); return enif_make_atom(env, "ok"); }
static ERL_NIF_TERM cqueue_register(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { ErlNifTid thread_id = enif_thread_self(); unsigned int i = 0; enif_rwlock_rwlock(lookup_lock); for (i = 0; i < schedulers; ++i) { if (scheduler_ids[i] == thread_id) { printf("Scheduler (%p) already registered.\r\n", thread_id); break; } else if (scheduler_ids[i] == NULL) { printf("Registering scheduler (%p) with index %d\r\n", thread_id, i); scheduler_ids[i] = thread_id; break; } } enif_rwlock_rwunlock(lookup_lock); if (i == schedulers) { return enif_make_badarg(env); } else { return enif_make_atom(env, "ok"); } }
static ERL_NIF_TERM get(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) { ERL_NIF_TERM atom; ErlNifBinary kbin; struct cache *c; struct cache_node *n; struct cache_incr_node *in; struct timespec now; int incrqs, hashv, bkt; ERL_NIF_TERM ret; ErlNifTid tid; if (!enif_is_atom(env, argv[0])) return enif_make_badarg(env); atom = argv[0]; if (!enif_inspect_binary(env, argv[1], &kbin)) return enif_make_badarg(env); if ((c = get_cache(atom))) { enif_rwlock_rlock(c->lookup_lock); HASH_FIND(hh, c->lookup, kbin.data, kbin.size, n); if (!n) { enif_rwlock_runlock(c->lookup_lock); __sync_add_and_fetch(&c->miss, 1); enif_consume_timeslice(env, 10); return enif_make_atom(env, "notfound"); } if (n->expiry.tv_sec != 0) { clock_now(&now); if (n->expiry.tv_sec < now.tv_sec) { enif_rwlock_runlock(c->lookup_lock); __sync_add_and_fetch(&c->miss, 1); enif_consume_timeslice(env, 10); return enif_make_atom(env, "notfound"); } } in = enif_alloc(sizeof(*in)); memset(in, 0, sizeof(*in)); in->node = n; __sync_add_and_fetch(&c->hit, 1); tid = enif_thread_self(); HASH_SFH(&tid, sizeof(ErlNifTid), N_INCR_BKT, hashv, bkt); enif_mutex_lock(c->incr_lock[bkt]); TAILQ_INSERT_TAIL(&(c->incr_head[bkt]), in, entry); enif_mutex_unlock(c->incr_lock[bkt]); incrqs = __sync_add_and_fetch(&(c->incr_count), 1); ret = enif_make_resource_binary(env, n->val, n->val, n->vsize); enif_rwlock_runlock(c->lookup_lock); if (incrqs > 1024) enif_cond_broadcast(c->check_cond); enif_consume_timeslice(env, 20); return ret; } return enif_make_atom(env, "notfound"); }
static unsigned long id_function(void) { return (unsigned long) enif_thread_self(); }