Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Remove extern "C" from cpp files (src/bindings/).
[simgrid.git] / src / bindings / java / jmsg_task.cpp
1 /* Functions related to the java task instances.                            */
2
3 /* Copyright (c) 2007-2018. The SimGrid Team. All rights reserved.          */
4
5 /* This program is free software; you can redistribute it and/or modify it
6  * under the terms of the license (GNU LGPL) which comes with this package. */
7
8 #include "simgrid/s4u/Host.hpp"
9
10 #include "jmsg.hpp"
11 #include "jmsg_host.h"
12 #include "jmsg_process.h"
13 #include "jmsg_task.h"
14 #include "jxbt_utilities.hpp"
15
16 XBT_LOG_EXTERNAL_DEFAULT_CATEGORY(java);
17
18 static jmethodID jtask_method_Comm_constructor;
19
20 static jfieldID jtask_field_Task_bind;
21 static jfieldID jtask_field_Task_name;
22 static jfieldID jtask_field_Task_messageSize;
23 static jfieldID jtask_field_Comm_bind;
24 static jfieldID jtask_field_Comm_taskBind;
25 static jfieldID jtask_field_Comm_receiving;
26
27 void jtask_bind(jobject jtask, msg_task_t task, JNIEnv * env)
28 {
29   env->SetLongField(jtask, jtask_field_Task_bind, (intptr_t)task);
30 }
31
32 msg_task_t jtask_to_native(jobject jtask, JNIEnv* env)
33 {
34   return (msg_task_t)(intptr_t)env->GetLongField(jtask, jtask_field_Task_bind);
35 }
36
37 JNIEXPORT void JNICALL Java_org_simgrid_msg_Task_nativeInit(JNIEnv *env, jclass cls) {
38   jclass jtask_class_Comm = env->FindClass("org/simgrid/msg/Comm");
39   jclass jtask_class_Task = env->FindClass("org/simgrid/msg/Task");
40   xbt_assert(jtask_class_Comm && jtask_class_Task,
41              "Native initialization of msg/Comm or msg/Task failed. Please report that bug");
42
43   jtask_method_Comm_constructor = env->GetMethodID(jtask_class_Comm, "<init>", "()V");
44   jtask_field_Task_bind = jxbt_get_jfield(env, jtask_class_Task, "bind", "J");
45   jtask_field_Task_name = jxbt_get_jfield(env, jtask_class_Task, "name", "Ljava/lang/String;");
46   jtask_field_Task_messageSize = jxbt_get_jfield(env, jtask_class_Task, "messageSize", "D");
47   jtask_field_Comm_bind = jxbt_get_jfield(env, jtask_class_Comm, "bind", "J");
48   jtask_field_Comm_taskBind = jxbt_get_jfield(env, jtask_class_Comm, "taskBind", "J");
49   jtask_field_Comm_receiving = jxbt_get_jfield(env, jtask_class_Comm, "receiving", "Z");
50   xbt_assert(jtask_field_Task_bind && jtask_field_Comm_bind && jtask_field_Comm_taskBind &&
51                  jtask_field_Comm_receiving && jtask_method_Comm_constructor,
52              "Native initialization of msg/Task failed. Please report that bug");
53 }
54
55 JNIEXPORT void JNICALL Java_org_simgrid_msg_Task_create(JNIEnv * env, jobject jtask, jstring jname,
56                                       jdouble jflopsAmount, jdouble jbytesAmount)
57 {
58   const char *name = nullptr;      /* the name of the task                                 */
59
60   if (jname)
61     name = env->GetStringUTFChars(jname, 0);
62   msg_task_t task = MSG_task_create(name, static_cast<double>(jflopsAmount), static_cast<double>(jbytesAmount), jtask);
63   if (jname)
64     env->ReleaseStringUTFChars(jname, name);
65
66   /* bind & store the task */
67   jtask_bind(jtask, task, env);
68 }
69
70 JNIEXPORT void JNICALL Java_org_simgrid_msg_Task_parallelCreate(JNIEnv * env, jobject jtask, jstring jname,
71                                          jobjectArray jhosts, jdoubleArray jcomputeDurations_arg,
72                                          jdoubleArray jmessageSizes_arg)
73 {
74   int host_count = static_cast<int>(env->GetArrayLength(jhosts));
75
76   jdouble* jcomputeDurations = env->GetDoubleArrayElements(jcomputeDurations_arg, 0);
77   msg_host_t* hosts          = new msg_host_t[host_count];
78   double* computeDurations   = new double[host_count];
79   for (int index = 0; index < host_count; index++) {
80     jobject jhost           = env->GetObjectArrayElement(jhosts, index);
81     hosts[index] = jhost_get_native(env, jhost);
82     computeDurations[index] = jcomputeDurations[index];
83   }
84   env->ReleaseDoubleArrayElements(jcomputeDurations_arg, jcomputeDurations, 0);
85
86   jdouble* jmessageSizes = env->GetDoubleArrayElements(jmessageSizes_arg, 0);
87   double* messageSizes   = new double[host_count * host_count];
88   for (int index = 0; index < host_count * host_count; index++) {
89     messageSizes[index] = jmessageSizes[index];
90   }
91   env->ReleaseDoubleArrayElements(jmessageSizes_arg, jmessageSizes, 0);
92
93   /* get the C string from the java string */
94   const char* name = env->GetStringUTFChars(jname, 0);
95   msg_task_t task  = MSG_parallel_task_create(name, host_count, hosts, computeDurations, messageSizes, jtask);
96   env->ReleaseStringUTFChars(jname, name);
97
98   /* associate the java task object and the native task */
99   jtask_bind(jtask, task, env);
100
101   delete[] hosts;
102   delete[] computeDurations;
103   delete[] messageSizes;
104 }
105
106 JNIEXPORT void JNICALL Java_org_simgrid_msg_Task_cancel(JNIEnv * env, jobject jtask)
107 {
108   msg_task_t ptask = jtask_to_native(jtask, env);
109
110   if (not ptask) {
111     jxbt_throw_notbound(env, "task", jtask);
112     return;
113   }
114
115   msg_error_t rv = MSG_task_cancel(ptask);
116
117   jxbt_check_res("MSG_task_cancel()", rv, MSG_OK, "unexpected error , please report this bug");
118 }
119
120 JNIEXPORT void JNICALL Java_org_simgrid_msg_Task_execute(JNIEnv * env, jobject jtask)
121 {
122   msg_task_t task = jtask_to_native(jtask, env);
123
124   if (not task) {
125     jxbt_throw_notbound(env, "task", jtask);
126     return;
127   }
128   msg_error_t rv;
129   rv = MSG_task_execute(task);
130   if (env->ExceptionOccurred())
131     return;
132   if (rv != MSG_OK) {
133     jmsg_throw_status(env, rv);
134   }
135 }
136
137 JNIEXPORT void JNICALL Java_org_simgrid_msg_Task_setBound(JNIEnv * env, jobject jtask, jdouble bound)
138 {
139   msg_task_t task = jtask_to_native(jtask, env);
140
141   if (not task) {
142     jxbt_throw_notbound(env, "task", jtask);
143     return;
144   }
145   MSG_task_set_bound(task, bound);
146 }
147
148 JNIEXPORT jstring JNICALL Java_org_simgrid_msg_Task_getName(JNIEnv * env, jobject jtask) {
149   msg_task_t task = jtask_to_native(jtask, env);
150
151   if (not task) {
152     jxbt_throw_notbound(env, "task", jtask);
153     return nullptr;
154   }
155
156   return env->NewStringUTF(MSG_task_get_name(task));
157 }
158
159 JNIEXPORT jobject JNICALL Java_org_simgrid_msg_Task_getSender(JNIEnv * env, jobject jtask) {
160   msg_process_t process;
161
162   msg_task_t task = jtask_to_native(jtask, env);
163
164   if (not task) {
165     jxbt_throw_notbound(env, "task", jtask);
166     return nullptr;
167   }
168
169   process = MSG_task_get_sender(task);
170   if (process == nullptr) {
171     return nullptr;
172   }
173   return (jobject)jprocess_from_native(process);
174 }
175
176 JNIEXPORT jobject JNICALL Java_org_simgrid_msg_Task_getSource(JNIEnv * env, jobject jtask)
177 {
178   msg_host_t host;
179   msg_task_t task = jtask_to_native(jtask, env);
180
181   if (not task) {
182     jxbt_throw_notbound(env, "task", jtask);
183     return nullptr;
184   }
185
186   host = MSG_task_get_source(task);
187   if (host == nullptr) {
188     return nullptr;
189   }
190   if (not host->extension(JAVA_HOST_LEVEL)) {
191     jxbt_throw_jni(env, "MSG_task_get_source() failed");
192     return nullptr;
193   }
194
195   return (jobject) host->extension(JAVA_HOST_LEVEL);
196 }
197
198 JNIEXPORT jdouble JNICALL Java_org_simgrid_msg_Task_getFlopsAmount(JNIEnv * env, jobject jtask)
199 {
200   msg_task_t ptask = jtask_to_native(jtask, env);
201
202   if (not ptask) {
203     jxbt_throw_notbound(env, "task", jtask);
204     return -1;
205   }
206   return (jdouble)MSG_task_get_flops_amount(ptask);
207 }
208
209 JNIEXPORT void JNICALL Java_org_simgrid_msg_Task_setName(JNIEnv *env, jobject jtask, jobject jname) {
210   msg_task_t task = jtask_to_native(jtask, env);
211
212   if (not task) {
213     jxbt_throw_notbound(env, "task", jtask);
214     return;
215   }
216   const char *name = env->GetStringUTFChars((jstring) jname, 0);
217
218   env->SetObjectField(jtask, jtask_field_Task_name, jname);
219   MSG_task_set_name(task, name);
220
221   env->ReleaseStringUTFChars((jstring) jname, name);
222 }
223
224 JNIEXPORT void JNICALL Java_org_simgrid_msg_Task_setPriority(JNIEnv * env, jobject jtask, jdouble priority)
225 {
226   msg_task_t task = jtask_to_native(jtask, env);
227
228   if (not task) {
229     jxbt_throw_notbound(env, "task", jtask);
230     return;
231   }
232   MSG_task_set_priority(task, static_cast<double>(priority));
233 }
234
235 JNIEXPORT void JNICALL Java_org_simgrid_msg_Task_setFlopsAmount (JNIEnv *env, jobject jtask, jdouble computationAmount)
236 {
237   msg_task_t task = jtask_to_native(jtask, env);
238
239   if (not task) {
240     jxbt_throw_notbound(env, "task", jtask);
241     return;
242   }
243   MSG_task_set_flops_amount(task, static_cast<double>(computationAmount));
244 }
245
246 JNIEXPORT void JNICALL Java_org_simgrid_msg_Task_setBytesAmount (JNIEnv *env, jobject jtask, jdouble dataSize)
247 {
248   msg_task_t task = jtask_to_native(jtask, env);
249
250   if (not task) {
251     jxbt_throw_notbound(env, "task", jtask);
252     return;
253   }
254   env->SetDoubleField(jtask, jtask_field_Task_messageSize, dataSize);
255   MSG_task_set_bytes_amount(task, static_cast<double>(dataSize));
256 }
257
258 JNIEXPORT void JNICALL Java_org_simgrid_msg_Task_sendBounded(JNIEnv * env,jobject jtask, jstring jalias,
259                                                              jdouble jtimeout,jdouble maxrate)
260 {
261   msg_task_t task = jtask_to_native(jtask, env);
262   if (not task) {
263     jxbt_throw_notbound(env, "task", jtask);
264     return;
265   }
266
267   /* Add a global ref into the Ctask so that the receiver can use it */
268   MSG_task_set_data(task, (void *) env->NewGlobalRef(jtask));
269
270   const char* alias = env->GetStringUTFChars(jalias, 0);
271   msg_error_t res =
272       MSG_task_send_with_timeout_bounded(task, alias, static_cast<double>(jtimeout), static_cast<double>(maxrate));
273   env->ReleaseStringUTFChars(jalias, alias);
274
275   if (res != MSG_OK)
276     jmsg_throw_status(env, res);
277 }
278
279 JNIEXPORT jobject JNICALL Java_org_simgrid_msg_Task_receive(JNIEnv* env, jclass cls, jstring jalias, jdouble jtimeout)
280 {
281   msg_task_t task = nullptr;
282
283   const char *alias = env->GetStringUTFChars(jalias, 0);
284   msg_error_t rv    = MSG_task_receive_ext(&task, alias, (double)jtimeout, /*host*/ nullptr);
285   env->ReleaseStringUTFChars(jalias, alias);
286   if (env->ExceptionOccurred())
287     return nullptr;
288   if (rv != MSG_OK) {
289     jmsg_throw_status(env,rv);
290     return nullptr;
291   }
292   jobject jtask_global = (jobject) MSG_task_get_data(task);
293
294   /* Convert the global ref into a local ref so that the JVM can free the stuff */
295   jobject jtask_local = env->NewLocalRef(jtask_global);
296   env->DeleteGlobalRef(jtask_global);
297   MSG_task_set_data(task, nullptr);
298
299   return (jobject) jtask_local;
300 }
301
302 JNIEXPORT jobject JNICALL Java_org_simgrid_msg_Task_irecv(JNIEnv * env, jclass cls, jstring jmailbox) {
303   jclass comm_class = env->FindClass("org/simgrid/msg/Comm");
304   if (not comm_class)
305     return nullptr;
306
307   //pointer to store the task object pointer.
308   msg_task_t* task = new msg_task_t(nullptr);
309   /* There should be a cache here */
310
311   jobject jcomm = env->NewObject(comm_class, jtask_method_Comm_constructor);
312   if (not jcomm) {
313     jxbt_throw_jni(env, "Can't create a Comm object.");
314     return nullptr;
315   }
316
317   const char* mailbox = env->GetStringUTFChars(jmailbox, 0);
318   msg_comm_t comm     = MSG_task_irecv(task, mailbox);
319   env->ReleaseStringUTFChars(jmailbox, mailbox);
320
321   env->SetLongField(jcomm, jtask_field_Comm_bind, (jlong) (uintptr_t)(comm));
322   env->SetLongField(jcomm, jtask_field_Comm_taskBind, (jlong) (uintptr_t)(task));
323   env->SetBooleanField(jcomm, jtask_field_Comm_receiving, JNI_TRUE);
324
325   return jcomm;
326 }
327
328 JNIEXPORT jobject JNICALL Java_org_simgrid_msg_Task_receiveBounded(JNIEnv* env, jclass cls, jstring jalias,
329                                                                    jdouble jtimeout, jdouble rate)
330 {
331   msg_task_t task = nullptr;
332
333   const char *alias = env->GetStringUTFChars(jalias, 0);
334   msg_error_t res   = MSG_task_receive_ext_bounded(&task, alias, static_cast<double>(jtimeout), /*host*/ nullptr,
335                                                  static_cast<double>(rate));
336   if (env->ExceptionOccurred())
337     return nullptr;
338   if (res != MSG_OK) {
339     jmsg_throw_status(env, res);
340     return nullptr;
341   }
342   jobject jtask_global = (jobject)MSG_task_get_data(task);
343
344   /* Convert the global ref into a local ref so that the JVM can free the stuff */
345   jobject jtask_local = env->NewLocalRef(jtask_global);
346   env->DeleteGlobalRef(jtask_global);
347   MSG_task_set_data(task, nullptr);
348
349   env->ReleaseStringUTFChars(jalias, alias);
350
351   return (jobject) jtask_local;
352 }
353
354 JNIEXPORT jobject JNICALL Java_org_simgrid_msg_Task_irecvBounded(JNIEnv * env, jclass cls, jstring jmailbox,
355                                                                  jdouble rate)
356 {
357   jclass comm_class = env->FindClass("org/simgrid/msg/Comm");
358   if (not comm_class)
359     return nullptr;
360
361   // pointer to store the task object pointer.
362   msg_task_t* task = new msg_task_t(nullptr);
363
364   jobject jcomm = env->NewObject(comm_class, jtask_method_Comm_constructor);
365   if (not jcomm) {
366     jxbt_throw_jni(env, "Can't create a Comm object.");
367     return nullptr;
368   }
369
370   const char* mailbox = env->GetStringUTFChars(jmailbox, 0);
371   msg_comm_t comm     = MSG_task_irecv_bounded(task, mailbox, static_cast<double>(rate));
372   env->ReleaseStringUTFChars(jmailbox, mailbox);
373
374   env->SetLongField(jcomm, jtask_field_Comm_bind, (jlong) (uintptr_t)(comm));
375   env->SetLongField(jcomm, jtask_field_Comm_taskBind, (jlong) (uintptr_t)(task));
376   env->SetBooleanField(jcomm, jtask_field_Comm_receiving, JNI_TRUE);
377
378   return jcomm;
379 }
380
381 JNIEXPORT jobject JNICALL Java_org_simgrid_msg_Task_isend(JNIEnv *env, jobject jtask, jstring jmailbox)
382 {
383   msg_comm_t comm;
384
385   jclass comm_class = env->FindClass("org/simgrid/msg/Comm");
386
387   if (not comm_class)
388     return nullptr;
389
390   jobject jcomm       = env->NewObject(comm_class, jtask_method_Comm_constructor);
391   const char* mailbox = env->GetStringUTFChars(jmailbox, 0);
392
393   msg_task_t task = jtask_to_native(jtask, env);
394
395   if (not task) {
396     env->ReleaseStringUTFChars(jmailbox, mailbox);
397     env->DeleteLocalRef(jcomm);
398     jxbt_throw_notbound(env, "task", jtask);
399         return nullptr;
400   }
401
402   MSG_task_set_data(task, (void *) env->NewGlobalRef(jtask));
403   comm = MSG_task_isend(task,mailbox);
404
405   env->SetLongField(jcomm, jtask_field_Comm_bind, (jlong) (uintptr_t)(comm));
406   env->SetLongField(jcomm, jtask_field_Comm_taskBind, (jlong) (uintptr_t)(nullptr));
407   env->SetBooleanField(jcomm, jtask_field_Comm_receiving, JNI_FALSE);
408
409   env->ReleaseStringUTFChars(jmailbox, mailbox);
410
411   return jcomm;
412 }
413
414 JNIEXPORT jobject JNICALL Java_org_simgrid_msg_Task_isendBounded(JNIEnv *env, jobject jtask, jstring jmailbox,
415                                                                  jdouble maxrate)
416 {
417   msg_task_t task;
418   jobject jcomm;
419   msg_comm_t comm;
420   const char *mailbox;
421
422   jclass comm_class = env->FindClass("org/simgrid/msg/Comm");
423   if (not comm_class)
424     return nullptr;
425
426   jcomm = env->NewObject(comm_class, jtask_method_Comm_constructor);
427   mailbox = env->GetStringUTFChars(jmailbox, 0);
428
429   task = jtask_to_native(jtask, env);
430
431   if (not task) {
432     env->ReleaseStringUTFChars(jmailbox, mailbox);
433     env->DeleteLocalRef(jcomm);
434     jxbt_throw_notbound(env, "task", jtask);
435         return nullptr;
436   }
437
438   MSG_task_set_data(task, (void *) env->NewGlobalRef(jtask));
439   comm = MSG_task_isend_bounded(task,mailbox,maxrate);
440
441   env->SetLongField(jcomm, jtask_field_Comm_bind, (jlong) (uintptr_t)(comm));
442   env->SetLongField(jcomm, jtask_field_Comm_taskBind, (jlong) (uintptr_t)(nullptr));
443   env->SetBooleanField(jcomm, jtask_field_Comm_receiving, JNI_FALSE);
444
445   env->ReleaseStringUTFChars(jmailbox, mailbox);
446
447   return jcomm;
448 }
449
450 JNIEXPORT void JNICALL Java_org_simgrid_msg_Task_nativeFinalize(JNIEnv * env, jobject jtask)
451 {
452   msg_task_t task = jtask_to_native(jtask, env);
453
454   if (not task) {
455     jxbt_throw_notbound(env, "task", jtask);
456     return;
457     }
458
459     MSG_task_destroy(task);
460 }
461
462 static void msg_task_cancel_on_failed_dsend(void*t) {
463   msg_task_t task = (msg_task_t) t;
464   JNIEnv *env =get_current_thread_env();
465   jobject jtask_global = (jobject) MSG_task_get_data(task);
466
467   /* Destroy the global ref so that the JVM can free the stuff */
468   env->DeleteGlobalRef(jtask_global);
469   MSG_task_set_data(task, nullptr);
470   MSG_task_destroy(task);
471 }
472
473 JNIEXPORT void JNICALL Java_org_simgrid_msg_Task_dsend(JNIEnv * env, jobject jtask, jstring jalias)
474 {
475   const char *alias = env->GetStringUTFChars(jalias, 0);
476
477   msg_task_t task = jtask_to_native(jtask, env);
478
479   if (not task) {
480     env->ReleaseStringUTFChars(jalias, alias);
481     jxbt_throw_notbound(env, "task", jtask);
482     return;
483   }
484
485   /* Pass a global ref to the Jtask into the Ctask so that the receiver can use it */
486   MSG_task_set_data(task, (void *) env->NewGlobalRef(jtask));
487   MSG_task_dsend(task, alias, msg_task_cancel_on_failed_dsend);
488
489   env->ReleaseStringUTFChars(jalias, alias);
490 }
491
492 JNIEXPORT void JNICALL Java_org_simgrid_msg_Task_dsendBounded(JNIEnv * env, jobject jtask, jstring jalias,
493                                                               jdouble maxrate)
494 {
495   const char *alias = env->GetStringUTFChars(jalias, 0);
496
497   msg_task_t task = jtask_to_native(jtask, env);
498
499   if (not task) {
500     env->ReleaseStringUTFChars(jalias, alias);
501     jxbt_throw_notbound(env, "task", jtask);
502     return;
503   }
504
505   /* Pass a global ref to the Jtask into the Ctask so that the receiver can use it */
506   MSG_task_set_data(task, (void *) env->NewGlobalRef(jtask));
507   MSG_task_dsend_bounded(task, alias, msg_task_cancel_on_failed_dsend,static_cast<double>(maxrate));
508
509   env->ReleaseStringUTFChars(jalias, alias);
510 }
511
512 JNIEXPORT jboolean JNICALL Java_org_simgrid_msg_Task_listen(JNIEnv * env, jclass cls, jstring jalias)
513 {
514   const char *alias = env->GetStringUTFChars(jalias, 0);
515   int rv = MSG_task_listen(alias);
516   env->ReleaseStringUTFChars(jalias, alias);
517
518   return (jboolean) rv;
519 }
520
521 JNIEXPORT jint JNICALL Java_org_simgrid_msg_Task_listenFrom(JNIEnv * env, jclass cls, jstring jalias)
522 {
523   const char *alias = env->GetStringUTFChars(jalias, 0);
524   int rv = MSG_task_listen_from(alias);
525   env->ReleaseStringUTFChars(jalias, alias);
526
527   return (jint) rv;
528 }