You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@couchdb.apache.org by kx...@apache.org on 2015/07/13 20:45:04 UTC
[05/43] jiffy commit: updated refs/heads/upstream to 446e284
Use a resource for the decoder structure
This is ground work to allow Jiffy to yield back to the scheduler.
Creating a decoder resource will allow for the necessary state to be
carried across NIF function invocations.
Project: http://git-wip-us.apache.org/repos/asf/couchdb-jiffy/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb-jiffy/commit/79d24e96
Tree: http://git-wip-us.apache.org/repos/asf/couchdb-jiffy/tree/79d24e96
Diff: http://git-wip-us.apache.org/repos/asf/couchdb-jiffy/diff/79d24e96
Branch: refs/heads/upstream
Commit: 79d24e9639e1c721e1a520da7e41715ea9907022
Parents: c5c794e
Author: Paul J. Davis <pa...@gmail.com>
Authored: Thu Jun 12 14:46:01 2014 -0500
Committer: Paul J. Davis <pa...@gmail.com>
Committed: Fri Jun 13 16:56:24 2014 -0500
----------------------------------------------------------------------
c_src/decoder.c | 97 ++++++++++++++++++++++++++++++++++++++++++----------
c_src/jiffy.c | 12 ++++++-
c_src/jiffy.h | 7 +++-
src/jiffy.erl | 8 +++--
4 files changed, 102 insertions(+), 22 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/couchdb-jiffy/blob/79d24e96/c_src/decoder.c
----------------------------------------------------------------------
diff --git a/c_src/decoder.c b/c_src/decoder.c
index fc892da..45ea329 100644
--- a/c_src/decoder.c
+++ b/c_src/decoder.c
@@ -61,21 +61,25 @@ typedef struct {
int st_top;
} Decoder;
-void
-dec_init(Decoder* d, ErlNifEnv* env, ERL_NIF_TERM arg, ErlNifBinary* bin)
+Decoder*
+dec_new(ErlNifEnv* env)
{
+ jiffy_st* st = (jiffy_st*) enif_priv_data(env);
+ Decoder* d = enif_alloc_resource(st->res_dec, sizeof(Decoder));
int i;
- d->env = env;
- d->atoms = enif_priv_data(env);
- d->arg = arg;
+ if(d == NULL) {
+ return NULL;
+ }
+
+ d->atoms = st;
d->is_partial = 0;
- d->p = (char*) bin->data;
- d->u = bin->data;
- d->len = bin->size;
- d->i = 0;
+ d->p = NULL;
+ d->u = NULL;
+ d->len = -1;
+ d->i = -1;
d->st_data = (char*) enif_alloc(STACK_SIZE_INC * sizeof(char));
d->st_size = STACK_SIZE_INC;
@@ -87,11 +91,36 @@ dec_init(Decoder* d, ErlNifEnv* env, ERL_NIF_TERM arg, ErlNifBinary* bin)
d->st_data[0] = st_value;
d->st_top++;
+
+ return d;
}
void
-dec_destroy(Decoder* d)
+dec_init(Decoder* d, ErlNifEnv* env, ERL_NIF_TERM arg, ErlNifBinary* bin)
{
+ d->env = env;
+ d->arg = arg;
+
+ d->p = (char*) bin->data;
+ d->u = bin->data;
+ d->len = bin->size;
+
+ // I'd like to be more forceful on this check so that when
+ // we run a second iteration of the decoder we are sure
+ // that we're using the same binary. Unfortunately, I don't
+ // think there's a value to base this assertion on.
+ if(d->i < 0) {
+ d->i = 0;
+ } else {
+ assert(d->i <= d->len && "mismatched binary lengths");
+ }
+}
+
+void
+dec_destroy(ErlNifEnv* env, void* obj)
+{
+ Decoder* d = (Decoder*) obj;
+
if(d->st_data != NULL) {
enif_free(d->st_data);
}
@@ -605,25 +634,59 @@ make_array(ErlNifEnv* env, ERL_NIF_TERM list)
}
ERL_NIF_TERM
-decode(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+decode_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
- Decoder dec;
- Decoder* d = &dec;
+ Decoder* d;
+ jiffy_st* st = (jiffy_st*) enif_priv_data(env);
+ ERL_NIF_TERM tmp_argv[4];
+
+ if(argc != 1) {
+ return enif_make_badarg(env);
+ }
+
+ d = dec_new(env);
+ if(d == NULL) {
+ return make_error(st, env, "internal_error");
+ }
+
+ tmp_argv[0] = argv[0];
+ tmp_argv[1] = enif_make_resource(env, d);
+ tmp_argv[2] = enif_make_list(env, 0);
+ tmp_argv[3] = enif_make_list(env, 0);
+
+ enif_release_resource(d);
+
+ return decode_iter(env, 4, tmp_argv);
+}
+
+ERL_NIF_TERM
+decode_iter(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{
+ Decoder* d;
+ jiffy_st* st = (jiffy_st*) enif_priv_data(env);
ErlNifBinary bin;
- ERL_NIF_TERM objs = enif_make_list(env, 0);
- ERL_NIF_TERM curr = enif_make_list(env, 0);
+ ERL_NIF_TERM objs;
+ ERL_NIF_TERM curr;
ERL_NIF_TERM val;
ERL_NIF_TERM ret;
- if(argc != 1) {
+ if(argc != 4) {
return enif_make_badarg(env);
} else if(!enif_inspect_binary(env, argv[0], &bin)) {
return enif_make_badarg(env);
+ } else if(!enif_get_resource(env, argv[1], st->res_dec, (void**) &d)) {
+ return enif_make_badarg(env);
+ } else if(!enif_is_list(env, argv[2])) {
+ return enif_make_badarg(env);
+ } else if(!enif_is_list(env, argv[3])) {
+ return enif_make_badarg(env);
}
dec_init(d, env, argv[0], &bin);
+ objs = argv[2];
+ curr = argv[3];
//fprintf(stderr, "Parsing:\r\n");
while(d->i < bin.size) {
@@ -908,7 +971,5 @@ decode(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
}
done:
- dec_destroy(d);
-
return ret;
}
http://git-wip-us.apache.org/repos/asf/couchdb-jiffy/blob/79d24e96/c_src/jiffy.c
----------------------------------------------------------------------
diff --git a/c_src/jiffy.c b/c_src/jiffy.c
index 964222c..e0c1f20 100644
--- a/c_src/jiffy.c
+++ b/c_src/jiffy.c
@@ -28,6 +28,15 @@ load(ErlNifEnv* env, void** priv, ERL_NIF_TERM info)
st->ref_object = make_atom(env, "$object_ref$");
st->ref_array = make_atom(env, "$array_ref$");
+ st->res_dec = enif_open_resource_type(
+ env,
+ NULL,
+ "decoder",
+ dec_destroy,
+ ERL_NIF_RT_CREATE | ERL_NIF_RT_TAKEOVER,
+ NULL
+ );
+
*priv = (void*) st;
return 0;
@@ -54,7 +63,8 @@ unload(ErlNifEnv* env, void* priv)
static ErlNifFunc funcs[] =
{
- {"nif_decode", 1, decode},
+ {"nif_decode_init", 1, decode_init},
+ {"nif_decode_iter", 4, decode_iter},
{"nif_encode", 2, encode}
};
http://git-wip-us.apache.org/repos/asf/couchdb-jiffy/blob/79d24e96/c_src/jiffy.h
----------------------------------------------------------------------
diff --git a/c_src/jiffy.h b/c_src/jiffy.h
index 3dda545..bfd5940 100644
--- a/c_src/jiffy.h
+++ b/c_src/jiffy.h
@@ -22,15 +22,20 @@ typedef struct {
ERL_NIF_TERM ref_object;
ERL_NIF_TERM ref_array;
+
+ ErlNifResourceType* res_dec;
} jiffy_st;
ERL_NIF_TERM make_atom(ErlNifEnv* env, const char* name);
ERL_NIF_TERM make_ok(jiffy_st* st, ErlNifEnv* env, ERL_NIF_TERM data);
ERL_NIF_TERM make_error(jiffy_st* st, ErlNifEnv* env, const char* error);
-ERL_NIF_TERM decode(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+ERL_NIF_TERM decode_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+ERL_NIF_TERM decode_iter(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
ERL_NIF_TERM encode(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+void dec_destroy(ErlNifEnv* env, void* obj);
+
int int_from_hex(const unsigned char* p);
int int_to_hex(int val, char* p);
int utf8_len(int c);
http://git-wip-us.apache.org/repos/asf/couchdb-jiffy/blob/79d24e96/src/jiffy.erl
----------------------------------------------------------------------
diff --git a/src/jiffy.erl b/src/jiffy.erl
index c4b3d69..c9e65e4 100644
--- a/src/jiffy.erl
+++ b/src/jiffy.erl
@@ -8,7 +8,7 @@
-on_load(init/0).
decode(Data) when is_binary(Data) ->
- case nif_decode(Data) of
+ case nif_decode_init(Data) of
{error, _} = Error ->
throw(Error);
{partial, EJson} ->
@@ -99,7 +99,11 @@ init() ->
not_loaded(Line) ->
erlang:nif_error({not_loaded, [{module, ?MODULE}, {line, Line}]}).
-nif_decode(_Data) ->
+nif_decode_init(_Data) ->
+ ?NOT_LOADED,
+ nif_decode_iter(w, x, y, z).
+
+nif_decode_iter(_Data, _Decoder, _, _) ->
?NOT_LOADED.
nif_encode(_Data, _Options) ->