Wizzup?
2009-11-03 18:08:52
I guess this won't be interesting to most of you - but I think it is important to put these problems / ideas general.
NOTE: In the context of threads -> Parent = main thread; child = non main thread; but they belong to the same process.
Introduction:
To be able to run several scripts (or even one) with Mufasa, we need to implement a way to start and stop a script. In this situation we have a Parent (The GUI), and childs. These childs can be a "Thread", or a "Process".
When we use a thread, the memory between the parent and childs is generally shared. A thread can be controlled from the main process; and dies with the Parent. Threads are generally easier to use than Processes, but also less powerful, as they fully depend on the parent. Communication is typically easier with threads, as the main thread has control over the rest of the threads, and can access it memory.
Mufasa uses threads.
Apart from the advantages I just named, there are also disadvantages.
One major disadvantage is that SMART, or rather, the Java VM can only be used once per process; not per thread. So we can't have two threads using a different SMART. I'm sure you can imagine what effect this has. This was even initially a problem; since we used to load Plugins once a script has started, and unloaded them once a script stopped; this stopping (and closing) SMART.
Currently we hacked this into Mufasa, so that plugins are loaded separately from the Script, but can still be used. Another notable fact is that FPC GUI's are only allowed to be run on the main thread, currently we have to perform a LOT of hacking to get it done; and it still allows the scripter to kill the main thread on accident.
A process on the other hand is (totally) independent of it's parent. (Well, not totally, but let's assume it is…)
Running a FPC GUI on a new process is no problem, as we will run the script on the main thread. Another notable advantage is that would could run it in the background; effectively without a GUI. (Client/Server structure anyone?)
We would also be able to run one JVM (SMART) per process, thus effectively running multiple scripts, each with their own smart. To the user this would make no difference, except for the fact that he would see multiple Mufasa processes in his Task Manager. Forking/Starting a new process isn't a problem - but communication is. We could easily start a new process, pass is the script to compile and execute, and it will compile and execute it. Additionally, it can also load libraries it needs. (SMART)
Now, if we want to stop the script, we can simply send a terminate signal, and it will close. This is will also close SMART.
This isn't dangerous, but very annoying to the user. (This is why Raymond and I made the plugins global in the first place!)
–EDIT–
We would start a new process with a "Script Loader Process". GUI -> fork() + exec('scriptloader');
– END-EDIT–
So, there are roughly two solutions.
The first one includes sharing the libraries, and certain memory maps. This can be quite complicated, and it is possibly still affected by the fact that the JVM is limited to one instance per process.
The other solution is excessive communication between the parent process and the child process. We can then make the parent "tell" the client to Stop the script. We then explicitly do not kill the child, thus keeping the libraries (SMART…) loaded. Once again, we would separate the libraries/plugins from the script. (Not a problem, since we only run one script per process now.)
However, PascalScript's .Execute method is blocking. This means we have no easy means to interrupt it's execution. (Killing it is possible, as mentioned above, but this will kill the entire process).
So, the second method is basically the only method we should use for processes. But inter process communication isn't easy, especially with blocking calls.
We could spawn a thread on the new process, that would perform all the communication, and could possibly call .Stop on the main thread. I don't know how stable this would be; as we absolutely wouldn't have any means to safely "Stop" the main the main thread running the script. Killing the main thread basically means killing the process, which we already can do, but then we will kill SMART.
Another solution would be to modify Pascal Script, so that it will perform Inter Process Communication while executing. For example, per line. (Pascal Script has an OnLine event)
This would be doable, I guess… But perhaps I am missing something…
As one can see, the major problems actually occur with SMART; since it is a special instance of a script.
We could also face the fact that SMART will close once we stop a script. But this can be very annoying. But it is definitely a possibility we should consider - as you can see the major problems aside around and with SMART.
If we ought to consider running only one script per Mufasa (GUI!) is a problem; then SCAR seems to have a big problem too.
So perhaps we don't really have a problem?
What are your thoughts?
Technical replies appreciated; but just giving your opinion on what we should do is also welcome.
Quick list:
~Wizz
E: Alternatively, one could change the way SMART works, and turn it into a server, which would manage other smart instances (processes), and allow other processes to attach or detach to these smart instances. This would fully separate SMART from Mufasa. A bit like KYAB I guess. ;)
NOTE: In the context of threads -> Parent = main thread; child = non main thread; but they belong to the same process.
Introduction:
To be able to run several scripts (or even one) with Mufasa, we need to implement a way to start and stop a script. In this situation we have a Parent (The GUI), and childs. These childs can be a "Thread", or a "Process".
When we use a thread, the memory between the parent and childs is generally shared. A thread can be controlled from the main process; and dies with the Parent. Threads are generally easier to use than Processes, but also less powerful, as they fully depend on the parent. Communication is typically easier with threads, as the main thread has control over the rest of the threads, and can access it memory.
Mufasa uses threads.
Apart from the advantages I just named, there are also disadvantages.
One major disadvantage is that SMART, or rather, the Java VM can only be used once per process; not per thread. So we can't have two threads using a different SMART. I'm sure you can imagine what effect this has. This was even initially a problem; since we used to load Plugins once a script has started, and unloaded them once a script stopped; this stopping (and closing) SMART.
Currently we hacked this into Mufasa, so that plugins are loaded separately from the Script, but can still be used. Another notable fact is that FPC GUI's are only allowed to be run on the main thread, currently we have to perform a LOT of hacking to get it done; and it still allows the scripter to kill the main thread on accident.
A process on the other hand is (totally) independent of it's parent. (Well, not totally, but let's assume it is…)
Running a FPC GUI on a new process is no problem, as we will run the script on the main thread. Another notable advantage is that would could run it in the background; effectively without a GUI. (Client/Server structure anyone?)
We would also be able to run one JVM (SMART) per process, thus effectively running multiple scripts, each with their own smart. To the user this would make no difference, except for the fact that he would see multiple Mufasa processes in his Task Manager. Forking/Starting a new process isn't a problem - but communication is. We could easily start a new process, pass is the script to compile and execute, and it will compile and execute it. Additionally, it can also load libraries it needs. (SMART)
Now, if we want to stop the script, we can simply send a terminate signal, and it will close. This is will also close SMART.
This isn't dangerous, but very annoying to the user. (This is why Raymond and I made the plugins global in the first place!)
–EDIT–
We would start a new process with a "Script Loader Process". GUI -> fork() + exec('scriptloader');
– END-EDIT–
So, there are roughly two solutions.
The first one includes sharing the libraries, and certain memory maps. This can be quite complicated, and it is possibly still affected by the fact that the JVM is limited to one instance per process.
The other solution is excessive communication between the parent process and the child process. We can then make the parent "tell" the client to Stop the script. We then explicitly do not kill the child, thus keeping the libraries (SMART…) loaded. Once again, we would separate the libraries/plugins from the script. (Not a problem, since we only run one script per process now.)
However, PascalScript's .Execute method is blocking. This means we have no easy means to interrupt it's execution. (Killing it is possible, as mentioned above, but this will kill the entire process).
So, the second method is basically the only method we should use for processes. But inter process communication isn't easy, especially with blocking calls.
We could spawn a thread on the new process, that would perform all the communication, and could possibly call .Stop on the main thread. I don't know how stable this would be; as we absolutely wouldn't have any means to safely "Stop" the main the main thread running the script. Killing the main thread basically means killing the process, which we already can do, but then we will kill SMART.
Another solution would be to modify Pascal Script, so that it will perform Inter Process Communication while executing. For example, per line. (Pascal Script has an OnLine event)
This would be doable, I guess… But perhaps I am missing something…
As one can see, the major problems actually occur with SMART; since it is a special instance of a script.
We could also face the fact that SMART will close once we stop a script. But this can be very annoying. But it is definitely a possibility we should consider - as you can see the major problems aside around and with SMART.
If we ought to consider running only one script per Mufasa (GUI!) is a problem; then SCAR seems to have a big problem too.
So perhaps we don't really have a problem?
What are your thoughts?
Technical replies appreciated; but just giving your opinion on what we should do is also welcome.
Quick list:
- Stick to what you have, threads. We don't need more than one SMART. Load plugins seperately from script.
- Stick to threads, but load plugins at the start of the script; even if it means closing SMART.
- Switch to processes; and load plugins when the script starts. Don't care is SMART closes.
- Switch to processes; and try to find a way to gracefully stop the script without stopping the process, thus allowing SMART and others to live on. Don't load plugins on script start; but on process start. (Either with another thread; signals; or with OnLine)
- Added: Just do it like SCAR. (A bit like the first option)
- Other, will post
~Wizz
E: Alternatively, one could change the way SMART works, and turn it into a server, which would manage other smart instances (processes), and allow other processes to attach or detach to these smart instances. This would fully separate SMART from Mufasa. A bit like KYAB I guess. ;)