Sewi has asked for the wisdom of the Perl Monks concerning the following question:

Dear Monks of Perl,
A C (or C++) program needs to have a script language for running simple and complex scripts. I considered Perl, because it can run independent from the programs regular memory space (there is no risk that a script does something bad with the program's memory) and the few interaction commands (like output to user, input from user, get or set some data) could be easily build as a Perl module. The interpreter needs to run within the master program - which could be done by loading the perl lib.
Here is a sample script:
use MasterProgram; MasterProgram::output("Hello World!"); MasterProgram::waitOK(); MasterProgram::clear(); MasterProgram::output("foo bar");
This doesn't really require perl but it is sufficent for demonstation of the problem:
The master starts this script, it shows a message, waits for an OK click and shows another message. While waiting for the OK click, there are two problems:
  • The master must be able to contiue doing other jobs. This could be done at the waitOK() or using threads in the Master, no real problem, but
  • Another instance of the script may be spawned while waiting for the OK-click. Our script run must block until the OK is received (waitOK() will do the blocking), but the other instance must run indepently from this
  • With an expected amount of 1000 - 5000 instances which must run at the same time, one perl instance for every instance isn't an option. There will be about 200 - 500 different fixed scripts. Changing a script may require restarting the master

    My idea was: Split the Perl code in blocks at every blocking command (like waitOK) either manually or using PPI, store each script in an array. Every array element is a anonymus sub-ref to a block including the blocking command. For our example:

    @Script = ( sub { MasterProgram::output("Hello World!"); MasterProgram +::waitOK(); }, sub {MasterProgram::clear(); MasterProgram::output("foo ba +r"); });
    Every script gets one Hash ref for storing all run-time variables which need to survive the whole script. my-variables will end at the next blocking command.
    The master starts an instance by creating a hash, pre-filling some neccessary values and running the first block. Whenever the master wishes to end a blocking command, it runs the next item of the array giving. Every item gets the instance's hash ref as the first argument.

    Question 1: Even if the concept is still in a very early stage and many things need to be considered... would it be possible?
    Question 2: Is there an easier way?

    Thank you.

    Replies are listed 'Best First'.
    Re: Perl as embedded script language
    by Anonymous Monk on Sep 05, 2009 at 00:52 UTC
      Even if the concept is still in a very early stage and many things need to be considered... would it be possible?

      Yes

      Is there an easier way?

      Use javascript ( SpiderApe).

    Re: Perl as embedded script language
    by salva (Canon) on Sep 05, 2009 at 08:41 UTC
      Trying to make your Perl scripts non-blocking preprocessing their source... well, I don't think it is a good idea, at least if you want your scripts to support the language fully and not just a subset. This should be done at the C level, inside the interpreter.

      Coro does half of it, running several perl threads inside the same system thread, the missing part is to rewrite the internal perl opcodes that can block to be non-blocking... though, I don't think this will be easy either.

      In any case, there are languages that natively support this thread model, for instance Python or Stackless Python or Oz that you should also check.

      update: very similar to Coro but at the C level is the GNU pth package. At first look, porting perl to run over this library doesn't look as complex as the alternatives. The idea would be to have several pth-threads at the C level and one independent perl interpreter running inside every one.

        Using Perl and Coro does seem to be the way to go, load Perl + Coro into your application, have each script you need to run be a separate Coro thread (really just a perl context), and when it calls back into your code, suspend that specific thread and unsuspend it on return from your code. You should still avoid Perl code that blocks for other reasons but it wouldn't block on calling back into your code.