X-Git-Url: http://info.iut-bm.univ-fcomte.fr/pub/gitweb/simgrid.git/blobdiff_plain/bc48db087894fd960073b3120cebf90e6b2f8c02..ea74f5d95928a521a588737e81f1de94eef25d19:/src/bindings/java/org/simgrid/msg/Process.java diff --git a/src/bindings/java/org/simgrid/msg/Process.java b/src/bindings/java/org/simgrid/msg/Process.java index 42d1276671..66eb168f86 100644 --- a/src/bindings/java/org/simgrid/msg/Process.java +++ b/src/bindings/java/org/simgrid/msg/Process.java @@ -1,29 +1,28 @@ -/* Copyright (c) 2006-2014. The SimGrid Team. - * All rights reserved. */ +/* Copyright (c) 2006-2022. 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. */ package org.simgrid.msg; +import java.util.ArrayList; import java.util.Arrays; -import java.util.Vector; /** - * A process may be defined as a code, with some private data, executing + * A process may be defined as a code, with some private data, executing * in a location (host). All the process used by your simulation must be * declared in the deployment file (XML format). - * To create your own process you must inherit your own process from this - * class and override the method "main()". For example if you want to use - * a process named Slave proceed as it : + * To create your own process you must inherit your own process from this + * class and override the method "main()". For example if you want to use + * a process named Worker proceed as it : * * (1) import the class Process of the package simgrid.msg * import simgrid.msg.Process; - * - * public class Slave extends simgrid.msg.Process { + * + * public class Worker extends simgrid.msg.Process { * * (2) Override the method function - * + * * \verbatim * public void main(String[] args) { * System.out.println("Hello MSG"); @@ -31,13 +30,13 @@ import java.util.Vector; * \endverbatim * } * The name of your process must be declared in the deployment file of your simulation. - * For the example, for the previous process Slave this file must contains a line : - * <process host="Maxims" function="Slave"/>, where Maxims is the host of the process - * Slave. All the process of your simulation are automatically launched and managed by Msg. - * A process use tasks to simulate communications or computations with another process. - * For more information see Task. For more information on host concept + * For the example, for the previous process Worker this file must contains a line : + * <process host="Maxims" function="Worker"/>, where Maxims is the host of the process + * Worker. All the process of your simulation are automatically launched and managed by Msg. + * A process use tasks to simulate communications or computations with another process. + * For more information see Task. For more information on host concept * see Host. - * + * */ public abstract class Process implements Runnable { @@ -46,175 +45,137 @@ public abstract class Process implements Runnable { * a native process. Even if this attribute is public you must never * access to it. It is set automatically during the build of the object. */ - private long bind; + private long bind = 0; /** Indicates if the process is started */ - boolean started; - /** - * Even if this attribute is public you must never access to it. - * It is used to compute the id of an MSG process. - */ - public static long nextProcessId = 0; - - /** - * Even if this attribute is public you must never access to it. - * It is compute automatically during the creation of the object. - * The native functions use this identifier to synchronize the process. - */ - private long id; /** Time at which the process should be created */ protected double startTime = 0; - /** Time at which the process should be killed. - * - * Set at creation, and used internally by SimGrid - */ - private double killTime = -1; + /** Time at which the process should be killed */ + private double killTime = -1; // Used from the C world + + private String name = null; - private String name; - private int pid = -1; private int ppid = -1; private Host host = null; - /** The arguments of the method function of the process. */ - public Vector args; - - - /** Default constructor */ - protected Process() { - this.id = nextProcessId++; - this.name = null; - this.bind = 0; - this.args = new Vector(); - } - + /** The arguments of the method function of the process. */ + private ArrayList args = new ArrayList<>(); /** * Constructs a new process from the name of a host and his name. The method * function of the process doesn't have argument. * - * @param hostname The name of the host of the process to create. + * @param hostname Where to create the process. * @param name The name of the process. * * @exception HostNotFoundException if no host with this name exists. - * + * * */ - public Process(String hostname, String name) throws HostNotFoundException { + protected Process(String hostname, String name) throws HostNotFoundException { this(Host.getByName(hostname), name, null); } /** * Constructs a new process from the name of a host and his name. The arguments * of the method function of the process are specified by the parameter args. * - * @param hostname The name of the host of the process to create. + * @param hostname Where to create the process. * @param name The name of the process. * @param args The arguments of the main function of the process. * * @exception HostNotFoundException if no host with this name exists. - * NativeException - * @throws NativeException * - */ - public Process(String hostname, String name, String args[]) throws HostNotFoundException, NativeException { + */ + protected Process(String hostname, String name, String[] args) throws HostNotFoundException { this(Host.getByName(hostname), name, args); } /** - * Constructs a new process from a host and his name. The method function of the + * Constructs a new process from a host and his name. The method function of the * process doesn't have argument. * - * @param host The host of the process to create. + * @param host Where to create the process. * @param name The name of the process. * */ - public Process(Host host, String name) { + protected Process(Host host, String name) { this(host, name, null); } /** * Constructs a new process from a host and his name, the arguments of here method function are * specified by the parameter args. * - * @param host The host of the process to create. + * @param host Where to create the process. * @param name The name of the process. - * @param args The arguments of main method of the process. - */ - public Process(Host host, String name, String[]args) { - this(); - this.host = host; + * @param argsParam The arguments of main method of the process. + */ + protected Process(Host host, String name, String[]argsParam) + { if (host == null) - throw new NullPointerException("Process name cannot be NULL"); + throw new IllegalArgumentException("Cannot create a process on the null host"); if (name == null) - throw new NullPointerException("Process name cannot be NULL"); + throw new IllegalArgumentException("Process name cannot be null"); + + this.host = host; this.name = name; - this.args = new Vector(); - if (null != args) - this.args.addAll(Arrays.asList(args)); - } + this.args = new ArrayList<>(); + if (null != argsParam) + this.args.addAll(Arrays.asList(argsParam)); + } /** * Constructs a new process from a host and his name, the arguments of here method function are * specified by the parameter args. * - * @param host The host of the process to create. + * @param host Where to create the process. * @param name The name of the process. * @param args The arguments of main method of the process. * @param startTime Start time of the process * @param killTime Kill time of the process * */ - public Process(Host host, String name, String[]args, double startTime, double killTime) { - this(); - this.host = host; - if (host == null) - throw new NullPointerException("Process name cannot be NULL"); - if (name == null) - throw new NullPointerException("Process name cannot be NULL"); - this.name = name; - - this.args = new Vector(); - if (null != args) - this.args.addAll(Arrays.asList(args)); - + protected Process(Host host, String name, String[]args, double startTime, double killTime) { + this(host, name, args); this.startTime = startTime; - this.killTime = killTime; + this.killTime = killTime; } /** - * The natively implemented method to create an MSG process. - * @param hostName A valid (bound) host where create the process. + * The native method to create an MSG process. + * @param host where to create the process. */ - protected native void create(String hostName) throws HostNotFoundException; + protected native void create(Host host); + /** * This method kills all running process of the simulation. - * - * @param resetPID Should we reset the PID numbers. A negative number means no reset - * and a positive number will be used to set the PID of the next newly - * created process. - * - * @return The function returns the PID of the next created process. - * - */ - public static native int killAll(int resetPID); + */ + public static native void killAll(); /** Simply kills the receiving process. * * SimGrid sometimes have issues when you kill processes that are currently communicating and such. We are working on it to fix the issues. */ public native void kill(); - + public static void kill(Process p) { + p.kill(); + } + /** Suspends the process. See {@link #resume()} to resume it afterward */ public native void suspend(); /** Resume a process that was suspended by {@link #suspend()}. */ - public native void resume(); + public native void resume(); /** Tests if a process is suspended. * - * @see #suspend() - * @see #resume() + * @see suspend() + * @see resume() */ public native boolean isSuspended(); - + + /** Yield the current process. All other processes that are ready at the same timestamp will be executed first */ + public static native void yield(); + /** * Specify whether the process should restart when its host restarts after a failure - * + * * A process naturally stops when its host stops. It starts again only if autoRestart is set to true. * Otherwise, it just disappears when the host stops. */ @@ -230,40 +191,43 @@ public abstract class Process implements Runnable { /** * Returns the host of the process. * @return The host instance of the process. - */ + */ public Host getHost() { return this.host; } /** * This static method gets a process from a PID. * - * @param PID The process identifier of the process to get. + * @param pid The process identifier of the process to get. * * @return The process with the specified PID. - * - * @exception NativeException on error in the native SimGrid code - */ - public static native Process fromPID(int PID) throws NativeException; + */ + public static native Process fromPID(int pid); /** * This method returns the PID of the process. * * @return The PID of the process. * - */ + */ public int getPID() { + if (pid == -1) // Don't traverse the JNI barrier if you already have the answer + pid = nativeGetPID(); return pid; } + // This should not be used: the PID is supposed to be initialized from the C directly when the actor is created, + // but this sometimes fail, so let's play nasty but safe here. + private native int nativeGetPID(); /** * This method returns the PID of the parent of a process. * * @return The PID of the parent of the process. * - */ + */ public int getPPID() { return ppid; } /** - * Returns the value of a given process property. + * Returns the value of a given process property. */ public native String getProperty(String name); @@ -278,7 +242,7 @@ public abstract class Process implements Runnable { * * @return The current process. * - */ + */ public static native Process getCurrentProcess(); /** * Migrates a process to another host. @@ -286,75 +250,70 @@ public abstract class Process implements Runnable { * @param host The host where to migrate the process. * */ - public native void migrate(Host host); + public native void migrate(Host host); /** - * Makes the current process sleep until millis millisecondes have elapsed. - * You should note that unlike "waitFor" which takes seconds, this method takes milliseconds. - * FIXME: Not optimal, maybe we should have two native functions. + * Makes the current process sleep until millis milliseconds have elapsed. + * You should note that unlike "waitFor" which takes seconds (as usual in SimGrid), this method takes milliseconds (as usual for sleep() in Java). + * * @param millis the length of time to sleep in milliseconds. */ public static void sleep(long millis) throws HostFailureException { sleep(millis,0); } /** - * Makes the current process sleep until millis milliseconds and nanos nanoseconds + * Makes the current process sleep until millis milliseconds and nanos nanoseconds * have elapsed. - * Unlike {@link #waitFor(double)} which takes seconds, this method takes + * Unlike {@link #waitFor(double)} which takes seconds, this method takes * milliseconds and nanoseconds. * Overloads Thread.sleep. * @param millis the length of time to sleep in milliseconds. - * @param nanos additionnal nanoseconds to sleep. + * @param nanos additional nanoseconds to sleep. */ - public native static void sleep(long millis, int nanos) throws HostFailureException; + public static native void sleep(long millis, int nanos) throws HostFailureException; /** * Makes the current process sleep until time seconds have elapsed. * @param seconds The time the current process must sleep. - */ - public native void waitFor(double seconds) throws HostFailureException; + */ + public native void waitFor(double seconds) throws HostFailureException; /** * This method actually creates and run the process. * It is a noop if the process is already launched. - * @throws HostNotFoundException */ - public final void start() throws HostNotFoundException { - if (!started) { - started = true; - create(host.getName()); - } + public final void start() { + if (bind == 0) + create(host); } - /** This method runs the process. Il calls the method function that you must overwrite. */ + /** This method runs the process. It calls the method function that you must overwrite. */ @Override public void run() { - String[] args = null; /* do not fill it before the signal or this.args will be empty */ - try { - args = new String[this.args.size()]; - if (this.args.size() > 0) { - this.args.toArray(args); - } + String[] argsArray = new String[this.args.size()]; + this.args.toArray(argsArray); - this.main(args); - } catch(MsgException e) { + this.main(argsArray); + } + catch(MsgException e) { e.printStackTrace(); Msg.info("Unexpected behavior. Stopping now"); System.exit(1); } - catch(ProcessKilledError pk) { - } - exit(); + /* Let the ProcessKilledError (that we'd get if the process is forcefully killed) flow back to the caller */ } /** - * The main function of the process (to implement). + * The main function of the process (to implement by the user). * * @param args * @throws MsgException */ public abstract void main(String[]args) throws MsgException; - public native void exit(); + /** Stops the execution of the current actor */ + public void exit() { + this.kill(); + } /** * Class initializer, to initialize various JNI stuff */ @@ -367,7 +326,13 @@ public abstract class Process implements Runnable { * This static method returns the current amount of processes running * * @return The count of the running processes - */ - public native static int getCount(); + */ + public static native int getCount(); + public static void debugAllThreads() { + // Search remaining threads that are not main nor daemon + for (Thread t : Thread.getAllStackTraces().keySet()) + if (! t.isDaemon() && !t.getName().equals("main")) + System.err.println("Thread "+t.getName()+" is still running! Please report that bug"); + } }