Skip to content

Instantly share code, notes, and snippets.

@KeyYao
Created February 20, 2020 13:35
Show Gist options
  • Save KeyYao/7934107c73539aaeb6014b1c4527171a to your computer and use it in GitHub Desktop.
Save KeyYao/7934107c73539aaeb6014b1c4527171a to your computer and use it in GitHub Desktop.
JNIEnvHandler
//
// Created by Key.Yao on 2020-02-20.
//
#include "JNIEnvHandler.h"
using namespace std;
struct ThreadMessage {
ThreadMessage(int i, void* m, bool flag) {
what = i;
msg = m;
exit = flag;
}
int what;
void* msg;
bool exit;
};
JNIEnvHandler::JNIEnvHandler(const char *threadName) {
_threadName = threadName;
_thread = nullptr;
_exitFlag = false;
_vm = nullptr;
_callback = nullptr;
}
JNIEnvHandler::~JNIEnvHandler() {
_thread = nullptr;
_callback = nullptr;
_instance = nullptr;
_vm = nullptr;
}
bool JNIEnvHandler::init(JavaVM *vm, jobject instance, handleMessage callback) {
if (!_thread) {
_thread = new thread(&JNIEnvHandler::process, this);
}
_vm = vm;
_instance = instance;
_callback = callback;
return true;
}
void JNIEnvHandler::exit() {
if (!_thread) {
return;
}
auto *msg = new ThreadMessage(-1, nullptr, true);
{
lock_guard<mutex> lock(_mutex);
_queue.push(msg);
_cv.notify_one();
}
_thread->join();
delete _thread;
_thread = nullptr;
_exitFlag = true;
}
std::thread::id JNIEnvHandler::getThreadId() {
return _thread->get_id();
}
void JNIEnvHandler::post(int what, void *obj) {
auto *msg = new ThreadMessage(what, obj, false);
unique_lock<mutex> lock(_mutex);
_queue.push(msg);
_cv.notify_one();
}
void JNIEnvHandler::process() {
_exitFlag = false;
JNIEnv *env = nullptr;
if (_vm) {
_vm->AttachCurrentThread(&env, nullptr);
}
while (true) {
ThreadMessage *msg = nullptr;
{
unique_lock<mutex> lock(_mutex);
while (_queue.empty()) {
_cv.wait(lock);
}
if (_queue.empty()) {
continue;
}
msg = _queue.front();
_queue.pop();
}
if (msg->exit) {
delete msg;
break;
}
if (env && _instance) {
_callback(msg->what, msg->msg, env, _instance);
}
delete msg;
}
env->DeleteGlobalRef(_instance);
if (_vm) {
_vm->DetachCurrentThread();
}
}
//
// Created by Key.Yao on 2020-02-20.
//
#ifndef __JNIENVHANDLER_H__
#define __JNIENVHANDLER_H__
#include <jni.h>
#include <thread>
#include <queue>
#include <atomic>
#include <condition_variable>
typedef void(*handleMessage)(int what, void* obj, JNIEnv *env, jobject instance);
struct ThreadMessage;
class JNIEnvHandler {
public:
JNIEnvHandler(const char* threadName);
~JNIEnvHandler();
bool init(JavaVM *vm, jobject instance, handleMessage callback);
void exit();
std::thread::id getThreadId();
void post(int what, void *obj = nullptr);
private:
JNIEnvHandler(const JNIEnvHandler&);
JNIEnvHandler&operator=(const JNIEnvHandler&);
void process();
JavaVM *_vm;
jobject _instance;
std::thread *_thread;
std::queue<ThreadMessage*> _queue;
std::mutex _mutex;
std::condition_variable _cv;
std::atomic<bool> _exitFlag;
handleMessage _callback;
const char* _threadName;
};
#endif //__JNIENVHANDLER_H__
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment