GraphLab: Distributed Graph-Parallel API  2.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
org_graphlab_Core.hpp
Go to the documentation of this file.
1 /**
2  * Copyright (c) 2009 Carnegie Mellon University.
3  * All rights reserved.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing,
12  * software distributed under the License is distributed on an "AS
13  * IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
14  * express or implied. See the License for the specific language
15  * governing permissions and limitations under the License.
16  *
17  * For more about this software visit:
18  *
19  * http://www.graphlab.ml.cmu.edu
20  *
21  */
22 
23 /**
24  * @file org_graphlab_Core.hpp
25  * \c javah will generate \c org_graphlab_Core.h from the native methods
26  * defined in \c org.graphlab.Context (and so will overwrite the file every time).
27  * Define any additional classes/structs/typedefs in this hpp file.
28  * @author Jiunn Haur Lim <[email protected]>
29  */
30 
31 #ifndef ORG_GRAPHLAB_CORE_HPP
32 #define ORG_GRAPHLAB_CORE_HPP
33 
34 #include <execinfo.h>
35 #include <graphlab.hpp>
36 
37 #include "java_any.hpp"
38 #include "org_graphlab_Core.h"
39 
40 namespace graphlab {
41 
42  /**
43  * Wrapper for graphlab::core.
44  * Contains the core, a reference to the Java core object (so that it
45  * doesn't get garbage collected), and other utility functions for dealing
46  * with the JVM.
47  */
48  template <typename Graph, typename UpdateFunctor>
49  class jni_core : public java_any {
50 
51  public:
52 
53  /** ID of pointer to JNI environment in thread local store */
54  static const size_t ENV_ID;
55 
56  private:
57 
58  typedef core<Graph, UpdateFunctor> core_type;
59 
60  /** graphlab::core object - the soul that this body wraps around */
61  core_type *mcore;
62 
63  /** Java virtual machine reference - set only once for each process */
64  static JavaVM *mjvm;
65 
66  public:
67 
68  /**
69  * Creates a new graphlab core and a new reference to the associated
70  * Java org.graphlab.Core object (so that it doesn't get garbage collected.)
71  * @param[in] env JNI environment, which will be used to create the
72  * reference to the Java object.
73  * @param[in] obj associated org.graphlab.Core object.
74  */
75  jni_core (JNIEnv *env, jobject &obj) : java_any (env, obj) {
76  this->mcore = new core_type();
77  }
78 
79  /**
80  * Gets the real graphlab core that this method wraps around
81  * @return graphlab::core
82  */
83  core_type &operator()(){
84  return *mcore;
85  }
86 
87  /**
88  * Deallocates the graphlab core. Parent constructor will delete jobject
89  * reference.
90  */
92  delete mcore;
93  }
94 
95  /**
96  * Saves a reference to the Java Virtual Machine.
97  * @param[in] jvm pointer to the Java Virtual Machine
98  */
99  static void set_jvm (JavaVM *jvm){
100  mjvm = jvm;
101  }
102 
103  /**
104  * Gets a reference to the Java Virtual Machine.
105  * @return pointer to the Java Virtual Machine
106  */
107  static JavaVM *get_jvm (){
108  return mjvm;
109  }
110 
111  /**
112  * Detaches the current thread from the JVM.
113  * If a pointer to the JNI environment cannot be found in the thread-local
114  * store, that means that this thread has already been detached, and the
115  * function will return immediately. Otherwise, the thread is detached and
116  * the pointer to the JNI environment is removed from the thread-local
117  * store.
118  */
119  static void detach_from_jvm() {
120 
121  // if the current thread is still attached, detach it
122  if (thread::contains(ENV_ID)) {
123  int res = mjvm->DetachCurrentThread();
124  assert(res >= 0);
125  thread::get_local(ENV_ID) = NULL;
126  }
127 
128  }
129 
130  static void dump_backtrace(int sig){
131 
132  void *array[10];
133  size_t size;
134 
135  // get void*'s for all entries on the stack
136  size = backtrace(array, 10);
137 
138  // print out all the frames to stderr
139  backtrace_symbols_fd(array, size, 2);
140 
141  }
142 
143  /** Convenience method for throwing Java exceptions */
144  static void throw_exception(JNIEnv* env,
145  const char *exception,
146  const char *message){
147  jclass exc = env->FindClass(exception);
148  if (NULL == exc) return;
149  env->ThrowNew(exc, message);
150  }
151 
152  /**
153  * Retrieves the JNI environment for the current thread.
154  * If a pointer to the JNI environment can be found in the thread-local
155  * store, returns immediately; otherwise, that means that the current
156  * thread has not been attached to the JVM yet. In that case, this
157  * function will attach the current thread to the JVM and save the
158  * associated JNI environment to the thread-local storage.
159  * @return JNI environment associated with the current thread.
160  */
161  static JNIEnv *get_jni_env (){
162 
163  JNIEnv *jenv = NULL;
164 
165  // if current thread is not already on the JVM, attach it
166  if (!thread::contains(ENV_ID)) {
167 
168  int res = mjvm->AttachCurrentThread((void **)&jenv, NULL);
169  assert(res >= 0);
170 
171  // store JNI environment in thread-local storage
172  thread::get_local(ENV_ID) = jenv;
173  thread::set_thread_destroy_callback(detach_from_jvm);
174 
175  }
176 
177  // return the environment associated with the current thread
178  return thread::get_local(ENV_ID).as<JNIEnv *>();
179 
180  }
181 
182  };
183 
184 }
185 
186 #endif