tables.c

00001 /* File:      tables.c
00002 ** Author(s): Ernie Johnson
00003 ** Contact:   xsb-contact@cs.sunysb.edu
00004 ** 
00005 ** Copyright (C) The Research Foundation of SUNY, 1986, 1993-1998
00006 ** 
00007 ** XSB is free software; you can redistribute it and/or modify it under the
00008 ** terms of the GNU Library General Public License as published by the Free
00009 ** Software Foundation; either version 2 of the License, or (at your option)
00010 ** any later version.
00011 ** 
00012 ** XSB is distributed in the hope that it will be useful, but WITHOUT ANY
00013 ** WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00014 ** FOR A PARTICULAR PURPOSE.  See the GNU Library General Public License for
00015 ** more details.
00016 ** 
00017 ** You should have received a copy of the GNU Library General Public License
00018 ** along with XSB; if not, write to the Free Software Foundation,
00019 ** Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00020 **
00021 ** $Id: tables.c,v 1.43 2006/03/27 00:13:54 tswift Exp $
00022 ** 
00023 */
00024 
00025 
00026 #include "xsb_config.h"
00027 #include "xsb_debug.h"
00028 
00029 #include "debugs/debug_tables.h"
00030 #include "debugs/debug_delay.h"
00031 
00032 #include <stdio.h>
00033 #include <stdlib.h>
00034 #include <string.h>
00035 
00036 #include "auxlry.h"
00037 #include "cell_xsb.h"
00038 #include "heap_xsb.h"
00039 #include "memory_xsb.h"
00040 #include "register.h"
00041 #include "binding.h"
00042 #include "psc_xsb.h"
00043 #include "table_stats.h"
00044 #include "trie_internals.h"
00045 #include "macro_xsb.h"
00046 #include "error_xsb.h"
00047 #include "flags_xsb.h"
00048 #include "tst_utils.h"
00049 #include "loader_xsb.h" /* for ZOOM_FACTOR, used in stack expansion */
00050 /*#include "subp.h"  for exception_handler, used in stack expansion */
00051 #include "tables.h"
00052 #include "thread_xsb.h"
00053 
00054 #include "sub_tables_xsb_i.h"
00055 #include "debug_xsb.h"
00056 
00057 
00058 /*=========================================================================
00059      This file contains the interface functions to the tabling subsystem
00060   =========================================================================*/
00061 
00062 
00063 /*=========================================================================*/
00064 
00065 /* Engine-Level Tabling Manager Structures
00066    --------------------------------------- */
00067 
00068 /* In the multi-threaded engine, smProdSF and smConsSF will be defined
00069    as their private analogues */
00070 #ifndef MULTI_THREAD
00071 Structure_Manager smProdSF = SM_InitDecl(subsumptive_producer_sf,
00072                                          SUBGOAL_FRAMES_PER_BLOCK,
00073                                          "Subsumptive Producer Subgoal Frame");
00074 
00075 Structure_Manager smConsSF = SM_InitDecl(subsumptive_consumer_sf,
00076                                          SUBGOAL_FRAMES_PER_BLOCK,
00077                                          "Subsumptive Consumer Subgoal Frame");
00078 
00079 #define subsumptive_smALN        smALN
00080 #endif
00081 
00082 Structure_Manager smVarSF  = SM_InitDecl(variant_subgoal_frame,
00083                                          SUBGOAL_FRAMES_PER_BLOCK,
00084                                          "Variant Subgoal Frame");
00085 Structure_Manager smALN    = SM_InitDecl(AnsListNode, ALNs_PER_BLOCK,
00086                                          "Answer List Node");
00087 
00088 /*
00089  * Allocates and initializes a subgoal frame for a producing subgoal.
00090  * The TIP field is initialized, fields of the call trie leaf and this
00091  * subgoal are set to point to one another, while the completion stack
00092  * frame pointer is set to the next available location (frame) on the
00093  * stack (but the space is not yet allocated from the stack).  Also,
00094  * an answer-list node is allocated for pointing to a dummy answer
00095  * node and inserted into the answer list.  Note that answer sets
00096  * (answer tries, roots) are lazily created -- not until an answer is
00097  * generated.  Therefore this field may potentially be NULL, as it is
00098  * initialized here.  memset() is used so that the remaining fields
00099  * are initialized to 0/NULL so, in some sense making this macro
00100  * independent of the number of fields.  
00101 
00102  * In addition, for variant tables, the private/shared field is set.
00103  * This field is used to determine whether to use shared or private
00104  * SMs when adding answers.
00105  */
00106 
00107 #ifndef WIN32
00108 inline 
00109 #endif
00110 VariantSF NewProducerSF(CTXTdeclc BTNptr Leaf,TIFptr TableInfo) {   
00111                                                                         
00112     void *pNewSF;                                                       
00113 
00114     if ( IsVariantPredicate(TableInfo) ) {                              
00115 #ifdef MULTI_THREAD                                                             
00116       if (threads_current_sm == PRIVATE_SM) {                           
00117         SM_AllocateStruct(smVarSF,pNewSF);                              
00118         pNewSF = memset(pNewSF,0,sizeof(variant_subgoal_frame));                
00119         subg_sf_type(pNewSF) = PRIVATE_VARIANT_PRODUCER_SFT;            
00120       } else {                                                          
00121         SM_AllocateSharedStruct(smVarSF,pNewSF);                                
00122         pNewSF = memset(pNewSF,0,sizeof(variant_subgoal_frame));                
00123         subg_sf_type(pNewSF) = SHARED_VARIANT_PRODUCER_SFT;     
00124       }                                                                 
00125     }
00126 #else
00127        SM_AllocateStruct(smVarSF,pNewSF);                              
00128        pNewSF = memset(pNewSF,0,sizeof(variant_subgoal_frame));         
00129        subg_sf_type(pNewSF) = PRIVATE_VARIANT_PRODUCER_SFT;
00130    }
00131 #endif
00132     else {                                                                  
00133      SM_AllocateStruct(smProdSF,pNewSF);                                    
00134      pNewSF = memset(pNewSF,0,sizeof(subsumptive_producer_sf));             
00135      subg_sf_type(pNewSF) = SUBSUMPTIVE_PRODUCER_SFT;                       
00136    }
00137    subg_deltf_ptr(pNewSF) = NULL;
00138    subg_tif_ptr(pNewSF) = TableInfo;                                        
00139    subg_dll_add_sf(pNewSF,TIF_Subgoals(TableInfo),TIF_Subgoals(TableInfo)); 
00140    subg_leaf_ptr(pNewSF) = Leaf;                                            
00141    CallTrieLeaf_SetSF(Leaf,pNewSF);                                         
00142    subg_ans_list_ptr(pNewSF) = empty_return_handle(pNewSF);                  
00143    subg_compl_stack_ptr(pNewSF) = openreg - COMPLFRAMESIZE;                 
00144    return (VariantSF)pNewSF;                                              
00145 }
00146 
00147 /*=========================================================================*/
00148 
00149 /*
00150  *                      Call Check/Insert Operation
00151  *                      ===========================
00152  */
00153 
00154 
00155 /*
00156  * Create an Empty Call Index, represented by a Basic Trie.  Note that
00157  * the root of the trie is labelled with the predicate symbol.
00158  * Assumes that private/shared switch for SMs has been set.
00159  */
00160 
00161 inline static  BTNptr newCallIndex(CTXTdeclc Psc predicate) {
00162 
00163   BTNptr pRoot;
00164 
00165   New_BTN( pRoot, CALL_TRIE_TT, TRIE_ROOT_NT, EncodeTriePSC(predicate),
00166            NULL, NULL );
00167   return pRoot;
00168 }
00169 
00170 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
00171 
00172 /*
00173  * Note that the call index of the TIF is not allocated until the first
00174  * call is entered.  Upon exit, CallLUR_VarVector(*results) points to
00175  * the size of the answer template on the CPS.  See slginsts_xsb_i.h
00176  * for answer template layout.
00177  * Assumes that private/shared switch for SMs has been set.
00178  */
00179 
00180 void table_call_search(CTXTdeclc TabledCallInfo *call_info,
00181                        CallLookupResults *results) {
00182 
00183   TIFptr tif;
00184 
00185   tif = CallInfo_TableInfo(*call_info);
00186   if ( IsNULL(TIF_CallTrie(tif)) )
00187     TIF_CallTrie(tif) = newCallIndex(CTXTc TIF_PSC(tif));
00188   if ( IsVariantPredicate(tif) )
00189     variant_call_search(CTXTc call_info,results);
00190   else
00191     subsumptive_call_search(CTXTc call_info,results);
00192   {
00193     /*
00194      * Copy substitution factor from CPS to Heap.  The arrangement of
00195      * this second s.f.  is similar to that in the CPS: the
00196      * size of the vector is now at the high end, but the components
00197      * are still arranged from high mem (first) to low (last) -- see
00198      * picture at beginning of slginsts_xsb_i.h.  At the return of
00199      * this function, each cell of the heap s.f. will have the same
00200      * value as the corresponding cell in the CPS s.g.  This is done so
00201      * that attvs can be analyzed upon interning answers -- see
00202      * documentation at the beginning of variant_call_search().
00203      */
00204     CPtr tmplt_component, tmplt_var_addr, hrg_addr;
00205     int size, j;
00206 
00207     tmplt_component = CallLUR_VarVector(*results);
00208     size = int_val(*tmplt_component) & 0xffff;
00209     xsb_dbgmsg((LOG_TRIE,
00210                 "done with vcs, answer_template %x\n",tmplt_component));
00211 
00212     /* expand heap if there's not enough space */
00213     if ((pb)top_of_localstk < (pb)top_of_heap + size +
00214         OVERFLOW_MARGIN) {
00215       xsb_abort("{table_call_search} Heap overflow copying answer template");
00216     }
00217 
00218     for ( j = size - 1, tmplt_component = tmplt_component + size;
00219           j >= 0;
00220           j--, tmplt_component-- ) {
00221       tmplt_var_addr = (CPtr)*tmplt_component;
00222       xsb_dbgmsg((LOG_TRIE,"in TSC, copying AT to heap At[%d]: %x val: %x",
00223                   (size-(j)),tmplt_component,tmplt_var_addr));
00224       /* Now we are sure that tmplt_var_addr is a var on the heap */
00225       hrg_addr = hreg+j;
00226       bld_copy(hrg_addr, (Cell)(tmplt_var_addr));
00227     }
00228     hreg += size;
00229     bld_copy(hreg, cell(CallLUR_VarVector(*results)));
00230     hreg++;
00231     /* orig version in tries.c had VarPosReg pointing at Var_{m} */
00232     CallLUR_VarVector(*results) = CallLUR_VarVector(*results) + size + 1;
00233   }
00234 }
00235 
00236 /*=========================================================================*/
00237 
00238 /*
00239  *                      Answer Check/Insert Operation
00240  *                      =============================
00241  */
00242 
00243 
00244 /*
00245  * Template is a pointer to the first term in the vector, with the
00246  * elements arranged from high to low memory.
00247  * Assumes that private/shared switch for SMs has been set.
00248  */
00249 
00250 BTNptr table_answer_search(CTXTdeclc VariantSF producer, int size, int attv_num,
00251                            CPtr templ, xsbBool *is_new) {
00252 
00253   void *answer;
00254 
00255   if ( IsSubsumptiveProducer(producer) ) {
00256     answer =
00257       subsumptive_answer_search(CTXTc (SubProdSF)producer,size,templ,is_new);
00258     if ( *is_new ) {
00259       ALNptr newALN;
00260       New_Private_ALN(newALN,answer,NULL);
00261       SF_AppendNewAnswer(producer,newALN);
00262     }
00263     /*
00264      * Conditional answers could result via dependence upon variant
00265      * subgoals which produce/consume conditional answers.
00266      */
00267     if ( IsNonNULL(delayreg) ) {
00268       fprintf(stdwarn, "\n++Warning: Derivation of conditional answer for "
00269                        "subsumptive subgoal ");
00270       sfPrintGoal(stdwarn, producer, NO);
00271       fprintf(stdwarn, "\n");
00272       if ( *is_new ) {
00273         fprintf(stderr, "++Error: The answer is new: ");
00274         printTriePath(stderr, answer, NO);
00275         fprintf(stderr, "\n");
00276         xsb_abort("Unsupported table operation: conditional-answer insertion");
00277       }
00278       else {
00279         fprintf(stdwarn, "++Warning: Answer is subsumed by: ");
00280         printTriePath(stdwarn, answer, NO);
00281         fprintf(stdwarn, "\n++Warning: Answer is rejected as redundant.  "
00282                          "Continuing...\n");
00283       }
00284     }
00285   }
00286   else {  /* Variant Producer */
00287     /*
00288      * We want to save the substitution factor of the answer in the
00289      * heap, so we have to change variant_answer_search().
00290      */
00291     xsbBool wasFound = TRUE;
00292     
00293 #ifndef IGNORE_DELAYVAR
00294     ans_var_pos_reg = hreg++;   /* Leave a cell for functor ret/n */
00295 #endif /* IGNORE_DELAYVAR */
00296 
00297     answer = variant_answer_search(CTXTc size,attv_num,templ,producer,&wasFound);
00298 
00299 #ifdef DEBUG_DELAYVAR
00300 #ifndef IGNORE_DELAYVAR
00301     fprintf(stddbg, ">>>> ans_var_pos_reg = ");
00302     if (isinteger(cell(ans_var_pos_reg)))
00303       fprintf(stddbg, "\"ret\"\n");
00304     else 
00305       fprintf(stddbg, "%s/%d\n", get_name((Psc)(cell(ans_var_pos_reg))),
00306               get_arity((Psc)(cell(ans_var_pos_reg))));
00307 #endif /* IGNORE_DELAYVAR */
00308 #endif /* DEBUG_DELAYVAR */
00309 
00310     do_delay_stuff(CTXTc (NODEptr)answer, producer, wasFound);
00311 
00312 #ifndef IGNORE_DELAYVAR
00313     undo_answer_bindings(CTXT);
00314 #endif /* IGNORE_DELAYVAR */
00315 
00316     *is_new = ! wasFound;
00317   }
00318   return (BTNptr)answer;
00319 }
00320 
00321 /*=========================================================================*/
00322 
00323 /*
00324  *                          Answer Consumption
00325  *                          ==================
00326  */
00327 
00328 
00329 void table_consume_answer(CTXTdeclc BTNptr answer, int size, int attv_num,
00330                           CPtr templ, TIFptr predicate) {
00331 
00332   if ( size > 0 ) {
00333     if ( IsSubsumptivePredicate(predicate) )
00334       consume_subsumptive_answer(CTXTc answer,size,templ);
00335     else
00336       /* this also tracks variables created during unification */
00337       load_solution_trie(CTXTc size,attv_num,templ,answer);
00338   }
00339   else if ( size == 0 ) {
00340     if ( ! IsEscapeNode(answer) )
00341       xsb_abort("Size of answer template is 0 but producer contains an "
00342                 "answer\nwith a non-empty substitution!\n");
00343   }
00344   else
00345     xsb_abort("table_consume_answer(): "
00346               "Answer template has negative size: %d\n", size);
00347 }
00348 
00349 /*=========================================================================*/
00350 
00351 /*
00352  *                         Answer Identification
00353  *                         =====================
00354  */
00355 
00356 
00357 /*
00358  *  Collects answers from a producer's answer set based on an answer
00359  *  template and a time stamp value.  Collection is performed to
00360  *  replenish the answer cache of a properly subsumed subgoal.
00361  *  Collected answers are placed into the consumer's cache and the time
00362  *  of this collection is noted.  Returns a pointer to the chain of new
00363  *  answers found, or NULL if no answers were found.
00364  */
00365 
00366 ALNptr table_identify_relevant_answers(CTXTdeclc SubProdSF prodSF, SubConsSF consSF,
00367                                        CPtr templ) {
00368 
00369   int size;
00370   TimeStamp ts;         /* for selecting answers from subsumer's AnsTbl */
00371 
00372   TSTNptr tstRoot;      /* TS answer trie root of subsumer */
00373   ALNptr answers;
00374 
00375 
00376 #ifdef DEBUG_ASSERTIONS
00377   if ( ((SubProdSF)consSF == prodSF) || (! IsSubsumptiveProducer(prodSF))
00378        || (! IsProperlySubsumed(consSF)) )
00379     xsb_abort("Relevant Answer Identification apparently triggered for a "
00380               "variant!\nPerhaps SF type is corrupt?");
00381 #endif
00382   size = int_val(*templ);
00383   templ--;  /* all templates on the heap, now --lfcastro */
00384   //  printf("\n"); printAnswerTemplate(stderr,templ,size);
00385   ts = conssf_timestamp(consSF);
00386   tstRoot = (TSTNptr)subg_ans_root_ptr(prodSF);
00387   NumSubOps_IdentifyRelevantAnswers++;
00388   answers = tst_collect_relevant_answers(CTXTc tstRoot,ts,size,templ);
00389   conssf_timestamp(consSF) = TSTN_TimeStamp(tstRoot);
00390   if ( IsNonNULL(answers) )
00391     SF_AppendNewAnswerList(consSF,answers);
00392   return answers;
00393 }
00394 
00395 /*=========================================================================*/
00396 
00397 /*
00398  *                     Table Structure Reclamation
00399  *                     ===========================
00400  */
00401 
00402 /*
00403  *  Deallocate all the data structures which become superfluous once the
00404  *  table has completed.  Currently, this includes the answer list nodes
00405  *  from the producer, and if subsumption was used, the TSIs from the
00406  *  answer set and the answer list nodes from the subsumed subgoals.
00407  *  For the producers, the engine requires that the dummy answer-list
00408  *  node remain, and that its 'next' field be set to either the constant
00409  *  CON_ANSWERS or UNCOND_ANSWERS depending on whether there were any
00410  *  conditional answers in the answer list.  For the subsumed (consumer)
00411  *  subgoals, the entire answer list, including the dummy, is reclaimed.
00412  *
00413  *  For statistical purposes, we check whether the current usage of
00414  *  these incomplete-table structures are new maximums.
00415  *
00416  *  Currently, timestamps from the TSIs are copied back to the TSTNs.
00417  *  Although not necessary, this method has some advantages.  Foremost,
00418  *  this field will never contain garbage values, and so we avoid
00419  *  dangling pointer problems.  Also, maintaining the time stamp values
00420  *  is beneficial for post-completion analysis of the TSTs and
00421  *  characteristics of the query evaluation.
00422  *
00423  *  Multiple calls to this function is avoided by checking a flag in the
00424  *  subgoal frame.  See macro reclaim_incomplete_table_structs() which
00425  *  contains the only reference to this function.
00426  */
00427 
00428 void table_complete_entry(CTXTdeclc VariantSF producerSF) {
00429 
00430   SubConsSF pSF;
00431   ALNptr pRealAnsList, pALN, tag;
00432   TSTHTptr ht;
00433   TSINptr tsi_entry;
00434 
00435   dbg_print_subgoal(LOG_STRUCT_MANAGER, stddbg, producerSF);
00436   xsb_dbgmsg((LOG_STRUCT_MANAGER, " complete... reclaiming structures.\n"));
00437 
00438   if (flags[TRACE_STA])
00439     compute_maximum_tablespace_stats(CTXT);
00440 
00441   /* Reclaim Auxiliary Structures from the TST
00442      ----------------------------------------- */
00443   if ( ProducerSubsumesSubgoals(producerSF) &&
00444        IsNonNULL(subg_ans_root_ptr(producerSF)) )
00445 
00446     for ( ht = TSTRoot_GetHTList(subg_ans_root_ptr(producerSF));
00447           IsNonNULL(ht);  ht = TSTHT_InternalLink(ht) ) {
00448 
00449       /*** Put timestamps back into TSTNs ***/
00450       for ( tsi_entry = TSTHT_IndexHead(ht);  IsNonNULL(tsi_entry);
00451             tsi_entry = TSIN_Next(tsi_entry) )
00452         TSTN_TimeStamp(TSIN_TSTNode(tsi_entry)) = TSIN_TimeStamp(tsi_entry);
00453 
00454       /*** Return TSIN chain to Structure Manager ***/
00455       if ( IsNULL(TSTHT_IndexTail(ht)) ||
00456            IsNonNULL(TSIN_Next(TSTHT_IndexTail(ht))) ||
00457            IsNULL(TSTHT_IndexHead(ht)) ||
00458            IsNonNULL(TSIN_Prev(TSTHT_IndexHead(ht))) )
00459         xsb_warn("Malconstructed TSI");
00460 
00461       xsb_dbgmsg((LOG_STRUCT_MANAGER, "  Reclaiming TS Index\n"));
00462       dbg_smPrint(LOG_STRUCT_MANAGER, smTSIN, "  before chain reclamation");
00463 
00464       /*** Because 'prev' field is first, the tail becomes the list head ***/
00465       SM_DeallocateStructList(smTSIN,TSTHT_IndexTail(ht),TSTHT_IndexHead(ht));
00466       TSTHT_IndexHead(ht) = TSTHT_IndexTail(ht) = NULL;
00467 
00468       dbg_smPrint(LOG_STRUCT_MANAGER, smTSIN, "  after chain reclamation");
00469     }
00470 
00471   /* Reclaim Producer's Answer List
00472      ------------------------------ */
00473   if ( has_answers(producerSF) ) {
00474     pALN = pRealAnsList = subg_answers(producerSF);
00475     tag = UNCOND_ANSWERS;
00476     do {
00477       if ( is_conditional_answer(ALN_Answer(pALN)) ) {
00478         tag = COND_ANSWERS;
00479         break;
00480       }
00481       pALN = ALN_Next(pALN);
00482     } while ( IsNonNULL(pALN) );
00483 #ifndef CONC_COMPL
00484     subg_answers(producerSF) = tag;
00485 #else
00486     subg_tag(producerSF) = tag;
00487 #endif
00488 
00489       xsb_dbgmsg((LOG_STRUCT_MANAGER, "  Reclaiming ALN chain for subgoal\n"));
00490       dbg_smPrint(LOG_STRUCT_MANAGER, smALN, "  before chain reclamation");
00491 
00492     if ( IsNULL(subg_ans_list_tail(producerSF)) ||
00493          IsNonNULL(ALN_Next(subg_ans_list_tail(producerSF))) )
00494       xsb_abort("Answer-List exception: Tail pointer incorrectly maintained");
00495 #ifndef CONC_COMPL
00496 #ifdef MULTI_THREAD
00497     if (IsSharedSF(producerSF)) {                               
00498       SM_DeallocateSharedStructList(smALN,pRealAnsList,
00499                               subg_ans_list_tail(producerSF));
00500     } else {
00501       SM_DeallocateStructList(*private_smALN,pRealAnsList,
00502                               subg_ans_list_tail(producerSF));
00503     }
00504 #else
00505       SM_DeallocateStructList(smALN,pRealAnsList,
00506                               subg_ans_list_tail(producerSF));
00507 #endif
00508     subg_ans_list_tail(producerSF) = NULL;
00509 #endif
00510 
00511     dbg_smPrint(LOG_STRUCT_MANAGER, smALN, "  after chain reclamation");
00512   }
00513 
00514   /* Process its Consumers
00515      --------------------- */
00516   if ( IsSubsumptiveProducer(producerSF) ) {
00517     pSF = subg_consumers(producerSF);
00518 
00519 
00520     if (IsNonNULL(pSF)) {
00521       xsb_dbgmsg((LOG_STRUCT_MANAGER, 
00522                  "Reclaiming structures from consumers of "));
00523       dbg_print_subgoal(LOG_STRUCT_MANAGER, stddbg, producerSF);
00524       xsb_dbgmsg((LOG_STRUCT_MANAGER, "\n"));
00525     }
00526 
00527     while ( IsNonNULL(pSF) ) {
00528 
00529       xsb_dbgmsg((LOG_STRUCT_MANAGER, "  Reclaiming ALN chain for consumer\n"));
00530       dbg_smPrint(LOG_STRUCT_MANAGER, smALN, "  before chain reclamation");
00531 
00532       if ( has_answers(pSF) )    /* real answers exist */
00533         SM_DeallocateStructList(subsumptive_smALN,subg_ans_list_ptr(pSF),
00534                                 subg_ans_list_tail(pSF))
00535       else
00536         SM_DeallocateStruct(subsumptive_smALN,subg_ans_list_ptr(pSF))
00537       dbg_smPrint(LOG_STRUCT_MANAGER, smALN, "  after chain reclamation");
00538 
00539       subg_ans_list_ptr(pSF) = subg_ans_list_tail(pSF) = NULL;
00540       pSF = conssf_consumers(pSF);
00541     }
00542   }
00543 
00544   xsb_dbgmsg((LOG_STRUCT_MANAGER, "Subgoal structure-reclamation complete!\n"));
00545 }
00546 
00547 /*-------------------------------------------------------------------------*/
00548 
00549 /* TLS: I made this into a function and moved it from macro_xsb to
00550    make the tif_list conditional a little more transparent, and to
00551    facilitate debugging. */
00552 
00553 inline TIFptr New_TIF(CTXTdeclc Psc pPSC) {        
00554   TIFptr pTIF;
00555 
00556    pTIF = (TIFptr)mem_alloc(sizeof(TableInfoFrame),TABLE_SPACE);        
00557    if ( IsNULL(pTIF) )                                                  
00558      xsb_abort("Ran out of memory in allocation of TableInfoFrame");    
00559    TIF_PSC(pTIF) = pPSC;                                                
00560    if (get_tabled(pPSC)==T_TABLED) {                                    
00561      TIF_EvalMethod(pTIF) = (TabledEvalMethod)pflags[TABLING_METHOD];   
00562      if (TIF_EvalMethod(pTIF) == VARIANT_EVAL_METHOD)                   
00563        set_tabled(pPSC,T_TABLED_VAR);                                   
00564      else set_tabled(pPSC,T_TABLED_SUB);                                
00565    }                                                                    
00566    else if (get_tabled(pPSC)==T_TABLED_VAR)                             
00567       TIF_EvalMethod(pTIF) = VARIANT_EVAL_METHOD;                       
00568    else if (get_tabled(pPSC)==T_TABLED_SUB)                             
00569      TIF_EvalMethod(pTIF) = SUBSUMPTIVE_EVAL_METHOD;                    
00570    else {                                                               
00571       xsb_warn("%s/%d not identified as tabled in .xwam file, Recompile (variant assumed)", \
00572         get_name(pPSC),get_arity(pPSC));                                
00573       TIF_EvalMethod(pTIF) = VARIANT_EVAL_METHOD;                       
00574       set_tabled(pPSC,T_TABLED_VAR);                                    
00575    }                                                                    
00576    TIF_CallTrie(pTIF) = NULL;                                           
00577    TIF_Mark(pTIF) = 0;                                                  
00578    TIF_DelTF(pTIF) = NULL;                                              
00579    TIF_Subgoals(pTIF) = NULL;                                           
00580    TIF_NextTIF(pTIF) = NULL;                                            
00581 #ifdef MULTI_THREAD
00582    if (get_shared(pPSC)) {
00583      SYS_MUTEX_LOCK( MUTEX_TABLE );                             
00584      if ( IsNonNULL(tif_list.last) )                                    
00585        TIF_NextTIF(tif_list.last) = pTIF;                                     
00586      else                                                                       
00587        tif_list.first = pTIF;                                           
00588      tif_list.last = pTIF;                                              
00589      SYS_MUTEX_UNLOCK( MUTEX_TABLE );                           
00590    } else {
00591      if ( IsNonNULL(private_tif_list.last) )                                    
00592        TIF_NextTIF(private_tif_list.last) = pTIF;                            
00593      else                                                                       
00594        private_tif_list.first = pTIF;                                           
00595      private_tif_list.last = pTIF;                                            
00596    }
00597 #else
00598    if ( IsNonNULL(tif_list.last) )                                      
00599      TIF_NextTIF(tif_list.last) = pTIF;                               
00600    else                                                                 
00601      tif_list.first = pTIF;                                             
00602    tif_list.last = pTIF;                                                
00603 #endif
00604    return pTIF;
00605 }
00606 
00607 /*=========================================================================*/

Generated on Wed Jul 26 13:30:42 2006 for XSB by  doxygen 1.4.5