1*cdf0e10cSrcweir /*************************************************************************
2*cdf0e10cSrcweir  *
3*cdf0e10cSrcweir  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4*cdf0e10cSrcweir  *
5*cdf0e10cSrcweir  * Copyright 2000, 2010 Oracle and/or its affiliates.
6*cdf0e10cSrcweir  *
7*cdf0e10cSrcweir  * OpenOffice.org - a multi-platform office productivity suite
8*cdf0e10cSrcweir  *
9*cdf0e10cSrcweir  * This file is part of OpenOffice.org.
10*cdf0e10cSrcweir  *
11*cdf0e10cSrcweir  * OpenOffice.org is free software: you can redistribute it and/or modify
12*cdf0e10cSrcweir  * it under the terms of the GNU Lesser General Public License version 3
13*cdf0e10cSrcweir  * only, as published by the Free Software Foundation.
14*cdf0e10cSrcweir  *
15*cdf0e10cSrcweir  * OpenOffice.org is distributed in the hope that it will be useful,
16*cdf0e10cSrcweir  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17*cdf0e10cSrcweir  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18*cdf0e10cSrcweir  * GNU Lesser General Public License version 3 for more details
19*cdf0e10cSrcweir  * (a copy is included in the LICENSE file that accompanied this code).
20*cdf0e10cSrcweir  *
21*cdf0e10cSrcweir  * You should have received a copy of the GNU Lesser General Public License
22*cdf0e10cSrcweir  * version 3 along with OpenOffice.org.  If not, see
23*cdf0e10cSrcweir  * <http://www.openoffice.org/license.html>
24*cdf0e10cSrcweir  * for a copy of the LGPLv3 License.
25*cdf0e10cSrcweir  *
26*cdf0e10cSrcweir  ************************************************************************/
27*cdf0e10cSrcweir 
28*cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
29*cdf0e10cSrcweir #include "precompiled_bridges.hxx"
30*cdf0e10cSrcweir 
31*cdf0e10cSrcweir #include "jvmaccess/virtualmachine.hxx"
32*cdf0e10cSrcweir #include "rtl/byteseq.h"
33*cdf0e10cSrcweir #include "rtl/byteseq.hxx"
34*cdf0e10cSrcweir #include "rtl/memory.h"
35*cdf0e10cSrcweir #include "rtl/ref.hxx"
36*cdf0e10cSrcweir #include "sal/types.h"
37*cdf0e10cSrcweir #include "uno/threadpool.h"
38*cdf0e10cSrcweir 
39*cdf0e10cSrcweir #include "jni.h"
40*cdf0e10cSrcweir 
41*cdf0e10cSrcweir #include <new>
42*cdf0e10cSrcweir 
43*cdf0e10cSrcweir /* The native implementation part of
44*cdf0e10cSrcweir  * jurt/com/sun/star/lib/uno/environments/remote/NativeThreadPool.java.
45*cdf0e10cSrcweir  */
46*cdf0e10cSrcweir 
47*cdf0e10cSrcweir namespace {
48*cdf0e10cSrcweir 
49*cdf0e10cSrcweir struct Pool {
50*cdf0e10cSrcweir     Pool(rtl::Reference< jvmaccess::VirtualMachine > const & theVirtualMachine,
51*cdf0e10cSrcweir          jmethodID theExecute, uno_ThreadPool thePool):
52*cdf0e10cSrcweir         virtualMachine(theVirtualMachine), execute(theExecute), pool(thePool) {}
53*cdf0e10cSrcweir 
54*cdf0e10cSrcweir     rtl::Reference< jvmaccess::VirtualMachine > virtualMachine;
55*cdf0e10cSrcweir     jmethodID execute;
56*cdf0e10cSrcweir     uno_ThreadPool pool;
57*cdf0e10cSrcweir };
58*cdf0e10cSrcweir 
59*cdf0e10cSrcweir struct Job {
60*cdf0e10cSrcweir     Job(Pool * thePool, jobject theJob): pool(thePool), job(theJob) {}
61*cdf0e10cSrcweir 
62*cdf0e10cSrcweir     Pool * pool;
63*cdf0e10cSrcweir     jobject job;
64*cdf0e10cSrcweir };
65*cdf0e10cSrcweir 
66*cdf0e10cSrcweir void throwOutOfMemory(JNIEnv * env) {
67*cdf0e10cSrcweir     jclass c = env->FindClass("java/lang/OutOfMemoryError");
68*cdf0e10cSrcweir     if (c != 0) {
69*cdf0e10cSrcweir         env->ThrowNew(c, "");
70*cdf0e10cSrcweir     }
71*cdf0e10cSrcweir }
72*cdf0e10cSrcweir 
73*cdf0e10cSrcweir }
74*cdf0e10cSrcweir 
75*cdf0e10cSrcweir extern "C" {
76*cdf0e10cSrcweir 
77*cdf0e10cSrcweir static void SAL_CALL executeRequest(void * data) {
78*cdf0e10cSrcweir     Job * job = static_cast< Job * >(data);
79*cdf0e10cSrcweir     try {
80*cdf0e10cSrcweir         jvmaccess::VirtualMachine::AttachGuard guard(job->pool->virtualMachine);
81*cdf0e10cSrcweir         JNIEnv * env = guard.getEnvironment();
82*cdf0e10cSrcweir         // Failure of the following Job.execute Java call is ignored; if that
83*cdf0e10cSrcweir         // call fails, it should be due to a java.lang.Error, which is not
84*cdf0e10cSrcweir         // handled well, anyway:
85*cdf0e10cSrcweir         env->CallObjectMethod(job->job, job->pool->execute);
86*cdf0e10cSrcweir         env->DeleteGlobalRef(job->job);
87*cdf0e10cSrcweir         delete job;
88*cdf0e10cSrcweir     } catch (jvmaccess::VirtualMachine::AttachGuard::CreationException &) {
89*cdf0e10cSrcweir         //TODO: DeleteGlobalRef(job->job)
90*cdf0e10cSrcweir         delete job;
91*cdf0e10cSrcweir     }
92*cdf0e10cSrcweir }
93*cdf0e10cSrcweir 
94*cdf0e10cSrcweir }
95*cdf0e10cSrcweir 
96*cdf0e10cSrcweir extern "C" JNIEXPORT jbyteArray JNICALL
97*cdf0e10cSrcweir Java_com_sun_star_lib_uno_environments_remote_NativeThreadPool_threadId(
98*cdf0e10cSrcweir     JNIEnv * env, jclass) SAL_THROW_EXTERN_C()
99*cdf0e10cSrcweir {
100*cdf0e10cSrcweir     sal_Sequence * s = 0;
101*cdf0e10cSrcweir     uno_getIdOfCurrentThread(&s); //TODO: out of memory
102*cdf0e10cSrcweir     uno_releaseIdFromCurrentThread();
103*cdf0e10cSrcweir     rtl::ByteSequence seq(s);
104*cdf0e10cSrcweir     rtl_byte_sequence_release(s);
105*cdf0e10cSrcweir     sal_Int32 n = seq.getLength();
106*cdf0e10cSrcweir     jbyteArray a = env->NewByteArray(n);
107*cdf0e10cSrcweir         // sal_Int32 and jsize are compatible here
108*cdf0e10cSrcweir     if (a == 0) {
109*cdf0e10cSrcweir         return 0;
110*cdf0e10cSrcweir     }
111*cdf0e10cSrcweir     void * p = env->GetPrimitiveArrayCritical(a, 0);
112*cdf0e10cSrcweir     if (p == 0) {
113*cdf0e10cSrcweir         return 0;
114*cdf0e10cSrcweir     }
115*cdf0e10cSrcweir     rtl_copyMemory(p, seq.getConstArray(), n);
116*cdf0e10cSrcweir         // sal_Int8 and jbyte ought to be compatible
117*cdf0e10cSrcweir     env->ReleasePrimitiveArrayCritical(a, p, 0);
118*cdf0e10cSrcweir     return a;
119*cdf0e10cSrcweir }
120*cdf0e10cSrcweir 
121*cdf0e10cSrcweir extern "C" JNIEXPORT jlong JNICALL
122*cdf0e10cSrcweir Java_com_sun_star_lib_uno_environments_remote_NativeThreadPool_create(
123*cdf0e10cSrcweir     JNIEnv * env, jclass) SAL_THROW_EXTERN_C()
124*cdf0e10cSrcweir {
125*cdf0e10cSrcweir     JavaVM * vm;
126*cdf0e10cSrcweir     if (env->GetJavaVM(&vm) != JNI_OK) { //TODO: no Java exception raised?
127*cdf0e10cSrcweir         jclass c = env->FindClass("java/lang/RuntimeException");
128*cdf0e10cSrcweir         if (c != 0) {
129*cdf0e10cSrcweir             env->ThrowNew(c, "JNI GetJavaVM failed");
130*cdf0e10cSrcweir         }
131*cdf0e10cSrcweir         return 0;
132*cdf0e10cSrcweir     }
133*cdf0e10cSrcweir     jclass c = env->FindClass("com/sun/star/lib/uno/environments/remote/Job");
134*cdf0e10cSrcweir     if (c == 0) {
135*cdf0e10cSrcweir         return 0;
136*cdf0e10cSrcweir     }
137*cdf0e10cSrcweir     jmethodID execute = env->GetMethodID(c, "execute", "()Ljava/lang/Object;");
138*cdf0e10cSrcweir     if (execute == 0) {
139*cdf0e10cSrcweir         return 0;
140*cdf0e10cSrcweir     }
141*cdf0e10cSrcweir     try {
142*cdf0e10cSrcweir         return reinterpret_cast< jlong >(new Pool(
143*cdf0e10cSrcweir             new jvmaccess::VirtualMachine(vm, env->GetVersion(), false, env),
144*cdf0e10cSrcweir             execute, uno_threadpool_create()));
145*cdf0e10cSrcweir     } catch (std::bad_alloc) {
146*cdf0e10cSrcweir         throwOutOfMemory(env);
147*cdf0e10cSrcweir         return 0;
148*cdf0e10cSrcweir     }
149*cdf0e10cSrcweir }
150*cdf0e10cSrcweir 
151*cdf0e10cSrcweir extern "C" JNIEXPORT void JNICALL
152*cdf0e10cSrcweir Java_com_sun_star_lib_uno_environments_remote_NativeThreadPool_attach(
153*cdf0e10cSrcweir     JNIEnv *, jclass, jlong pool) SAL_THROW_EXTERN_C()
154*cdf0e10cSrcweir {
155*cdf0e10cSrcweir     uno_threadpool_attach(reinterpret_cast< Pool * >(pool)->pool);
156*cdf0e10cSrcweir }
157*cdf0e10cSrcweir 
158*cdf0e10cSrcweir extern "C" JNIEXPORT jobject JNICALL
159*cdf0e10cSrcweir Java_com_sun_star_lib_uno_environments_remote_NativeThreadPool_enter(
160*cdf0e10cSrcweir     JNIEnv * env, jclass, jlong pool) SAL_THROW_EXTERN_C()
161*cdf0e10cSrcweir {
162*cdf0e10cSrcweir     jobject job;
163*cdf0e10cSrcweir     uno_threadpool_enter(
164*cdf0e10cSrcweir         reinterpret_cast< Pool * >(pool)->pool,
165*cdf0e10cSrcweir         reinterpret_cast< void ** >(&job));
166*cdf0e10cSrcweir     if (job == 0) {
167*cdf0e10cSrcweir         return 0;
168*cdf0e10cSrcweir     }
169*cdf0e10cSrcweir     jobject ref = env->NewLocalRef(job);
170*cdf0e10cSrcweir     env->DeleteGlobalRef(job);
171*cdf0e10cSrcweir     return ref;
172*cdf0e10cSrcweir }
173*cdf0e10cSrcweir 
174*cdf0e10cSrcweir extern "C" JNIEXPORT void JNICALL
175*cdf0e10cSrcweir Java_com_sun_star_lib_uno_environments_remote_NativeThreadPool_detach(
176*cdf0e10cSrcweir     JNIEnv *, jclass, jlong pool) SAL_THROW_EXTERN_C()
177*cdf0e10cSrcweir {
178*cdf0e10cSrcweir     uno_threadpool_detach(reinterpret_cast< Pool * >(pool)->pool);
179*cdf0e10cSrcweir }
180*cdf0e10cSrcweir 
181*cdf0e10cSrcweir extern "C" JNIEXPORT void JNICALL
182*cdf0e10cSrcweir Java_com_sun_star_lib_uno_environments_remote_NativeThreadPool_putJob(
183*cdf0e10cSrcweir     JNIEnv * env, jclass, jlong pool, jbyteArray threadId, jobject job,
184*cdf0e10cSrcweir     jboolean request, jboolean oneWay) SAL_THROW_EXTERN_C()
185*cdf0e10cSrcweir {
186*cdf0e10cSrcweir     void * s = env->GetPrimitiveArrayCritical(threadId, 0);
187*cdf0e10cSrcweir     if (s == 0) {
188*cdf0e10cSrcweir         return;
189*cdf0e10cSrcweir     }
190*cdf0e10cSrcweir     rtl::ByteSequence seq(
191*cdf0e10cSrcweir         static_cast< sal_Int8 * >(s), env->GetArrayLength(threadId));
192*cdf0e10cSrcweir         // sal_Int8 and jbyte ought to be compatible; sal_Int32 and jsize are
193*cdf0e10cSrcweir         // compatible here
194*cdf0e10cSrcweir         //TODO: out of memory
195*cdf0e10cSrcweir     env->ReleasePrimitiveArrayCritical(threadId, s, JNI_ABORT);
196*cdf0e10cSrcweir     Pool * p = reinterpret_cast< Pool * >(pool);
197*cdf0e10cSrcweir     jobject ref = env->NewGlobalRef(job);
198*cdf0e10cSrcweir     if (ref == 0) {
199*cdf0e10cSrcweir         return;
200*cdf0e10cSrcweir     }
201*cdf0e10cSrcweir     Job * j = 0;
202*cdf0e10cSrcweir     if (request) {
203*cdf0e10cSrcweir         j = new(std::nothrow) Job(p, ref);
204*cdf0e10cSrcweir         if (j == 0) {
205*cdf0e10cSrcweir             env->DeleteGlobalRef(ref);
206*cdf0e10cSrcweir             throwOutOfMemory(env);
207*cdf0e10cSrcweir             return;
208*cdf0e10cSrcweir         }
209*cdf0e10cSrcweir     }
210*cdf0e10cSrcweir     uno_threadpool_putJob(
211*cdf0e10cSrcweir         p->pool, seq.getHandle(),
212*cdf0e10cSrcweir         request ? static_cast< void * >(j) : static_cast< void * >(ref),
213*cdf0e10cSrcweir         request ? executeRequest : 0, oneWay);
214*cdf0e10cSrcweir }
215*cdf0e10cSrcweir 
216*cdf0e10cSrcweir extern "C" JNIEXPORT void JNICALL
217*cdf0e10cSrcweir Java_com_sun_star_lib_uno_environments_remote_NativeThreadPool_dispose(
218*cdf0e10cSrcweir     JNIEnv *, jclass, jlong pool) SAL_THROW_EXTERN_C()
219*cdf0e10cSrcweir {
220*cdf0e10cSrcweir     uno_threadpool_dispose(reinterpret_cast< Pool * >(pool)->pool);
221*cdf0e10cSrcweir }
222*cdf0e10cSrcweir 
223*cdf0e10cSrcweir extern "C" JNIEXPORT void JNICALL
224*cdf0e10cSrcweir Java_com_sun_star_lib_uno_environments_remote_NativeThreadPool_destroy(
225*cdf0e10cSrcweir     JNIEnv *, jclass, jlong pool) SAL_THROW_EXTERN_C()
226*cdf0e10cSrcweir {
227*cdf0e10cSrcweir     Pool * p = reinterpret_cast< Pool * >(pool);
228*cdf0e10cSrcweir     uno_threadpool_destroy(p->pool);
229*cdf0e10cSrcweir     delete p;
230*cdf0e10cSrcweir }
231