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.