|  | // This file is part of Jiffy released under the MIT license. | 
|  | // See the LICENSE file for more information. | 
|  |  | 
|  | #include "jiffy.h" | 
|  | #include <stdio.h> | 
|  |  | 
|  | 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_iter) != 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(ErlNifEnv* env, size_t* used, size_t bytes_per_red) | 
|  | { | 
|  | #if(ERL_NIF_MAJOR_VERSION >= 2 && ERL_NIF_MINOR_VERSION >= 4) | 
|  |  | 
|  | if(((*used) / bytes_per_red) >= 20) { | 
|  | *used = 0; | 
|  | return enif_consume_timeslice(env, 1); | 
|  | } | 
|  |  | 
|  | return 0; | 
|  |  | 
|  | #else | 
|  |  | 
|  | return ((*used) / bytes_per_red) >= DEFAULT_ERLANG_REDUCTION_COUNT; | 
|  |  | 
|  | #endif | 
|  | } |