Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Update copyright lines.
[simgrid.git] / src / bindings / java / JavaContext.cpp
index f5f0ffc..39a3070 100644 (file)
-/* context_java - implementation of context switching for java threads */
+/* Context switching within the JVM.                                        */
 
-/* Copyright (c) 2009-2010, 2012-2014. The SimGrid Team.
- * All rights reserved.                                                     */
+/* Copyright (c) 2009-2021. The SimGrid Team. All rights reserved.          */
 
 /* This program is free software; you can redistribute it and/or modify it
  * under the terms of the license (GNU LGPL) which comes with this package. */
 
+#include "JavaContext.hpp"
+#include "jxbt_utilities.hpp"
+#include "simgrid/Exception.hpp"
+#include "src/simix/smx_private.hpp"
+
 #include <functional>
 #include <utility>
 
-#include <xbt/function_types.h>
-#include <simgrid/simix.h>
-#include <xbt/ex.h>
-#include "JavaContext.hpp"
-#include "jxbt_utilities.h"
-#include "xbt/dynar.h"
-#include "../../simix/smx_private.h"
-extern JavaVM *__java_vm;
+extern JavaVM* __java_vm;
 
-XBT_LOG_NEW_DEFAULT_CATEGORY(jmsg, "MSG for Java(TM)");
+XBT_LOG_NEW_DEFAULT_CATEGORY(java, "MSG for Java(TM)");
 
 namespace simgrid {
-namespace java {
+namespace kernel {
+namespace context {
 
-simgrid::simix::ContextFactory* java_factory()
+ContextFactory* java_factory()
 {
   XBT_INFO("Using regular java threads.");
   return new JavaContextFactory();
 }
 
-JavaContextFactory::JavaContextFactory()
-  : ContextFactory("JavaContextFactory")
+JavaContextFactory::JavaContextFactory() : ContextFactory()
 {
+  xbt_assert(xbt::binary_name == "java");
 }
 
-JavaContextFactory::~JavaContextFactory()
-{
-}
+JavaContextFactory::~JavaContextFactory()=default;
 
-JavaContext* JavaContextFactory::self()
+Context* JavaContextFactory::create_context(std::function<void()>&& code, actor::ActorImpl* actor)
 {
-  return (JavaContext*) xbt_os_thread_get_extra_data();
-}
-
-JavaContext* JavaContextFactory::create_context(
-  std::function<void()> code,
-  void_pfn_smxprocess_t cleanup, smx_process_t process)
-{
-  return this->new_context<JavaContext>(std::move(code), cleanup, process);
+  return this->new_context<JavaContext>(std::move(code), actor);
 }
 
 void JavaContextFactory::run_all()
 {
-  xbt_dynar_t processes = SIMIX_process_get_runnable();
-  smx_process_t process;
-  unsigned int cursor;
-  xbt_dynar_foreach(processes, cursor, process) {
-    static_cast<JavaContext*>(SIMIX_process_get_context(process))->resume();
-  }
+  SerialThreadContext::run_all();
 }
 
-JavaContext::JavaContext(std::function<void()> code,
-        void_pfn_smxprocess_t cleanup_func,
-        smx_process_t process)
-  : Context(std::move(code), cleanup_func, process)
+JavaContext::JavaContext(std::function<void()>&& code, smx_actor_t actor)
+    : SerialThreadContext(std::move(code), actor, false /* not maestro */)
 {
-  static int thread_amount=0;
-  thread_amount++;
-
-  /* If the user provided a function for the process then use it otherwise is the context for maestro */
-  if (has_code()) {
-    this->jprocess = nullptr;
-    this->begin = xbt_os_sem_init(0);
-    this->end = xbt_os_sem_init(0);
-
-    TRY {
-       this->thread = xbt_os_thread_create(
-         nullptr, JavaContext::wrapper, this, nullptr);
-    }
-    CATCH_ANONYMOUS {
-      RETHROWF("Failed to create context #%d. You may want to switch to Java coroutines to increase your limits (error: %s)."
-               "See the Install section of simgrid-java documentation (in doc/install.html) for more on coroutines.",
-               thread_amount);
-    }
-  } else {
-    this->thread = nullptr;
-    xbt_os_thread_set_extra_data(this);
-  }
+  /* ThreadContext already does all we need */
 }
 
-JavaContext::~JavaContext()
+void JavaContext::start_hook()
 {
-  if (this->thread) {
-    // We are not in maestro context
-    xbt_os_thread_join(this->thread, nullptr);
-    xbt_os_sem_destroy(this->begin);
-    xbt_os_sem_destroy(this->end);
-  }
-}
+  Context::set_current(this); // We need to attach it also for maestro, in contrary to our ancestor
 
-void* JavaContext::wrapper(void *data)
-{
-  JavaContext* context = (JavaContext*)data;
-  xbt_os_thread_set_extra_data(context);
   //Attach the thread to the JVM
-
   JNIEnv *env;
-  XBT_ATTRIB_UNUSED jint error =
-    __java_vm->AttachCurrentThread((void **) &env, NULL);
+  XBT_ATTRIB_UNUSED jint error = __java_vm->AttachCurrentThread((void**)&env, nullptr);
   xbt_assert((error == JNI_OK), "The thread could not be attached to the JVM");
-  context->jenv = get_current_thread_env();
-  //Wait for the first scheduling round to happen.
-  xbt_os_sem_acquire(context->begin);
-  //Create the "Process" object if needed.
-  (*context)();
-  context->stop();
-  return nullptr;
-}
-
-void JavaContext::stop()
-{
-  /* I am the current process and I am dying */
-  if (this->iwannadie) {
-    this->iwannadie = 0;
-    JNIEnv *env = get_current_thread_env();
-    XBT_DEBUG("Gonna launch Killed Error");
-    // TODO Adrien, if the process has not been created at the java layer, why should we raise the exception/error at the java level (this happens
-    // for instance during the migration process that creates at the C level two processes: one on the SRC node and one on the DST node, if the DST process is killed.
-    // it is not required to raise an exception at the JAVA level, the low level should be able to manage such an issue correctly but this is not the case right now unfortunately ...
-    // TODO it will be nice to have the name of the process to help the end-user to know which Process has been killed
-   // jxbt_throw_by_name(env, "org/simgrid/msg/ProcessKilledError", bprintf("Process %s killed :) (file smx_context_java.c)", MSG_process_get_name( (msg_process_t)context) ));
-    jxbt_throw_by_name(env, "org/simgrid/msg/ProcessKilledError",
-      bprintf("Process %s killed :) (file JavaContext.cpp)",
-      simcall_process_get_name((smx_process_t) SIMIX_context_get_process(this))) );
-    XBT_DEBUG("Trigger a cancel error at the C level");
-    THROWF(cancel_error, 0, "process cancelled");
-  } else {
-    Context::stop();
-    /* detach the thread and kills it */
-    JNIEnv *env = this->jenv;
-    env->DeleteGlobalRef(this->jprocess);
-    XBT_ATTRIB_UNUSED jint error = __java_vm->DetachCurrentThread();
-    xbt_assert((error == JNI_OK), "The thread couldn't be detached.");
-    xbt_os_sem_release(this->end);
-    xbt_os_thread_exit(NULL);
-  }
+  this->jenv_ = env;
 }
 
-void JavaContext::suspend()
+void JavaContext::stop_hook()
 {
-  xbt_os_sem_release(this->end);
-  xbt_os_sem_acquire(this->begin);
-}
-
-// FIXME: inline those functions
-void JavaContext::resume()
-{
-  xbt_os_sem_release(this->begin);
-  xbt_os_sem_acquire(this->end);
+    JNIEnv* env = this->jenv_;
+    env->DeleteGlobalRef(this->jprocess_);
+    jint error = __java_vm->DetachCurrentThread();
+    if (error != JNI_OK) {
+      /* This is probably a Java thread, ie an actor not created from the XML (and thus from the C++),
+       * but from Java with something like new Process().start().
+       *
+       * We should not even try to detach such threads. Instead, we throw a Java exception that will raise up
+       * until run_jprocess(), IIUC.
+       */
+      jxbt_throw_by_name(env, "org/simgrid/msg/ProcessKilledError", "Process killed");
+      XBT_DEBUG("Cannot detach the current thread");
+    }
 }
 
-}
-}
+}}} // namespace simgrid::kernel::context