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