1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
|
#include <qapplication.h>
#include <qmutex.h>
#include <qtjava/QtSupport.h>
#include <qtjava/QtUtils.h>
#include "QtUtils.moc"
#define SYNC_EVENT1 60001
#define SYNC_EVENT2 60002
#define ASYNC_EVENT 60003
class QRunEvent : public QCustomEvent
{
public:
QRunEvent(int type, jobject r) :
QCustomEvent(type),
runnable(r),
res(0),
lock(0)
{}
jobject runnable;
jobject *res;
QMutex *lock;
};
QtUtils* QtUtils::gUtils = 0;
QtUtils::QtUtils()
{
}
QtUtils::~QtUtils()
{
}
void QtUtils::postSync(JNIEnv* env, jobject runnable) {
QMutex lock;
QRunEvent *e = new QRunEvent(SYNC_EVENT1, env->NewGlobalRef(runnable));
e->lock = &lock;
lock.lock();
//post the event to the QT-UI thread
//and trigger its processing
QApplication::postEvent(this, e);
QApplication::sendPostedEvents();
//the lock is gained only
//after executing the runnable
lock.lock();
lock.unlock();
}
jobject QtUtils::postSyncRet(JNIEnv* env, jobject runnable) {
QMutex lock;
jobject res;
QRunEvent *e = new QRunEvent(SYNC_EVENT2, env->NewGlobalRef(runnable));
e->lock = &lock;
e->res = &res;
lock.lock();
//post the event to the QT-UI thread and
//trigger its processing
QApplication::postEvent(this, e);
QApplication::sendPostedEvents();
//the lock is gained only
//after executing the runnable
lock.lock();
lock.unlock();
jobject lres = env->NewLocalRef(res);
env->DeleteGlobalRef(res);
return lres;
}
void QtUtils::postAsync(JNIEnv *env, jobject runnable) {
QRunEvent *e = new QRunEvent(ASYNC_EVENT, env->NewGlobalRef(runnable));
//post the event to the QT-UI thread,
//it will be processed in the next Qt-loop iterations
QApplication::postEvent(this, e);
}
void QtUtils::customEvent(QCustomEvent *e) {
if (e->type() >= SYNC_EVENT1 && e->type() <= ASYNC_EVENT) {
QRunEvent *re = (QRunEvent*) e;
JNIEnv *env = QtSupport::GetEnv();
jclass cls = env->GetObjectClass(re->runnable);
if (re->type() == SYNC_EVENT1) {
jmethodID m = env->GetMethodID(cls, "run", "()V");
if (m!=0) {
env->CallObjectMethod(re->runnable, m);
}
re->lock->unlock();
}
else if (re->type() == SYNC_EVENT2) {
jmethodID m = env->GetMethodID(cls, "run", "()Ljava/lang/Object;");
if (m!=0) {
jobject res = env->CallObjectMethod(re->runnable, m);
*(re->res) = env->NewGlobalRef(res);
}
re->lock->unlock();
}
else {
jmethodID m = env->GetMethodID(cls, "run", "()V");
if (m!=0) {
env->CallVoidMethod(re->runnable, m);
}
}
//runnable is no longer needed
env->DeleteGlobalRef(re->runnable);
}
}
JNIEXPORT jobject JNICALL
Java_org_kde_qt_QtUtils_execSyncOnGUIThread__Lorg_kde_qt_QtUtils_00024Compute_2
(JNIEnv *env, jclass, jobject runnable)
{
if (!runnable) return 0;
if (QtUtils::gUtils==0) QtUtils::gUtils = new QtUtils();
return QtUtils::gUtils->postSyncRet(env, runnable);
}
JNIEXPORT void JNICALL
Java_org_kde_qt_QtUtils_execSyncOnGUIThread__Ljava_lang_Runnable_2
(JNIEnv *env, jclass, jobject runnable)
{
if (!runnable) return;
if (QtUtils::gUtils==0) QtUtils::gUtils = new QtUtils();
QtUtils::gUtils->postSync(env, runnable);
}
JNIEXPORT void JNICALL
Java_org_kde_qt_QtUtils_execAsyncOnGUIThread
(JNIEnv *env, jclass, jobject runnable)
{
if (!runnable) return;
if (QtUtils::gUtils==0) QtUtils::gUtils = new QtUtils();
QtUtils::gUtils->postAsync(env, runnable);
}
|