Permalink
Browse files

Implement process-related NIF APIs

- enif_self
- enif_is_pid
- enif_send
- enif_get_local_pid

The caller of enif_self can only use the returned
pointer for the duration of the NIF call; otherwise
she will have to store the pointed-to value.
  • Loading branch information...
1 parent 91dd6dd commit 362f3f96dfc590239aaa834a9f1c082dca04a8de @krestenkrab krestenkrab committed Sep 16, 2013
Showing with 118 additions and 1 deletion.
  1. +3 −1 jnif/Makefile
  2. +1 −0 jnif/jnif.cc
  3. +5 −0 jnif/jnif.h
  4. +100 −0 jnif/jnif_process.cc
  5. +5 −0 src/main/java/erjang/EProc.java
  6. +4 −0 src/main/java/erjang/NIF.java
View
@@ -23,7 +23,9 @@ OFILES= jnif.o \
jnif_list.o \
jnif_errno.o \
jnif_dlopen.o \
- jnif_sys.o
+ jnif_sys.o \
+ jnif_process.o
+
all: $(OFILES)
View
@@ -245,6 +245,7 @@ extern "C" jint JNI_OnLoad(JavaVM *vm, void *reserved)
initialize_jnif_tuple(vm,je);
initialize_jnif_list(vm, je);
initialize_jnif_sys(vm, je);
+ initialize_jnif_process(vm, je);
}
return JNI_VERSION_1_4;
}
View
@@ -41,7 +41,9 @@ struct enif_environment_t {
std::list< jnif_dtor* > commits;
struct jnif_module *module;
+
jobject self;
+ ErlNifPid self_pid; // memory location to return
enif_environment_t() { type = ALLOC; self = NULL; module = NULL; }
@@ -94,4 +96,7 @@ void initialize_jnif_list(JavaVM* vm, JNIEnv *je);
// jnif_sys.cc
void initialize_jnif_sys(JavaVM* vm, JNIEnv *je);
+// jnif_process.cc
+void initialize_jnif_process(JavaVM* vm, JNIEnv *je);
+
#endif
View
@@ -0,0 +1,100 @@
+
+
+#include "jnif.h"
+
+
+
+static jmethodID m_eobject__testPID;
+static jmethodID m_eobject__testInternalPID;
+static jclass NIF_class;
+static jmethodID m_NIF__send;
+
+static jclass eproc_class;
+static jmethodID m_eproc__find;
+static jmethodID m_eproc__key;
+
+
+//
+// potential problem: the value returned by enif_self is only
+// valid for the life time of the given environment; otherwise it
+// will have to be copied.
+//
+ErlNifPid* enif_self(ErlNifEnv* ee)
+{
+ if (ee->self == NULL) return NULL;
+ jlong key = ee->je->CallIntMethod( ee->self, m_eproc__key );
+ ee->self_pid.pid = key;
+ return &ee->self_pid;
+}
+
+int enif_get_local_pid(ErlNifEnv* ee, ERL_NIF_TERM term, ErlNifPid* pid)
+{
+ JNIEnv* je = ee->je;
+ if (je->CallObjectMethod( E2J(term), m_eobject__testInternalPID) == NULL) {
+ return NIF_FALSE;
+ } else {
+ jlong key = je->CallIntMethod( E2J(term), m_eproc__key );
+ pid->pid = key;
+ return NIF_TRUE;
+ }
+}
+
+int enif_is_pid(ErlNifEnv* ee, ERL_NIF_TERM term)
+{
+ if (ee->je->CallObjectMethod( E2J(term), m_eobject__testPID) == NULL) {
+ return NIF_FALSE;
+ } else {
+ return NIF_TRUE;
+ }
+}
+
+int enif_send(ErlNifEnv* ee, ErlNifPid* to_pid,
+ ErlNifEnv* msg_env, ERL_NIF_TERM msg)
+{
+ JNIEnv* je = ee->je;
+ jint key = to_pid->pid;
+ jobject pid = je->CallStaticObjectMethod( eproc_class,
+ m_eproc__find,
+ (jint)key );
+ if (pid == NULL) {
+ return 0;
+ }
+
+ je->CallStaticVoidMethod( NIF_class,
+ m_NIF__send,
+ pid,
+ E2J(msg) );
+
+ return 1;
+}
+
+
+void initialize_jnif_process(JavaVM* vm, JNIEnv *je)
+{
+ jclass eobject_class = je->FindClass("erjang/EObject");
+ m_eobject__testPID = je->GetMethodID(eobject_class,
+ "testPID",
+ "()Lerjang/EPID;");
+ m_eobject__testInternalPID = je->GetMethodID(eobject_class,
+ "testInternalPID",
+ "()Lerjang/EInternalPID;");
+
+ NIF_class = je->FindClass("erjang/NIF");
+ NIF_class = (jclass) je->NewGlobalRef( NIF_class );
+
+ m_NIF__send = je->GetStaticMethodID(NIF_class,
+ "send",
+ "(Lerjang/EPID;Lerjang/EObject;)V");
+
+ eproc_class = je->FindClass("erjang/EProc");
+ eproc_class = (jclass) je->NewGlobalRef( eproc_class );
+
+ m_eproc__find= je->GetStaticMethodID(eproc_class,
+ "find",
+ "(I)Lerjang/EProc;");
+
+ m_eproc__key = je->GetMethodID(eproc_class,
+ "key",
+ "()I");
+
+}
@@ -180,6 +180,11 @@ protected void setTarget(EAtom m, EAtom f, ESeq a) {
}
}
+ // called from JNIF
+ static EProc find(int key) {
+ return all_tasks.get(key);
+ }
+
private int key() {
int key = (self.serial() << 15) | (self.id() & 0x7fff);
return key;
@@ -108,5 +108,9 @@ public static int get_num_async_threads() {
public static int get_num_scheduler_threads() {
return ERT.threadPoolSize();
}
+
+ public static void send(EPID target, EObject msg) {
+ target.sendb(msg);
+ }
}

0 comments on commit 362f3f9

Please sign in to comment.