You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucy.apache.org by ma...@apache.org on 2015/03/19 01:09:35 UTC

[15/19] lucy-clownfish git commit: Use custom C code for fleshing out Go bindings.

Use custom C code for fleshing out Go bindings.

Instead of wrapping the C version of the Clownfish shared library,
prepare to custom-code Go-specific behaviors for the host-specific
portions of Clownfish.

Content copied from c/src/**.c


Project: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/commit/56d26bc1
Tree: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/tree/56d26bc1
Diff: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/diff/56d26bc1

Branch: refs/heads/master
Commit: 56d26bc159fb97d8efb1f67f67f1d7b61a186aab
Parents: a255977
Author: Marvin Humphrey <ma...@rectangular.com>
Authored: Fri Nov 14 18:46:27 2014 -0800
Committer: Marvin Humphrey <ma...@rectangular.com>
Committed: Sun Mar 15 19:01:11 2015 -0700

----------------------------------------------------------------------
 runtime/go/ext/clownfish.c | 285 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 285 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/56d26bc1/runtime/go/ext/clownfish.c
----------------------------------------------------------------------
diff --git a/runtime/go/ext/clownfish.c b/runtime/go/ext/clownfish.c
index e69de29..196f90c 100644
--- a/runtime/go/ext/clownfish.c
+++ b/runtime/go/ext/clownfish.c
@@ -0,0 +1,285 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define CFISH_USE_SHORT_NAMES
+#define C_CFISH_OBJ
+#define C_CFISH_CLASS
+#define C_CFISH_METHOD
+#define C_CFISH_ERR
+#define C_CFISH_LOCKFREEREGISTRY
+
+#include <setjmp.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "charmony.h"
+
+#include "Clownfish/Obj.h"
+#include "Clownfish/Class.h"
+#include "Clownfish/Method.h"
+#include "Clownfish/Err.h"
+#include "Clownfish/Util/Memory.h"
+#include "Clownfish/String.h"
+#include "Clownfish/VArray.h"
+#include "Clownfish/LockFreeRegistry.h"
+
+/******************************** Obj **************************************/
+
+static CFISH_INLINE bool
+SI_immortal(cfish_Class *klass) {
+    if (klass == CFISH_CLASS
+        || klass == CFISH_METHOD
+        || klass == CFISH_BOOLNUM
+        || klass == CFISH_HASHTOMBSTONE
+       ){
+        return true;
+    }
+    return false;
+}
+
+static CFISH_INLINE bool
+SI_is_string_type(cfish_Class *klass) {
+    if (klass == CFISH_STRING || klass == CFISH_STACKSTRING) {
+        return true;
+    }
+    return false;
+}
+
+static CFISH_INLINE bool
+SI_threadsafe_but_not_immortal(cfish_Class *klass) {
+    if (klass == CFISH_LOCKFREEREGISTRY) {
+        return true;
+    }
+    return false;
+}
+
+uint32_t
+cfish_get_refcount(void *vself) {
+    cfish_Obj *self = (cfish_Obj*)vself;
+    return self->refcount;
+}
+
+Obj*
+cfish_inc_refcount(void *vself) {
+    Obj *self = (Obj*)vself;
+
+    // Handle special cases.
+    cfish_Class *const klass = self->klass;
+    if (klass->flags & CFISH_fREFCOUNTSPECIAL) {
+        if (SI_is_string_type(klass)) {
+            // Only copy-on-incref Strings get special-cased.  Ordinary
+            // strings fall through to the general case.
+            if (CFISH_Str_Is_Copy_On_IncRef((cfish_String*)self)) {
+                const char *utf8 = CFISH_Str_Get_Ptr8((cfish_String*)self);
+                size_t size = CFISH_Str_Get_Size((cfish_String*)self);
+                return (cfish_Obj*)cfish_Str_new_from_trusted_utf8(utf8, size);
+            }
+        }
+        else if (SI_immortal(klass)) {
+            return self;
+        }
+        else if (SI_threadsafe_but_not_immortal(klass)) {
+            // TODO: use atomic operation
+        }
+    }
+
+    self->refcount++;
+    return self;
+}
+
+uint32_t
+cfish_dec_refcount(void *vself) {
+    cfish_Obj *self = (Obj*)vself;
+    cfish_Class *klass = self->klass;
+    if (klass->flags & CFISH_fREFCOUNTSPECIAL) {
+        if (SI_immortal(klass)) {
+            return self->refcount;
+        }
+        else if (SI_threadsafe_but_not_immortal(klass)) {
+            // TODO: use atomic operation
+        }
+    }
+
+    uint32_t modified_refcount = INT32_MAX;
+    switch (self->refcount) {
+        case 0:
+            THROW(ERR, "Illegal refcount of 0");
+            break; // useless
+        case 1:
+            modified_refcount = 0;
+            Obj_Destroy(self);
+            break;
+        default:
+            modified_refcount = --self->refcount;
+            break;
+    }
+    return modified_refcount;
+}
+
+void*
+Obj_To_Host_IMP(Obj *self) {
+    UNUSED_VAR(self);
+    THROW(ERR, "TODO");
+    UNREACHABLE_RETURN(void*);
+}
+
+/******************************* Class *************************************/
+
+Obj*
+Class_Make_Obj_IMP(Class *self) {
+    Obj *obj = (Obj*)Memory_wrapped_calloc(self->obj_alloc_size, 1);
+    obj->klass = self;
+    obj->refcount = 1;
+    return obj;
+}
+
+Obj*
+Class_Init_Obj_IMP(Class *self, void *allocation) {
+    Obj *obj = (Obj*)allocation;
+    obj->klass = self;
+    obj->refcount = 1;
+    return obj;
+}
+
+Obj*
+Class_Foster_Obj_IMP(Class *self, void *host_obj) {
+    UNUSED_VAR(self);
+    UNUSED_VAR(host_obj);
+    THROW(ERR, "TODO");
+    UNREACHABLE_RETURN(Obj*);
+}
+
+void
+Class_register_with_host(Class *singleton, Class *parent) {
+    UNUSED_VAR(singleton);
+    UNUSED_VAR(parent);
+}
+
+VArray*
+Class_fresh_host_methods(String *class_name) {
+    UNUSED_VAR(class_name);
+    return VA_new(0);
+}
+
+String*
+Class_find_parent_class(String *class_name) {
+    UNUSED_VAR(class_name);
+    THROW(ERR, "TODO");
+    UNREACHABLE_RETURN(String*);
+}
+
+void*
+Class_To_Host_IMP(Class *self) {
+    UNUSED_VAR(self);
+    THROW(ERR, "TODO");
+    UNREACHABLE_RETURN(void*);
+}
+
+/******************************* Method ************************************/
+
+String*
+Method_Host_Name_IMP(Method *self) {
+    return (String*)INCREF(self->name);
+}
+
+/******************************** Err **************************************/
+
+/* TODO: Thread safety */
+static Err *current_error;
+static Err *thrown_error;
+static jmp_buf  *current_env;
+
+void
+Err_init_class(void) {
+}
+
+Err*
+Err_get_error() {
+    return current_error;
+}
+
+void
+Err_set_error(Err *error) {
+    if (current_error) {
+        DECREF(current_error);
+    }
+    current_error = error;
+}
+
+void
+Err_do_throw(Err *error) {
+    if (current_env) {
+        thrown_error = error;
+        longjmp(*current_env, 1);
+    }
+    else {
+        String *message = Err_Get_Mess(error);
+        char *utf8 = Str_To_Utf8(message);
+        fprintf(stderr, "%s", utf8);
+        FREEMEM(utf8);
+        exit(EXIT_FAILURE);
+    }
+}
+
+void*
+Err_To_Host_IMP(Err *self) {
+    UNUSED_VAR(self);
+    THROW(ERR, "TODO");
+    UNREACHABLE_RETURN(void*);
+}
+
+void
+Err_throw_mess(Class *klass, String *message) {
+    UNUSED_VAR(klass);
+    Err *err = Err_new(message);
+    Err_do_throw(err);
+}
+
+void
+Err_warn_mess(String *message) {
+    char *utf8 = Str_To_Utf8(message);
+    fprintf(stderr, "%s", utf8);
+    FREEMEM(utf8);
+    DECREF(message);
+}
+
+Err*
+Err_trap(Err_Attempt_t routine, void *context) {
+    jmp_buf  env;
+    jmp_buf *prev_env = current_env;
+    current_env = &env;
+
+    if (!setjmp(env)) {
+        routine(context);
+    }
+
+    current_env = prev_env;
+
+    Err *error = thrown_error;
+    thrown_error = NULL;
+    return error;
+}
+
+/************************** LockFreeRegistry *******************************/
+
+void*
+LFReg_To_Host_IMP(LockFreeRegistry *self) {
+    UNUSED_VAR(self);
+    THROW(ERR, "TODO");
+    UNREACHABLE_RETURN(void*);
+}
+
+