From a1d903e3e9660d84e01b1eddb054582213bd3442 Mon Sep 17 00:00:00 2001 From: Vitor Santos Costa Date: Thu, 21 Jul 2011 06:32:49 -0700 Subject: [PATCH] external term support. --- C/bignum.c | 2 +- C/c_interface.c | 24 +++++++++++++++ H/Yapproto.h | 2 +- docs/yap.tex | 68 +++++++++++++++++++++++++++++++++++------- include/YapInterface.h | 9 ++++++ 5 files changed, 93 insertions(+), 12 deletions(-) diff --git a/C/bignum.c b/C/bignum.c index 2e696df18..9fb1ee5ba 100755 --- a/C/bignum.c +++ b/C/bignum.c @@ -60,7 +60,7 @@ Yap_MkBigIntTerm(MP_INT *big) } Term -Yap_AllocDynamicData(size_t bytes) +Yap_AllocExternalDataInStack(size_t bytes) { CACHE_REGS Int nlimbs; diff --git a/C/c_interface.c b/C/c_interface.c index 0dab6924b..31fc1d051 100755 --- a/C/c_interface.c +++ b/C/c_interface.c @@ -390,6 +390,7 @@ X_API Bool STD_PROTO(YAP_IsDbRefTerm,(Term)); X_API Bool STD_PROTO(YAP_IsAtomTerm,(Term)); X_API Bool STD_PROTO(YAP_IsPairTerm,(Term)); X_API Bool STD_PROTO(YAP_IsApplTerm,(Term)); +X_API Bool STD_PROTO(YAP_IsExternalDataInStackTerm,(Term)); X_API Term STD_PROTO(YAP_MkIntTerm,(Int)); X_API Term STD_PROTO(YAP_MkBigNumTerm,(void *)); X_API Term STD_PROTO(YAP_MkRationalTerm,(void *)); @@ -536,6 +537,8 @@ X_API Term STD_PROTO(YAP_ModuleUser,(void)); X_API Int STD_PROTO(YAP_NumberOfClausesForPredicate,(PredEntry *)); X_API int STD_PROTO(YAP_MaxOpPriority,(Atom, Term)); X_API int STD_PROTO(YAP_OpInfo,(Atom, Term, int, int *, int *)); +X_API Term STD_PROTO(YAP_AllocExternalDataInStack,(size_t)); +X_API void *STD_PROTO(YAP_ExternalDataInStackFromTerm,(Term)); static int (*do_putcf)(wchar_t); @@ -2314,6 +2317,27 @@ YAP_RunGoal(Term t) return(out); } +X_API Term +YAP_AllocExternalDataInStack(size_t bytes) +{ + Term t = Yap_AllocExternalDataInStack(bytes); + if (t == TermNil) + return 0L; + return t; +} + +X_API Bool +YAP_IsExternalDataInStackTerm(Term t) +{ + return IsExternalBlobTerm(t); +} + +X_API void * +YAP_ExternalDataInStackFromTerm(Term t) +{ + return ExternalBlobFromTerm (t); +} + X_API Term YAP_RunGoalOnce(Term t) { diff --git a/H/Yapproto.h b/H/Yapproto.h index 06f855e01..e204341d0 100755 --- a/H/Yapproto.h +++ b/H/Yapproto.h @@ -120,7 +120,7 @@ int STD_PROTO(Yap_IsStringTerm, (Term)); int STD_PROTO(Yap_IsWideStringTerm, (Term)); Term STD_PROTO(Yap_RatTermToApplTerm, (Term)); void STD_PROTO(Yap_InitBigNums, (void)); -Term STD_PROTO(Yap_AllocDynamicData, (size_t)); +Term STD_PROTO(Yap_AllocExternalDataInStack, (size_t)); /* c_interface.c */ Int STD_PROTO(YAP_Execute,(struct pred_entry *, CPredicate)); diff --git a/docs/yap.tex b/docs/yap.tex index 219b19787..1c2076b81 100644 --- a/docs/yap.tex +++ b/docs/yap.tex @@ -16811,13 +16811,29 @@ only two boolean flags are accepted: @code{YAPC_ENABLE_GC} and @code{YAPC_ENABLE_AGC}. The first enables/disables the standard garbage collector, the second does the same for the atom garbage collector.` +@item @code{YAP_TERM} YAP_AllocExternalDataInStack(@code{size_t bytes}) +@item @code{void *} YAP_ExternalDataInStackFromTerm(@code{YAP_Term t}) +@item @code{YAP_Bool} YAP_IsExternalDataInStackTerm(@code{YAP_Term t}) +@findex YAP_AllocExternalDataInStack (C-Interface function) + +The next routines allow one to store external data in the Prolog +execution stack. The first routine reserves space for @var{sz} bytes +and returns an opaque handle. The second routines receives the handle +and returns a pointer to the data. The last routine checks if a term +is an opaque handle. + +Data will be automatically reclaimed during +backtracking. Also, this storage is opaque to the Prolog garbage compiler, +so it should not be used to store Prolog terms. On the other hand, it +may be useful to store arrays in a compact way, or pointers to external objects. + @item @code{int} YAP_HaltRegisterHook(@code{YAP_halt_hook f, void *closure}) @findex YAP_HaltRegisterHook (C-Interface function) Register the function @var{f} to be called if YAP is halted. The -function is called with two arguments: the exit code of the process (@code{0} -if this cannot be determined on your operating system) and the closure -argument @var{closure}. +function is called with two arguments: the exit code of the process +(@code{0} if this cannot be determined on your operating system) and +the closure argument @var{closure}. @c See also @code{at_halt/1}. @end table @@ -16850,6 +16866,7 @@ implementing the predicate and @var{arity} is its arity. @findex YAP_UserBackCutCPredicate (C-Interface function) @findex YAP_PRESERVE_DATA (C-Interface function) @findex YAP_PRESERVED_DATA (C-Interface function) +@findex YAP_PRESERVED_DATA_CUT (C-Interface function) @findex YAP_cutsucceed (C-Interface function) @findex YAP_cutfail (C-Interface function) For the second kind of predicates we need three C functions. The first one @@ -16915,11 +16932,15 @@ static int start_n100(void) @end example The routine starts by getting the dereference value of the argument. -The call to @code{YAP_PRESERVE_DATA} is used to initialize the memory which will -hold the information to be preserved across backtracking. The first -argument is the variable we shall use, and the second its type. Note -that we can only use @code{YAP_PRESERVE_DATA} once, so often we will -want the variable to be a structure. +The call to @code{YAP_PRESERVE_DATA} is used to initialize the memory +which will hold the information to be preserved across +backtracking. The first argument is the variable we shall use, and the +second its type. Note that we can only use @code{YAP_PRESERVE_DATA} +once, so often we will want the variable to be a structure. This data +is visible to the garbage collector, so it should consist of Prolog +terms, as in the example. It is also correct to store pointers to +objects external to YAP stacks, as the garbage collector will ignore +such references. If the argument of the predicate is a variable, the routine initializes the structure to be preserved across backtracking with the information @@ -16988,6 +17009,34 @@ when pruning the execution of the predicate, @var{arity} is the predicate arity, and @var{sizeof} is the size of the data to be preserved in the stack. In this example, we would have something like +@example +void +init_n100(void) +@{ + YAP_UserBackCutCPredicate("n100", start_n100, continue_n100, cut_n100, 1, 1); +@} +@end example +The argument before last is the predicate's arity. Notice again the +last argument to the call. function argument gives the extra space we +want to use for @code{PRESERVED_DATA}. Space is given in cells, where +a cell is the same size as a pointer. The garbage collector has access +to this space, hence users should use it either to store terms or to +store pointers to objects outside the stacks. + +The code for @code{cut_n100} could be: +@example +static int cut_n100(void) +@{ + YAP_PRESERVED_DATA_CUT(n100_data,n100_data_type*); + + fprintf("n100 cut with counter %ld\n", YAP_IntOfTerm(n100_data->next_solution)); + return TRUE; +@} +@end example +Notice that we have to use @code{YAP_PRESERVED_DATA_CUT}: this is +because the Prolog engine is at a different state during cut. + +If no work is required at cut, we can use: @example void init_n100(void) @@ -16995,8 +17044,7 @@ init_n100(void) YAP_UserBackCutCPredicate("n100", start_n100, continue_n100, NULL, 1, 1); @} @end example -Notice that we do not actually need to do anything on receiving a cut in -this case. +in this case no code is executed at cut time. @node Loading Objects, Save&Rest, Writing C, C-Interface @section Loading Object Files diff --git a/include/YapInterface.h b/include/YapInterface.h index 93897689a..1267e99d6 100755 --- a/include/YapInterface.h +++ b/include/YapInterface.h @@ -555,6 +555,15 @@ extern X_API int PROTO(YAP_MaxOpPriority,(YAP_Atom, YAP_Term)); /* int YAP_OpInfo(Atom, Term, int, int *, int *) */ extern X_API int PROTO(YAP_OpInfo,(YAP_Atom, YAP_Term, int, int *, int *)); +/* YAP_Bool YAP_IsExternalDataInStackTerm(YAP_Term) */ +extern X_API YAP_Bool PROTO(YAP_IsExternalDataInStackTerm,(YAP_Term)); + +/* Term YAP_AllocExternalDataInStack(size_t) */ +extern X_API YAP_Term PROTO(YAP_AllocExternalDataInStack,(size_t)); + +/* void *YAP_ExternalDataInStackFromTerm(YAP_Term) */ +extern X_API void *PROTO(YAP_ExternalDataInStackFromTerm,(YAP_Term)); + #define YAP_InitCPred(N,A,F) YAP_UserCPredicate(N,F,A) __END_DECLS