Skip to content

Instantly share code, notes, and snippets.

@bucko909
Created December 18, 2015 13:47
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bucko909/a3b5099c74bf267e65db to your computer and use it in GitHub Desktop.
Save bucko909/a3b5099c74bf267e65db to your computer and use it in GitHub Desktop.
#include "erl_nif.h"
#include <stdio.h>
static int load(ErlNifEnv* env, void** priv, ERL_NIF_TERM load_info)
{
int *priv_int = enif_alloc(sizeof(int));
*priv = (void *)priv_int;
enif_get_int(env, load_info, priv_int);
printf("loaded %i %i\r\n", UNIQ, *priv_int);
return 0;
}
static int upgrade(ErlNifEnv* env, void** priv, void** old_priv, ERL_NIF_TERM load_info)
{
int *old_priv_int = *old_priv;
int *priv_int = enif_alloc(sizeof(int));
*priv = (void *)priv_int;
enif_get_int(env, load_info, priv_int);
printf("upgraded %i %i %i\r\n", UNIQ, *priv_int, *old_priv_int);
return 0;
}
static void unload(ErlNifEnv* env, void* priv)
{
int *priv_int = priv;
printf("unloaded %i %i\r\n", UNIQ, *priv_int);
return;
}
static ERL_NIF_TERM compile_uniq(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
return enif_make_int(env, UNIQ);
}
static ERL_NIF_TERM load_uniq(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
return enif_make_int(env, *((int *)enif_priv_data(env)));
}
static ErlNifFunc nif_funcs[] = {
{"compile_uniq", 0, compile_uniq},
{"load_uniq", 0, load_uniq}
};
ERL_NIF_INIT(enif_test_mod, nif_funcs, &load, NULL, &upgrade, &unload);
-module(enif_test).
-compile(export_all).
compile(I) ->
os:cmd("gcc -c -Wall -Werror -fpic -DUNIQ=" ++ integer_to_list(I) ++ " enif_test.c"),
os:cmd("gcc -shared -o enif_test.so enif_test.o").
eset(I) -> ets:insert(a, {a, I}).
test_reload() ->
ets:new(a, [public, named_table]),
compile(1),
eset(2),
{module, _} = code:load_file(enif_test_mod),
check(1, enif_test_mod:compile_uniq(), "nif compiled as expected"),
check(2, enif_test_mod:load_uniq(), "nif initialised as expected"),
compile(3),
check(1, enif_test_mod:compile_uniq(), "nif not unexpectedly reloaded"),
{module, _} = code:load_file(enif_test_mod),
check(3, enif_test_mod:compile_uniq(), "nif reloaded post compile properly"),
init:stop().
test_reload_post_delete() ->
ets:new(a, [public, named_table]),
compile(1),
eset(2),
{module, _} = code:load_file(enif_test_mod),
check(1, enif_test_mod:compile_uniq(), "nif compiled as expected"),
check(2, enif_test_mod:load_uniq(), "nif initialised as expected"),
compile(3),
check(1, enif_test_mod:compile_uniq(), "nif not unexpectedly reloaded"),
true = code:delete(enif_test_mod),
{module, _} = code:load_file(enif_test_mod),
check(3, enif_test_mod:compile_uniq(), "nif reloaded post compile properly"),
init:stop().
test_reload_post_purge() ->
ets:new(a, [public, named_table]),
compile(1),
eset(2),
{module, _} = code:load_file(enif_test_mod),
check(1, enif_test_mod:compile_uniq(), "nif compiled as expected"),
check(2, enif_test_mod:load_uniq(), "nif initialised as expected"),
compile(3),
check(1, enif_test_mod:compile_uniq(), "nif not unexpectedly reloaded"),
true = code:delete(enif_test_mod),
io:format("delete finished~n"),
true = code:soft_purge(enif_test_mod),
io:format("soft_purge finished~n"),
{module, _} = code:load_file(enif_test_mod),
check(3, enif_test_mod:compile_uniq(), "nif reloaded post compile properly"),
init:stop().
test_reload_post_reload_purge() ->
ets:new(a, [public, named_table]),
compile(1),
eset(2),
{module, _} = code:load_file(enif_test_mod),
check(1, enif_test_mod:compile_uniq(), "nif compiled as expected"),
check(2, enif_test_mod:load_uniq(), "nif initialised as expected"),
eset(3),
{module, _} = code:load_file(enif_test_mod),
check(3, enif_test_mod:load_uniq(), "nif reinitialised as expected"),
compile(4),
check(1, enif_test_mod:compile_uniq(), "nif not unexpectedly reloaded"),
true = code:soft_purge(enif_test_mod),
true = code:delete(enif_test_mod),
{module, _} = code:load_file(enif_test_mod),
check(4, enif_test_mod:compile_uniq(), "nif reloaded post compile properly"),
init:stop().
test_reload_post_reload_complete_purge() ->
ets:new(a, [public, named_table]),
compile(1),
eset(2),
{module, _} = code:load_file(enif_test_mod),
check(1, enif_test_mod:compile_uniq(), "nif compiled as expected"),
check(2, enif_test_mod:load_uniq(), "nif initialised as expected"),
eset(3),
{module, _} = code:load_file(enif_test_mod),
check(3, enif_test_mod:load_uniq(), "nif reinitialised as expected"),
compile(4),
check(1, enif_test_mod:compile_uniq(), "nif not unexpectedly reloaded"),
true = code:soft_purge(enif_test_mod),
io:format("soft_purge finished~n"),
true = code:delete(enif_test_mod),
io:format("delete finished~n"),
true = code:soft_purge(enif_test_mod),
io:format("soft_purge finished~n"),
{module, _} = code:load_file(enif_test_mod),
check(4, enif_test_mod:compile_uniq(), "nif reloaded post compile properly"),
init:stop().
check(N, N, M) ->
io:format(" CORRECT: ~s~n", [M]);
check(_, _, M) ->
io:format("INCORRECT: ~s~n", [M]).
-module(enif_test_mod).
-compile([export_all]).
-on_load(init/0).
init() ->
ok = erlang:load_nif("./enif_test", eget()).
eget() ->
[{a, I}] = ets:lookup(a, a), I.
compile_uniq() -> erlang:error(no_nif).
load_uniq() -> erlang:error(no_nif).
$ erlc enif_test.erl && erlc enif_test_mod.erl && for I in test_reload{,_post_{delete,purge,reload_{purge,complete_purge}}}; do echo $I:; echo; erl -noshell -s enif_test $I; echo; done
test_reload:
loaded 1 2
CORRECT: nif compiled as expected
CORRECT: nif initialised as expected
CORRECT: nif not unexpectedly reloaded
upgraded 1 2 2
INCORRECT: nif reloaded post compile properly
unloaded 1 2
unloaded 1 2
test_reload_post_delete:
loaded 1 2
CORRECT: nif compiled as expected
CORRECT: nif initialised as expected
CORRECT: nif not unexpectedly reloaded
upgraded 1 2 2
INCORRECT: nif reloaded post compile properly
unloaded 1 2
unloaded 1 2
test_reload_post_purge:
loaded 1 2
CORRECT: nif compiled as expected
CORRECT: nif initialised as expected
CORRECT: nif not unexpectedly reloaded
delete finished
unloaded 1 2
soft_purge finished
loaded 3 2
CORRECT: nif reloaded post compile properly
unloaded 3 2
test_reload_post_reload_purge:
loaded 1 2
CORRECT: nif compiled as expected
CORRECT: nif initialised as expected
upgraded 1 3 2
CORRECT: nif reinitialised as expected
CORRECT: nif not unexpectedly reloaded
unloaded 1 2
upgraded 1 3 3
INCORRECT: nif reloaded post compile properly
unloaded 1 3
unloaded 1 3
test_reload_post_reload_complete_purge:
loaded 1 2
CORRECT: nif compiled as expected
CORRECT: nif initialised as expected
upgraded 1 3 2
CORRECT: nif reinitialised as expected
CORRECT: nif not unexpectedly reloaded
unloaded 1 2
soft_purge finished
delete finished
unloaded 1 3
soft_purge finished
loaded 4 3
CORRECT: nif reloaded post compile properly
unloaded 4 3
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment