示例#1
0
文件: callback.c 项目: miho/jna
static void
callback_dispatch(ffi_cif* cif, void* resp, void** cbargs, void* user_data) {
  callback* cb = ((callback *)user_data); 
  JavaVM* jvm = cb->vm;
  JNIEnv* env;
  int was_attached = (*jvm)->GetEnv(jvm, (void *)&env, JNI_VERSION_1_4) == JNI_OK;
  jboolean detach = was_attached ? JNI_FALSE : JNI_TRUE;

  if (!was_attached) {
    int attach_status = 0;
    JavaVMAttachArgs args;
    jobject group = NULL;
    int daemon = JNI_FALSE;

    args.version = JNI_VERSION_1_2;
    args.name = NULL;
    args.group = NULL;
    if (cb->behavior_flags & CB_HAS_INITIALIZER) {
      AttachOptions options;
      options.daemon = JNI_FALSE; // default non-daemon
      options.detach = JNI_TRUE; // default detach behavior
      options.name = NULL;
      args.group = initializeThread(cb, &options);
      daemon = options.daemon ? JNI_TRUE : JNI_FALSE;
      detach = options.detach ? JNI_TRUE : JNI_FALSE;
      args.name = options.name;
    }
    if (daemon) {
      attach_status = (*jvm)->AttachCurrentThreadAsDaemon(jvm, (void*)&env, &args);
    }
    else {
      attach_status = (*jvm)->AttachCurrentThread(jvm, (void *)&env, &args);
    }
    if (attach_status != JNI_OK) {
      fprintf(stderr, "JNA: Can't attach native thread to VM for callback: %d\n", attach_status);
      return;
    }
    if (args.group) {
      (*env)->DeleteWeakGlobalRef(env, args.group);
    }
  }
  
  // Give the callback glue its own local frame to ensure all local references
  // are properly disposed
  if ((*env)->PushLocalFrame(env, 16) < 0) {
    fprintf(stderr, "JNA: Out of memory: Can't allocate local frame");
  }
  else {
    // Kind of a hack, use last error value rather than setting up our own TLS
    setLastError(0);
    callback_invoke(env, cb, cif, resp, cbargs);
    // Must be invoked immediately after return to avoid anything
    // stepping on errno/GetLastError
    switch(lastError()) {
    case THREAD_LEAVE_ATTACHED: detach = JNI_FALSE; break;
    case THREAD_DETACH: detach = JNI_TRUE; break;
    default: break; /* use default detach behavior */
    }
    (*env)->PopLocalFrame(env, NULL);
  }
  
  if (detach) {
    (*jvm)->DetachCurrentThread(jvm);
  }
}
示例#2
0
文件: callback.c 项目: cxbrooks/jna
static void
callback_dispatch(ffi_cif* cif, void* resp, void** cbargs, void* user_data) {
  callback* cb = ((callback *)user_data); 
  JavaVM* jvm = cb->vm;
  JNIEnv* env = NULL;
  int was_attached = (*jvm)->GetEnv(jvm, (void *)&env, JNI_VERSION_1_4) == JNI_OK;
  jboolean detach = was_attached ? JNI_FALSE : JNI_TRUE;
  thread_storage* tls = was_attached ? get_thread_storage(env) : NULL;

  if (!was_attached) {
    int attach_status = 0;
    JavaVMAttachArgs args;
    int daemon = JNI_FALSE;

    args.version = JNI_VERSION_1_2;
    args.name = NULL;
    args.group = NULL;
    if (cb->behavior_flags & CB_HAS_INITIALIZER) {
      AttachOptions options;
      options.daemon = JNI_FALSE; // default non-daemon
      options.detach = JNI_TRUE; // default detach behavior
      options.name = NULL;
      args.group = initializeThread(cb, &options);
      daemon = options.daemon ? JNI_TRUE : JNI_FALSE;
      detach = options.detach ? JNI_TRUE : JNI_FALSE;
      args.name = options.name;
    }
    if (daemon) {
      attach_status = (*jvm)->AttachCurrentThreadAsDaemon(jvm, (void*)&env, &args);
    }
    else {
      attach_status = (*jvm)->AttachCurrentThread(jvm, (void *)&env, &args);
    }
    tls = get_thread_storage(env);
    if (tls) {
      snprintf(tls->name, sizeof(tls->name), "%s", args.name ? args.name : "<unconfigured native thread>");
      tls->detach = detach;
      tls->jvm_thread = JNI_FALSE;
    }
    // Dispose of allocated memory
    free(args.name);
    if (attach_status != JNI_OK) {
      fprintf(stderr, "JNA: Can't attach native thread to VM for callback: %d\n", attach_status);
      return;
    }
    if (args.group) {
      (*env)->DeleteWeakGlobalRef(env, args.group);
    }
  }
						
  if (!tls) {
    fprintf(stderr, "JNA: couldn't obtain thread-local storage\n");
    return;
  }

  // Give the callback glue its own local frame to ensure all local references
  // are properly disposed
  if ((*env)->PushLocalFrame(env, 16) < 0) {
    fprintf(stderr, "JNA: Out of memory: Can't allocate local frame\n");
  }
  else {
    callback_invoke(env, cb, cif, resp, cbargs);
    // Make note of whether the callback wants to avoid detach
    detach = tls->detach && !tls->jvm_thread;
    (*env)->PopLocalFrame(env, NULL);
  }
  
  if (detach) {
    if ((*jvm)->DetachCurrentThread(jvm) != 0) {
      fprintf(stderr, "JNA: could not detach thread\n");
    }
  }
}