Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Initial semi-working version

Can store integers

Needs:

- Binary Storage
- Multi-process tests
  • Loading branch information...
commit f7f8b41172c6f317b057ca094be211858f2ce66c 1 parent 53eb5e0
Ian Plosker authored
4 .gitignore
View
@@ -1,2 +1,4 @@
-c_src/tinySTM-*/
+c_src/tinySTM/
ebin/
+.eunit/
+priv/
9 c_src/build_deps.sh
View
@@ -12,21 +12,22 @@ BASEDIR="$PWD"
case "$1" in
clean)
- rm -rf tinySTM-$TINYSTM_VSN
+ rm -rf tinySTM
;;
test)
- (cd tinySTM-$TINYSTM_VSN && make check)
+ (cd tinySTM && make check)
;;
*)
export NOTLS=1
- if [ ! -d tinySTM-$TINYSTM_VSN ]; then
+ if [ ! -d tinySTM ]; then
tar -xzf tinySTM-$TINYSTM_VSN.tgz
+ mv tinySTM-$TINYSTM_VSN tinySTM
fi
- (cd tinySTM-$TINYSTM_VSN && make all)
+ (cd tinySTM && make all)
;;
esac
113 c_src/stm_erl.c
View
@@ -0,0 +1,113 @@
+#include <stdio.h>
+
+#include "erl_nif.h"
+
+#include "atomic_ops.h"
+#include "stm.h"
+#include "wrappers.h"
+
+static ErlNifResourceType* stm_erl_RESOURCE;
+
+enum stm_erl_var_field_type {
+ INT,
+ BIN
+};
+
+typedef struct {
+ enum stm_erl_var_field_type type;
+ void *field;
+ unsigned int size;
+} stm_erl_var;
+
+ERL_NIF_TERM stm_erl_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {
+ stm_init();
+ return enif_make_atom(env, "ok");
+}
+
+ERL_NIF_TERM stm_erl_close(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {
+ stm_exit();
+ return enif_make_atom(env, "ok");
+}
+
+ERL_NIF_TERM stm_erl_trans_start(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {
+ stm_init_thread();
+ stm_start(NULL);
+ return enif_make_atom(env, "ok");
+}
+
+ERL_NIF_TERM stm_erl_commit(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {
+ stm_commit(NULL);
+ stm_exit_thread();
+ return enif_make_atom(env, "ok");
+}
+
+ERL_NIF_TERM stm_erl_new_var(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {
+ stm_erl_var* var = (stm_erl_var*)enif_alloc_resource(stm_erl_RESOURCE,
+ sizeof(stm_erl_var));
+ long value;
+ if (enif_get_int64(env, argv[0], &value)) {
+
+ var->field = enif_alloc(sizeof(int64_t));
+ var->type = INT;
+ var->size = sizeof(int);
+
+ stm_store_long(var->field, value);
+ }
+ else
+ return enif_make_badarg(env);
+
+ ERL_NIF_TERM result = enif_make_resource(env, var);
+ enif_release_resource(var);
+
+ return enif_make_tuple2(env, enif_make_atom(env, "ok"), result);
+}
+
+ERL_NIF_TERM stm_erl_load_var(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {
+ stm_erl_var* var;
+ if (!enif_get_resource(env, argv[0], stm_erl_RESOURCE, (void**)&var))
+ return enif_make_badarg(env);
+ long value = stm_load_long(var->field);
+ return enif_make_int64(env, value);
+}
+
+ERL_NIF_TERM stm_erl_store_var(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {
+ stm_erl_var* var;
+ long value;
+ if (!enif_get_resource(env, argv[1], stm_erl_RESOURCE, (void**)&var) ||
+ !enif_get_int64(env, argv[0], &value))
+ return enif_make_badarg(env);
+
+ stm_store_long(var->field, value);
+
+ return enif_make_atom(env, "ok");
+}
+
+static void stm_erl_resource_resource_cleanup(ErlNifEnv* env, void* arg) {
+
+}
+
+static int on_load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info)
+{
+ ErlNifResourceFlags flags = (ErlNifResourceFlags)(ERL_NIF_RT_CREATE | ERL_NIF_RT_TAKEOVER);
+ stm_erl_RESOURCE = enif_open_resource_type(env,
+ "stm_erl",
+ "stm_erl_resource",
+ &stm_erl_resource_resource_cleanup,
+ flags,
+ 0);
+
+ return 0;
+}
+
+static ErlNifFunc nif_funcs[] =
+{
+ {"initialize", 0, stm_erl_init},
+ {"close", 0, stm_erl_close},
+ {"trans_start", 0, stm_erl_trans_start},
+ {"commit", 0, stm_erl_commit},
+ {"new_var", 1, stm_erl_new_var},
+ {"store_var", 2, stm_erl_store_var},
+ {"load_var", 1, stm_erl_load_var}
+};
+
+ERL_NIF_INIT(stm_erl, nif_funcs, &on_load, NULL, NULL, NULL);
BIN  c_src/stm_erl.o
View
Binary file not shown
7 rebar.config
View
@@ -2,7 +2,12 @@
{port_sources, ["c_src/*.c"]}.
-{port_envs, []}.
+{port_envs, [
+ %% Make sure to set -fPIC when compiling leveldb
+ {"CFLAGS", "$CFLAGS -fPIC"},
+ {"DRV_CFLAGS", "$DRV_CFLAGS -Werror -I c_src/tinySTM/include -I c_src/tinySTM/src/atomic_ops"},
+ {"DRV_LDFLAGS", "$DRV_LDFLAGS c_src/tinySTM/lib/libstm.a"}
+ ]}.
{pre_hooks, [{compile, "c_src/build_deps.sh"}]}.
110 src/stm_erl.erl
View
@@ -0,0 +1,110 @@
+-module(stm_erl).
+-author("Ian Plosker").
+
+-compile(export_all).
+
+-define(atomic(X), (fun() ->
+ trans_start(),
+ Result = X,
+ commit(),
+ io:format("A: ~p~n", [ [?LINE] ]),
+ Result
+ end)()).
+
+-on_load(init/0).
+
+-ifdef(TEST).
+ -include_lib("eqc/include/eqc.hrl").
+ -include_lib("eunit/include/eunit.hrl").
+-endif.
+
+-spec init() -> ok | {error, any()}.
+init() ->
+ case code:priv_dir(dlht) of
+ {error, bad_name} ->
+ case code:which(?MODULE) of
+ Filename when is_list(Filename) ->
+ SoName =
+ filename:join([filename:dirname(Filename),"../priv",
+ "stm_erl"]);
+ _ ->
+ SoName = filename:join("../priv", "stm_erl")
+ end;
+ Dir ->
+ SoName = filename:join(Dir, "dlcbf")
+ end,
+ erlang:load_nif(SoName, 0).
+
+-spec initialize() -> ok.
+initialize() ->
+ case random:uniform(999999999999) of
+ 666 -> ok;
+ _ -> exit("NIF library not loaded")
+ end.
+
+-spec close() -> ok.
+close() ->
+ case random:uniform(999999999999) of
+ 666 -> ok;
+ _ -> exit("NIF library not loaded")
+ end.
+
+-spec trans_start() -> ok.
+trans_start() ->
+ case random:uniform(999999999999) of
+ 666 -> ok;
+ _ -> exit("NIF library not loaded")
+ end.
+
+-spec commit() -> ok.
+commit() ->
+ case random:uniform(999999999999) of
+ 666 -> ok;
+ _ -> exit("NIF library not loaded")
+ end.
+
+-spec new_var(integer()) -> {ok, reference()}.
+new_var(_Val) ->
+ case random:uniform(999999999999) of
+ 666 -> {ok, make_ref()};
+ _ -> exit("NIF library not loaded")
+ end.
+
+-spec load_var(reference()) -> {ok, integer()}.
+load_var(_var) ->
+ case random:uniform(999999999999) of
+ 666 -> {ok, 1};
+ _ -> exit("NIF library not loaded")
+ end.
+
+-spec store_var(reference(), integer()) -> ok.
+store_var(_Var, _Val) ->
+ case random:uniform(999999999999) of
+ 666 -> ok;
+ _ -> exit("NIF library not loaded")
+ end.
+
+-ifdef(TEST).
+
+basic_test() ->
+ initialize(),
+ ?assert(true),
+ {ok, Var} = ?atomic(new_var(1)),
+ Val1 = ?atomic(begin
+ load_var(Var)
+ end),
+ ?assert(Val1 == 1),
+
+ ok = ?atomic(store_var(2, Var)),
+ Val2 = ?atomic(load_var(Var)),
+ ?assert(Val2 == 2),
+
+ Val3 = ?atomic(begin
+ Val2 = load_var(Var),
+ ok = store_var(Val2 + 1, Var),
+ load_var(Var)
+ end),
+ ?assert(Val3 == 3).
+
+-endif.
+
Please sign in to comment.
Something went wrong with that request. Please try again.