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) ->