Listing 6: Native code implementation of a thread-safe sorting container (excerpt from file jni_complex_example.cpp)

// uses double-checker locking pattern [8]
class SampleContainer {
   static SampleContainer *instance;

   typedef multimap<string, JNIGlobalRef<jobject> *> 
   MapOfObjects;

   MapOfObjects mapOfObjects;     // the container implementation
   JNIGlobalRef<jobject> monitor; // monitor (for 
                                  // critical sections)
   JNIEnv *_env;                  // the environment variable

   SampleContainer(JNIEnv *env) 
      : _env(env), monitor(env, getMonitorObject(env)) {}
   ~SampleContainer();            // the dtor purges all the map 
                                  // elements

   // allocating the monitor object
   jobject getMonitorObject(JNIEnv *env) {  
      JNIClass objectClass(env, "java/lang/Object");
      jmethodID constructorId = 
         env->GetMethodID(objectClass, "<init>", "()V");
      return env->NewObject(objectClass, constructorId);
   }
   
public:
   static SampleContainer *getInstance(JNIEnv *env = 0) {
      if (instance == 0) {
         if (env == 0) {   // raise an exception flag in Java, 
                           // then throw a C++ exception
            env->ThrowNew(JNIClass(env, "java/lang/Exception"), 
               "Init failed");
            throw new JNIException("Init failed");
         }
         static JNIGlobalRef<jobject> 
         initMonitor(env, getMonitorObject(env));

         // Double-checked locking is used to 
         // provide correct initialization
         JNIMonitor startCriticalSection(env, initMonitor);
         if (instance == 0)
            instance = new SampleContainer(env);
      }
      return instance;
   }

   // explicitly release the native resources
   static void clean() { delete instance; }   

   void insert(jobject obj) {
      JNIMonitor startCriticalSection(_env, monitor);

      // retrieve the object ID
      JNIStringUTFChars str(_env, obj, "name"); 
      JNIGlobalRef<jobject> *ref = 
         new JNIGlobalRef<jobject>(_env, obj);
      mapOfObjects.insert(make_pair(str.asString(), ref));
   }

   vector<JNIGlobalRef<jobject> *> exportAllObjects() {
      JNIMonitor startCriticalSection(_env, monitor);

      vector<JNIGlobalRef<jobject> *> 
      result(mapOfObjects.size(), 0);
    
      MapOfObjects::iterator p; 
      vector<JNIGlobalRef<jobject> *>::iterator q;
      for (p = mapOfObjects.begin(), q = result.begin();
           p != mapOfObjects.end(); p++, q++)
         *q = (*p).second;
      return result;
   }     
};

// Singleton instance
SampleContainer *SampleContainer::instance = 0;

/* Implementation of native calls (note that their 
   prototypes are automatically generated) */

// init_native_resources()
JNIEXPORT void JNICALL 
Java_JniComplexExample_init_1native_1resources 
   (JNIEnv *env, jclass clazz)
{ SampleContainer::getInstance(env); }

// clean_native_resources()
JNIEXPORT void JNICALL 
Java_JniComplexExample_clean_1native_1resources 
   (JNIEnv *env, jclass clazz)
{ SampleContainer::clean(); }

// register_object()
JNIEXPORT void JNICALL 
Java_JniComplexExample_register_1object 
   (JNIEnv *env, jclass clazz, jobject obj)
{ SampleContainer::getInstance()->insert(obj); }

// recall_objects
JNIEXPORT jobjectArray JNICALL 
Java_JniComplexExample_recall_1objects 
   (JNIEnv *env, jclass clazz) {
  
   // obtain the vector of global references
   vector<JNIGlobalRef<jobject> *> allObjects = 
      SampleContainer::getInstance()->exportAllObjects();

   // create an output array of type 'NameWithInfo[]'
   JNIClass objectClass(env, "NameWithInfo");
   jobjectArray result = 
      env->NewObjectArray(allObjects.size(), objectClass, 0);
  
   // export the objects
   for (int i = 0; i < allObjects.size(); i++)
      env->SetObjectArrayElement(result, i, *allObjects[i]);
   return result;
}
— End of Listing —