// This file is part of Jiffy released under the MIT license. // See the LICENSE file for more information. #include "jiffy.h" #include ERL_NIF_TERM make_atom(ErlNifEnv* env, const char* name) { ERL_NIF_TERM ret; if(enif_make_existing_atom(env, name, &ret, ERL_NIF_LATIN1)) { return ret; } return enif_make_atom(env, name); } ERL_NIF_TERM make_ok(jiffy_st* st, ErlNifEnv* env, ERL_NIF_TERM value) { return enif_make_tuple2(env, st->atom_ok, value); } ERL_NIF_TERM make_error(jiffy_st* st, ErlNifEnv* env, const char* error) { return enif_make_tuple2(env, st->atom_error, make_atom(env, error)); } ERL_NIF_TERM make_obj_error(jiffy_st* st, ErlNifEnv* env, const char* error, ERL_NIF_TERM obj) { ERL_NIF_TERM reason = enif_make_tuple2(env, make_atom(env, error), obj); return enif_make_tuple2(env, st->atom_error, reason); } int get_bytes_per_iter(ErlNifEnv* env, ERL_NIF_TERM val, size_t* bpi) { jiffy_st* st = (jiffy_st*) enif_priv_data(env); const ERL_NIF_TERM* tuple; int arity; unsigned int bytes; if(!enif_get_tuple(env, val, &arity, &tuple)) { return 0; } if(arity != 2) { return 0; } if(enif_compare(tuple[0], st->atom_bytes_per_iter) != 0) { return 0; } if(!enif_get_uint(env, tuple[1], &bytes)) { return 0; } // Calculate the number of bytes per reduction *bpi = (size_t) (bytes / DEFAULT_ERLANG_REDUCTION_COUNT); return 1; } int get_bytes_per_red(ErlNifEnv* env, ERL_NIF_TERM val, size_t* bpi) { jiffy_st* st = (jiffy_st*) enif_priv_data(env); const ERL_NIF_TERM* tuple; int arity; unsigned int bytes; if(!enif_get_tuple(env, val, &arity, &tuple)) { return 0; } if(arity != 2) { return 0; } if(enif_compare(tuple[0], st->atom_bytes_per_red) != 0) { return 0; } if(!enif_get_uint(env, tuple[1], &bytes)) { return 0; } *bpi = (size_t) bytes; return 1; } int get_null_term(ErlNifEnv* env, ERL_NIF_TERM val, ERL_NIF_TERM *null_term) { jiffy_st* st = (jiffy_st*) enif_priv_data(env); const ERL_NIF_TERM* tuple; int arity; if(!enif_get_tuple(env, val, &arity, &tuple)) { return 0; } if(arity != 2) { return 0; } if(enif_compare(tuple[0], st->atom_null_term) != 0) { return 0; } if(!enif_is_atom(env, tuple[1])) { return 0; } *null_term = tuple[1]; return 1; } int should_yield(size_t used, size_t bytes_per_red) { return (used / bytes_per_red) >= DEFAULT_ERLANG_REDUCTION_COUNT; } void bump_used_reds(ErlNifEnv* env, size_t used, size_t bytes_per_red) { #if CONSUME_TIMESLICE_PRESENT size_t reds_used; size_t pct_used; reds_used = used / bytes_per_red; pct_used = 100 * reds_used / DEFAULT_ERLANG_REDUCTION_COUNT; if(pct_used > 0) { if(pct_used > 100) { pct_used = 100; } enif_consume_timeslice(env, pct_used); } #endif (void) env; (void) used; (void) bytes_per_red; }