Node:Multiple SICStus Run-Times in C, Next:Foreign Resources and Multiple SICStus Run-Times, Previous:Multiple SICStus Run-Times in Java, Up:Multiple SICStus Run-Times
Unless otherwise noted, this section documents the behavior when using dynamic linking to access a SICStus run-time.
The key implementation feature that makes it possible to use multiple
run-times is that all calls from C to the SICStus API (SP_query,
etc.) go through a dispatch vector. Two run-times can be loaded at the
same time since their APIs are accessed through different dispatch vectors.
By default, there will be a single dispatch vector, referenced from a
global variable (sp_GlobalSICStus). A SICStus API functions, such
as SP_query, is then defined as a macro that expands to something
similar to sp_GlobalSICStus->SP_query_pointer.
The name of the global dispatch vector is subject to change without
notice; it should not be referenced directly. If you need to access the
dispatch vector, use the C macro SICStusDISPATCHVAR instead, see
below.
When building an application with spld, by default
only one SICStus run-time can be loaded in the process. This is
similar to the case in SICStus versions prior to 3.9. For most
applications built with spld, the changes necessary to support
multiple SICStus run-times should be invisible, and old code should only
need to be rebuilt with spld.
In order to maintain backward compatibility, the global dispatch vector
is automatically set up by SP_initialize. Other SICStus API
functions will not set up the dispatch vector, and will therefore lead to
memory access errors if called before SP_initialize. Currently,
hook functions such as SP_set_memalloc_hooks also set up the
dispatch vector to allow them to be called before
SP_initialize. However, only SP_initialize is guaranteed
to set up the dispatch vector. The hook installation functions may
change to use a different mechanism in the future. The SICStus API
functions that perform automatic setup of the dispatch vector are
marked with SPEXPFLAG_PREINIT in sicstus.h.
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,
sprt39.dll, libsprt39.so).
An application that wants to use more than one SICStus run-time needs to
be built using the --multi-sp-aware argument 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.
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
(sprt39.dll on Windows and, typically, libsprt39.so on UNIX).
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.
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.