11.3.2 Using More than One SICStus Run-Time

Using more than one SICStus run-time in a process is only supported when the dynamic library version of the SICStus run-time is used (e.g, sprt312.dll, libsprt312.so).

An application that wants to use more than one SICStus run-time needs to be built using the --multi-sp-aware option to spld. C-code compiled by spld --multi-sp-aware will have the C preprocessor macro MULTI_SP_AWARE defined and non-zero.

Unlike the single run-time case described above, an application built with --multi-sp-aware will not have a global variable that holds the dispatch vector. Instead, your code will have to take steps to ensure that the appropriate dispatch vector is used when switching between SICStus run-times.

There are several steps needed to access a SICStus run-time from an application built with --multi-sp-aware.

  1. You must obtain the dispatch vector of the initial SICStus run-time using SP_get_dispatch(). Note that this function is special in that it is not accessed through the dispatch vector; instead, it is exported in the ordinary manner from the SICStus run-time dynamic library (sprt312.dll under Windows and, typically, libsprt312.so under UNIX).
  2. You must ensure that SICStusDISPATCHVAR expands to something that references the dispatch vector obtained in step 1.

    The C pre-processor macro SICStusDISPATCHVAR should expand to a SICSTUS_API_STRUCT_TYPE *, that is, a pointer to the dispatch vector that should be used. When --multi-sp-aware is not used SICStusDISPATCHVAR expands to sp_GlobalSICStus as described above. When using --multi-sp-aware it is probably best to let SICStusDISPATCHVAR expand to a local variable.

  3. Once you have access to the SICStus API of the initial SICStus run-time you can call the SICStus API function SP_load_sicstus_run_time() to load additional run-times.
     SICSTUS_API_STRUCT_TYPE *SP_get_dispatch(void *reserved);

SP_get_dispatch() returns the dispatch vector of the SICStus run-time. The argument reserved should be NULL. This function can be called from any thread.

     typedef SICSTUS_API_STRUCT_TYPE *SP_get_dispatch_type(void *);
     
     int SP_load_sicstus_run_time(SP_get_dispatch_type **ppfunc, void **phandle);

SP_load_sicstus_run_time() loads a new SICStus run-time. SP_load_sicstus_run_time() returns zero if a new run-time could not be loaded. If a new run-time could be loaded a non-zero value is returned and the address of the SP_get_dispatch() function of the newly loaded SICStus run-time is stored at the address ppfunc. The second argument, phandle, is reserved and should be NULL.

As a special case, if SP_load_sicstus_run_time() is called from a SICStus run-time that has not been initialized (with SP_initialize()) and that has not previously been loaded as the result of calling SP_load_sicstus_run_time(), then no new run-time is loaded. Instead, the SP_get_dispatch() of the run-time itself is returned. In particular, the first time SP_load_sicstus_run_time() is called on the initial SICStus run-time, and if this happens before the initial SICStus run-time is initialized, then no new run-time is loaded.

Calling SP_load_sicstus_run_time() from a particular run-time can be done from any thread.

An application that links statically with the SICStus run-time should not call SP_load_sicstus_run_time().

You should not use pre-linked foreign resources when using multiple SICStus run-times in the same process.

For an example of loading and using multiple SICStus run-times, see library/jasper/spnative.c that implements this functionality for the Java interface Jasper.