610 lines
		
	
	
		
			20 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			610 lines
		
	
	
		
			20 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/************************************************************************
 | 
						|
**                                                                     **
 | 
						|
**                   The YapTab/YapOr/OPTYap systems                   **
 | 
						|
**                                                                     **
 | 
						|
** YapTab extends the Yap Prolog engine to support sequential tabling  **
 | 
						|
** YapOr extends the Yap Prolog engine to support or-parallelism       **
 | 
						|
** OPTYap extends the Yap Prolog engine to support or-parallel tabling **
 | 
						|
**                                                                     **
 | 
						|
**                                                                     **
 | 
						|
**      Yap Prolog was developed at University of Porto, Portugal      **
 | 
						|
**                                                                     **
 | 
						|
************************************************************************/
 | 
						|
 | 
						|
/* -------------------- **
 | 
						|
**      Prototypes      **
 | 
						|
** -------------------- */
 | 
						|
 | 
						|
/* get a def for NULL */
 | 
						|
#include <stdlib.h>
 | 
						|
 | 
						|
static inline void PUT_IN_EXECUTING(int);
 | 
						|
static inline void PUT_OUT_EXECUTING(int);
 | 
						|
static inline void PUT_IN_FINISHED(int);
 | 
						|
#ifdef TABLING_INNER_CUTS
 | 
						|
static inline void PUT_IN_PRUNING(int);
 | 
						|
static inline void PUT_OUT_PRUNING(int);
 | 
						|
#endif /* TABLING_INNER_CUTS */
 | 
						|
 | 
						|
static inline void PUT_IN_REQUESTABLE(int);
 | 
						|
static inline void PUT_OUT_REQUESTABLE(int);
 | 
						|
static inline void SCH_update_local_or_tops(void);
 | 
						|
static inline void SCH_refuse_share_request_if_any(void);
 | 
						|
static inline void SCH_set_load(choiceptr);
 | 
						|
static inline void SCH_new_alternative(yamop *,yamop *);
 | 
						|
 | 
						|
static inline void CUT_send_prune_request(int, choiceptr);
 | 
						|
static inline void CUT_reset_prune_request(void);
 | 
						|
 | 
						|
static inline int CUT_last_worker_left_pending_prune(or_fr_ptr);
 | 
						|
static inline or_fr_ptr CUT_leftmost_or_frame(void);
 | 
						|
#ifdef TABLING_INNER_CUTS
 | 
						|
static inline or_fr_ptr CUT_leftmost_until(or_fr_ptr, int);
 | 
						|
#endif /* TABLING_INNER_CUTS */
 | 
						|
 | 
						|
static inline void CUT_store_answer(or_fr_ptr, qg_ans_fr_ptr);
 | 
						|
static inline void CUT_store_answers(or_fr_ptr, qg_sol_fr_ptr);
 | 
						|
static inline void CUT_join_answers_in_an_unique_frame(qg_sol_fr_ptr);
 | 
						|
static inline void CUT_free_solution_frame(qg_sol_fr_ptr);
 | 
						|
static inline void CUT_free_solution_frames(qg_sol_fr_ptr);
 | 
						|
static inline qg_sol_fr_ptr CUT_prune_solution_frames(qg_sol_fr_ptr, int);
 | 
						|
 | 
						|
 | 
						|
 | 
						|
/* ---------------------------- **
 | 
						|
**      Instruction Macros      **
 | 
						|
** ---------------------------- */
 | 
						|
 | 
						|
#if SIZEOF_INT == 2
 | 
						|
#define YAMOP_CUT_FLAG    0x8000
 | 
						|
#define YAMOP_SEQ_FLAG    0x4000
 | 
						|
#define YAMOP_FLAGS_BITS  0xc000
 | 
						|
#define YAMOP_LTT_BITS    0x3fff
 | 
						|
#elif SIZEOF_INT == 4
 | 
						|
#define YAMOP_CUT_FLAG    0x80000000
 | 
						|
#define YAMOP_SEQ_FLAG    0x40000000
 | 
						|
#define YAMOP_FLAGS_BITS  0xc0000000
 | 
						|
#define YAMOP_LTT_BITS    0x3fffffff
 | 
						|
#elif SIZEOF_INT == 8
 | 
						|
#define YAMOP_CUT_FLAG    0x8000000000000000
 | 
						|
#define YAMOP_SEQ_FLAG    0x4000000000000000
 | 
						|
#define YAMOP_FLAGS_BITS  0xc000000000000000
 | 
						|
#define YAMOP_LTT_BITS    0x3fffffffffffffff
 | 
						|
#else
 | 
						|
#define YAMOP_CUT_FLAG    OOOOPPS!!! Unknown Integer Sizeof
 | 
						|
#define YAMOP_SEQ_FLAG    OOOOPPS!!! Unknown Integer Sizeof
 | 
						|
#define YAMOP_FLAGS_BITS  OOOOPPS!!! Unknown Integer Sizeof
 | 
						|
#define YAMOP_LTT_BITS    OOOOPPS!!! Unknown Integer Sizeof
 | 
						|
#endif /* SIZEOF_INT */
 | 
						|
 | 
						|
#define YAMOP_OR_ARG(INST)         ((INST)->u.Otapl.or_arg)
 | 
						|
#define YAMOP_LTT(INST)            (((INST)->u.Otapl.or_arg) & YAMOP_LTT_BITS)
 | 
						|
#define YAMOP_SEQ(INST)            (((INST)->u.Otapl.or_arg) & YAMOP_SEQ_FLAG)
 | 
						|
#define YAMOP_CUT(INST)            (((INST)->u.Otapl.or_arg) & YAMOP_CUT_FLAG)
 | 
						|
#define YAMOP_FLAGS(INST)          (((INST)->u.Otapl.or_arg) & YAMOP_FLAGS_BITS)
 | 
						|
 | 
						|
#define INIT_YAMOP_LTT(INST, LTT)  ((INST)->u.Otapl.or_arg = LTT+1)
 | 
						|
#define PUT_YAMOP_LTT(INST, LTT)   (INST)->u.Otapl.or_arg = YAMOP_FLAGS(INST) | (LTT+1)
 | 
						|
#define PUT_YAMOP_SEQ(INST)        (INST)->u.Otapl.or_arg |= YAMOP_SEQ_FLAG
 | 
						|
#define PUT_YAMOP_CUT(INST)        (INST)->u.Otapl.or_arg |= YAMOP_CUT_FLAG
 | 
						|
 | 
						|
#define BRANCH(WORKER, DEPTH)      GLOBAL_branch(WORKER, DEPTH)
 | 
						|
#define BRANCH_LTT(WORKER, DEPTH)  (BRANCH(WORKER, DEPTH) & YAMOP_LTT_BITS)
 | 
						|
#define BRANCH_CUT(WORKER, DEPTH)  (BRANCH(WORKER, DEPTH) & YAMOP_CUT_FLAG)
 | 
						|
 | 
						|
 | 
						|
 | 
						|
/* ------------------------------ **
 | 
						|
**      Parallel Mode Macros      **
 | 
						|
** ------------------------------ */
 | 
						|
 | 
						|
#define PARALLEL_MODE_OFF     0
 | 
						|
#define PARALLEL_MODE_ON      1
 | 
						|
#define PARALLEL_MODE_RUNNING 2
 | 
						|
 | 
						|
 | 
						|
 | 
						|
/* ----------------------- **
 | 
						|
**      Engine Macros      **
 | 
						|
** ----------------------- */
 | 
						|
 | 
						|
#define worker_offset(X)	  ((GLOBAL_number_workers + X - worker_id) % GLOBAL_number_workers * Yap_worker_area_size)
 | 
						|
 | 
						|
#define LOCK_OR_FRAME(fr)      LOCK(OrFr_lock(fr))
 | 
						|
#define UNLOCK_OR_FRAME(fr)  UNLOCK(OrFr_lock(fr))
 | 
						|
 | 
						|
#define LOCK_WORKER(w)        LOCK(REMOTE_lock(w))
 | 
						|
#define UNLOCK_WORKER(w)    UNLOCK(REMOTE_lock(w))
 | 
						|
 | 
						|
 | 
						|
 | 
						|
/* -------------------------- **
 | 
						|
**      Scheduler Macros      **
 | 
						|
** -------------------------- */
 | 
						|
 | 
						|
#define SCH_top_shared_cp(CP)  (Get_LOCAL_top_cp() == CP)
 | 
						|
 | 
						|
#define SCH_any_share_request  (LOCAL_share_request != MAX_WORKERS)
 | 
						|
 | 
						|
#define SCHEDULER_GET_WORK()          \
 | 
						|
        if (get_work())               \
 | 
						|
          goto shared_fail;           \
 | 
						|
        else                          \
 | 
						|
          goto shared_end
 | 
						|
 | 
						|
#define SCH_check_prune_request()     \
 | 
						|
  if (Get_LOCAL_prune_request()) {    \
 | 
						|
          SCHEDULER_GET_WORK();       \
 | 
						|
        }
 | 
						|
 | 
						|
#if defined(YAPOR_COPY) || defined(YAPOR_SBA) || defined(YAPOR_THREADS)
 | 
						|
#define SCH_check_share_request()     \
 | 
						|
        if (SCH_any_share_request) {  \
 | 
						|
	  ASP = YENV;                 \
 | 
						|
	  saveregs();                 \
 | 
						|
          p_share_work();             \
 | 
						|
	  setregs();                  \
 | 
						|
        }
 | 
						|
#else /* YAPOR_COW */
 | 
						|
#define SCH_check_share_request()     \
 | 
						|
        if (SCH_any_share_request) {  \
 | 
						|
          if (! p_share_work())       \
 | 
						|
            goto shared_fail;         \
 | 
						|
        }
 | 
						|
#endif /* YAPOR_COPY || YAPOR_SBA || YAPOR_COW || YAPOR_THREADS */
 | 
						|
 | 
						|
#define SCH_check_requests()          \
 | 
						|
        SCH_check_prune_request();    \
 | 
						|
        SCH_check_share_request()
 | 
						|
 | 
						|
#define SCH_last_alternative(curpc, CP_PTR)    \
 | 
						|
        H = HBREG = PROTECT_FROZEN_H(CP_PTR);  \
 | 
						|
        CPREG = CP_PTR->cp_cp;		       \
 | 
						|
        ENV = CP_PTR->cp_env;                  \
 | 
						|
        SCH_new_alternative(curpc, NULL)
 | 
						|
 | 
						|
 | 
						|
 | 
						|
/* -------------------- **
 | 
						|
**      Cut Macros      **
 | 
						|
** -------------------- */
 | 
						|
 | 
						|
#define CUT_prune_to(PRUNE_CP)                           \
 | 
						|
        if (YOUNGER_CP(Get_LOCAL_top_cp(), PRUNE_CP)) {  \
 | 
						|
          if (! Get_LOCAL_prune_request())               \
 | 
						|
	    prune_shared_branch(PRUNE_CP, NULL);         \
 | 
						|
	  PRUNE_CP = Get_LOCAL_top_cp();	         \
 | 
						|
        }
 | 
						|
 | 
						|
#define CUT_wait_leftmost()                                           \
 | 
						|
        if (GLOBAL_parallel_mode == PARALLEL_MODE_RUNNING) {          \
 | 
						|
           /* parallel execution mode --> wait until leftmost */      \
 | 
						|
           int i, loop, depth, ltt;                                   \
 | 
						|
           bitmap members;                                            \
 | 
						|
           or_fr_ptr leftmost_or_fr;                                  \
 | 
						|
           leftmost_or_fr = LOCAL_top_or_fr;                          \
 | 
						|
           do {                                                       \
 | 
						|
             depth = OrFr_depth(leftmost_or_fr);                      \
 | 
						|
             ltt = BRANCH_LTT(worker_id, depth);                      \
 | 
						|
             do {                                                     \
 | 
						|
               loop = FALSE;                                          \
 | 
						|
               SCH_check_requests();                                  \
 | 
						|
               BITMAP_copy(members, OrFr_members(leftmost_or_fr));    \
 | 
						|
               BITMAP_delete(members, worker_id);                     \
 | 
						|
               for (i = 0; i < GLOBAL_number_workers; i++) {                 \
 | 
						|
                 /*  not leftmost in current frame if there is a  */  \
 | 
						|
	         /* worker in a left branch and it is not idle or */  \
 | 
						|
                 /*     if it is idle it is in a younger node     */  \
 | 
						|
                 if (BITMAP_member(members, i) &&                     \
 | 
						|
                     BRANCH_LTT(i, depth) > ltt &&                    \
 | 
						|
                     (! BITMAP_member(GLOBAL_bm_idle_workers, i) ||   \
 | 
						|
                      leftmost_or_fr != REMOTE_top_or_fr(i))) {       \
 | 
						|
                   loop = TRUE;                                       \
 | 
						|
                   break;                                             \
 | 
						|
                 }                                                    \
 | 
						|
               }                                                      \
 | 
						|
             } while (loop);                                          \
 | 
						|
             leftmost_or_fr = OrFr_nearest_leftnode(leftmost_or_fr);  \
 | 
						|
           } while (leftmost_or_fr != GLOBAL_root_or_fr);             \
 | 
						|
         }
 | 
						|
 | 
						|
 | 
						|
 | 
						|
/* ---------------------- **
 | 
						|
**      Engine Stuff      **
 | 
						|
** ---------------------- */
 | 
						|
 | 
						|
static inline 
 | 
						|
void PUT_IN_EXECUTING(int w) {
 | 
						|
  LOCK(GLOBAL_locks_bm_executing_workers);
 | 
						|
  BITMAP_insert(GLOBAL_bm_executing_workers, w);
 | 
						|
  UNLOCK(GLOBAL_locks_bm_executing_workers);
 | 
						|
  return;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
static inline 
 | 
						|
void PUT_OUT_EXECUTING(int w) {
 | 
						|
  LOCK(GLOBAL_locks_bm_executing_workers);
 | 
						|
  BITMAP_delete(GLOBAL_bm_executing_workers, w);
 | 
						|
  UNLOCK(GLOBAL_locks_bm_executing_workers);
 | 
						|
  return;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
static inline 
 | 
						|
void PUT_IN_FINISHED(int w) {
 | 
						|
  LOCK(GLOBAL_locks_bm_finished_workers);
 | 
						|
  BITMAP_insert(GLOBAL_bm_finished_workers, w);
 | 
						|
  UNLOCK(GLOBAL_locks_bm_finished_workers);
 | 
						|
  return;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
#ifdef TABLING_INNER_CUTS
 | 
						|
static inline 
 | 
						|
void PUT_IN_PRUNING(int w) {
 | 
						|
  LOCK(GLOBAL_locks_bm_pruning_workers);
 | 
						|
  BITMAP_insert(GLOBAL_bm_pruning_workers, w);
 | 
						|
  UNLOCK(GLOBAL_locks_bm_pruning_workers);
 | 
						|
  return;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
static inline 
 | 
						|
void PUT_OUT_PRUNING(int w) {
 | 
						|
  LOCK(GLOBAL_locks_bm_pruning_workers);
 | 
						|
  BITMAP_delete(GLOBAL_bm_pruning_workers, w);
 | 
						|
  UNLOCK(GLOBAL_locks_bm_pruning_workers);
 | 
						|
  return;
 | 
						|
}
 | 
						|
#endif /* TABLING_INNER_CUTS */
 | 
						|
 | 
						|
 | 
						|
 | 
						|
/* ------------------------- **
 | 
						|
**      Scheduler Stuff      **
 | 
						|
** ------------------------- */
 | 
						|
 | 
						|
static inline 
 | 
						|
void PUT_IN_REQUESTABLE(int p) {
 | 
						|
  LOCK(GLOBAL_locks_bm_requestable_workers);
 | 
						|
  BITMAP_insert(GLOBAL_bm_requestable_workers, p);
 | 
						|
  UNLOCK(GLOBAL_locks_bm_requestable_workers);
 | 
						|
  return;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
static inline 
 | 
						|
void PUT_OUT_REQUESTABLE(int p) {
 | 
						|
  LOCK(GLOBAL_locks_bm_requestable_workers);
 | 
						|
  BITMAP_delete(GLOBAL_bm_requestable_workers, p);
 | 
						|
  UNLOCK(GLOBAL_locks_bm_requestable_workers);
 | 
						|
  return;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
static inline 
 | 
						|
void SCH_update_local_or_tops(void) {
 | 
						|
  CACHE_REGS
 | 
						|
  Set_LOCAL_top_cp(Get_LOCAL_top_cp()->cp_b);
 | 
						|
  LOCAL_top_or_fr = Get_LOCAL_top_cp()->cp_or_fr;
 | 
						|
  return;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
static inline
 | 
						|
void SCH_refuse_share_request_if_any(void)  {
 | 
						|
  CACHE_REGS
 | 
						|
  if (SCH_any_share_request) {
 | 
						|
    REMOTE_reply_signal(LOCAL_share_request) = no_sharing;
 | 
						|
    LOCAL_share_request = MAX_WORKERS;
 | 
						|
    PUT_OUT_REQUESTABLE(worker_id);
 | 
						|
  }
 | 
						|
  return;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
static inline 
 | 
						|
void SCH_set_load(choiceptr current_cp) {
 | 
						|
  CACHE_REGS
 | 
						|
  Int lub;  /* local untried branches */
 | 
						|
  choiceptr previous_cp = current_cp->cp_b;
 | 
						|
 | 
						|
#define INIT_CP_LUB(CP, LUB)  CP->cp_or_fr = (struct or_frame *)(LUB)
 | 
						|
#define CP_LUB(CP)            (Int)(CP->cp_or_fr)
 | 
						|
 | 
						|
  if (SCH_top_shared_cp(previous_cp))
 | 
						|
    lub = 0;  
 | 
						|
  else if (YAMOP_SEQ(previous_cp->cp_ap))
 | 
						|
    lub = CP_LUB(previous_cp);
 | 
						|
  else
 | 
						|
    lub = CP_LUB(previous_cp) + YAMOP_LTT(previous_cp->cp_ap);
 | 
						|
  INIT_CP_LUB(current_cp, lub);
 | 
						|
 | 
						|
  if (YAMOP_SEQ(current_cp->cp_ap))
 | 
						|
    LOCAL_load = lub;
 | 
						|
  else
 | 
						|
    LOCAL_load = lub + YAMOP_LTT(current_cp->cp_ap);
 | 
						|
  return;
 | 
						|
}
 | 
						|
 | 
						|
static inline
 | 
						|
void SCH_new_alternative(yamop *curpc, yamop *new) {
 | 
						|
  CACHE_REGS
 | 
						|
  OrFr_alternative(LOCAL_top_or_fr) = new;
 | 
						|
  BRANCH(worker_id, OrFr_depth(LOCAL_top_or_fr)) = YAMOP_OR_ARG(curpc);
 | 
						|
  UNLOCK_OR_FRAME(LOCAL_top_or_fr);
 | 
						|
  return;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
/* ---------------------------- **
 | 
						|
**      Cut Stuff: Pruning      **
 | 
						|
** ---------------------------- */
 | 
						|
 | 
						|
static inline
 | 
						|
void CUT_send_prune_request(int worker, choiceptr prune_cp) {
 | 
						|
  LOCK_WORKER(worker);
 | 
						|
  if (YOUNGER_CP(REMOTE_top_cp(worker), prune_cp) &&
 | 
						|
     (! Get_REMOTE_prune_request(worker) || YOUNGER_CP(Get_REMOTE_prune_request(worker), prune_cp)))
 | 
						|
    Set_REMOTE_prune_request(worker, prune_cp);
 | 
						|
  UNLOCK_WORKER(worker);
 | 
						|
  return;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
static inline
 | 
						|
void CUT_reset_prune_request(void) {
 | 
						|
  CACHE_REGS
 | 
						|
  LOCK_WORKER(worker_id); 
 | 
						|
  if (Get_LOCAL_prune_request() && EQUAL_OR_YOUNGER_CP(Get_LOCAL_prune_request(), Get_LOCAL_top_cp()))
 | 
						|
    Set_LOCAL_prune_request(NULL);
 | 
						|
  UNLOCK_WORKER(worker_id);
 | 
						|
  return;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
/* ----------------------------- **
 | 
						|
**      Cut Stuff: Leftmost      **
 | 
						|
** ----------------------------- */
 | 
						|
 | 
						|
static inline
 | 
						|
int CUT_last_worker_left_pending_prune(or_fr_ptr or_frame) {
 | 
						|
  CACHE_REGS
 | 
						|
  int i, depth, ltt;
 | 
						|
  bitmap members;
 | 
						|
 | 
						|
  depth = OrFr_depth(or_frame);
 | 
						|
  ltt = OrFr_pend_prune_ltt(or_frame);
 | 
						|
  members = OrFr_members(or_frame);
 | 
						|
  BITMAP_delete(members, worker_id);
 | 
						|
  for (i = 0; i < GLOBAL_number_workers; i++) {
 | 
						|
    if (BITMAP_member(members, i) && BRANCH_LTT(i, depth) > ltt)
 | 
						|
      return FALSE;
 | 
						|
  }
 | 
						|
  return TRUE;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
static inline
 | 
						|
or_fr_ptr CUT_leftmost_or_frame(void) {
 | 
						|
  CACHE_REGS
 | 
						|
  int i, depth, ltt;
 | 
						|
  bitmap members;
 | 
						|
  or_fr_ptr leftmost_or_fr, or_fr, nearest_or_fr;
 | 
						|
 | 
						|
  BITMAP_clear(members);
 | 
						|
  BITMAP_insert(members, worker_id);
 | 
						|
  leftmost_or_fr = LOCAL_top_or_fr;
 | 
						|
  depth = OrFr_depth(leftmost_or_fr);
 | 
						|
  do {
 | 
						|
    ltt = BRANCH_LTT(worker_id, depth);
 | 
						|
    BITMAP_difference(members, OrFr_members(leftmost_or_fr), members);
 | 
						|
    if (members)
 | 
						|
      for (i = 0; i < GLOBAL_number_workers; i++)
 | 
						|
        if (BITMAP_member(members, i) && BRANCH_LTT(i, depth) > ltt)
 | 
						|
          goto update_nearest_leftnode_data;
 | 
						|
    BITMAP_copy(members, OrFr_members(leftmost_or_fr));
 | 
						|
    leftmost_or_fr = OrFr_nearest_leftnode(leftmost_or_fr);
 | 
						|
    depth = OrFr_depth(leftmost_or_fr);
 | 
						|
  } while (depth);
 | 
						|
 | 
						|
update_nearest_leftnode_data:
 | 
						|
  or_fr = LOCAL_top_or_fr;
 | 
						|
  nearest_or_fr = OrFr_nearest_leftnode(or_fr);
 | 
						|
  while (OrFr_depth(nearest_or_fr) > depth) {
 | 
						|
    LOCK_OR_FRAME(or_fr);
 | 
						|
    OrFr_nearest_leftnode(or_fr) = leftmost_or_fr;
 | 
						|
    UNLOCK_OR_FRAME(or_fr);
 | 
						|
    or_fr = nearest_or_fr;
 | 
						|
    nearest_or_fr = OrFr_nearest_leftnode(or_fr);
 | 
						|
  }
 | 
						|
 | 
						|
  return leftmost_or_fr;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
#ifdef TABLING_INNER_CUTS
 | 
						|
static inline
 | 
						|
or_fr_ptr CUT_leftmost_until(or_fr_ptr start_or_fr, int until_depth) {
 | 
						|
  int i, ltt, depth;
 | 
						|
  bitmap prune_members, members;
 | 
						|
  or_fr_ptr leftmost_or_fr, nearest_or_fr;
 | 
						|
 | 
						|
  /* we assume that the start_or_fr frame is locked and empty (without members) */
 | 
						|
  leftmost_or_fr = OrFr_nearest_leftnode(start_or_fr);
 | 
						|
  depth = OrFr_depth(leftmost_or_fr);
 | 
						|
  if (depth > until_depth) {
 | 
						|
    BITMAP_copy(prune_members, GLOBAL_bm_pruning_workers);
 | 
						|
    BITMAP_delete(prune_members, worker_id);
 | 
						|
    ltt = BRANCH_LTT(worker_id, depth);
 | 
						|
    BITMAP_intersection(members, prune_members, OrFr_members(leftmost_or_fr));
 | 
						|
    if (members) {
 | 
						|
      for (i = 0; i < GLOBAL_number_workers; i++) {
 | 
						|
        if (BITMAP_member(members, i) && 
 | 
						|
            BRANCH_LTT(i, depth) > ltt &&
 | 
						|
            EQUAL_OR_YOUNGER_CP(GetOrFr_node(leftmost_or_fr), REMOTE_pruning_scope(i)))
 | 
						|
          return leftmost_or_fr;
 | 
						|
      }
 | 
						|
      BITMAP_minus(prune_members, members);
 | 
						|
    }
 | 
						|
    /* reaching that point we should update the nearest leftnode data before return */
 | 
						|
    leftmost_or_fr = OrFr_nearest_leftnode(leftmost_or_fr);
 | 
						|
    depth = OrFr_depth(leftmost_or_fr);
 | 
						|
    while (depth > until_depth) {
 | 
						|
      ltt = BRANCH_LTT(worker_id, depth);
 | 
						|
      BITMAP_intersection(members, prune_members, OrFr_members(leftmost_or_fr));
 | 
						|
      if (members) {
 | 
						|
        for (i = 0; i < GLOBAL_number_workers; i++) {
 | 
						|
          if (BITMAP_member(members, i) &&
 | 
						|
              BRANCH_LTT(i, depth) > ltt &&
 | 
						|
              EQUAL_OR_YOUNGER_CP(GetOrFr_node(leftmost_or_fr), REMOTE_pruning_scope(i))) {
 | 
						|
            /* update nearest leftnode data */
 | 
						|
            OrFr_nearest_leftnode(start_or_fr) = leftmost_or_fr;
 | 
						|
            start_or_fr = OrFr_nearest_leftnode(start_or_fr);
 | 
						|
            nearest_or_fr = OrFr_nearest_leftnode(start_or_fr);
 | 
						|
            while (OrFr_depth(nearest_or_fr) > depth) {
 | 
						|
              LOCK_OR_FRAME(start_or_fr);
 | 
						|
              OrFr_nearest_leftnode(start_or_fr) = leftmost_or_fr;
 | 
						|
              UNLOCK_OR_FRAME(start_or_fr);
 | 
						|
              start_or_fr = nearest_or_fr;
 | 
						|
              nearest_or_fr = OrFr_nearest_leftnode(start_or_fr);
 | 
						|
            }
 | 
						|
            return leftmost_or_fr;
 | 
						|
	  }
 | 
						|
        }
 | 
						|
        BITMAP_minus(prune_members, members);
 | 
						|
      }
 | 
						|
      leftmost_or_fr = OrFr_nearest_leftnode(leftmost_or_fr);
 | 
						|
      depth = OrFr_depth(leftmost_or_fr);
 | 
						|
    }
 | 
						|
    /* update nearest leftnode data */
 | 
						|
    OrFr_nearest_leftnode(start_or_fr) = leftmost_or_fr;
 | 
						|
    start_or_fr = OrFr_nearest_leftnode(start_or_fr);
 | 
						|
    nearest_or_fr = OrFr_nearest_leftnode(start_or_fr);
 | 
						|
    while (OrFr_depth(nearest_or_fr) > depth) {
 | 
						|
      LOCK_OR_FRAME(start_or_fr);
 | 
						|
      OrFr_nearest_leftnode(start_or_fr) = leftmost_or_fr;
 | 
						|
      UNLOCK_OR_FRAME(start_or_fr);
 | 
						|
      start_or_fr = nearest_or_fr;
 | 
						|
      nearest_or_fr = OrFr_nearest_leftnode(start_or_fr);
 | 
						|
    }
 | 
						|
  }
 | 
						|
  return NULL;
 | 
						|
}
 | 
						|
#endif /* TABLING_INNER_CUTS */
 | 
						|
 | 
						|
 | 
						|
 | 
						|
/* ------------------------------------------------ **
 | 
						|
**      Cut Stuff: Managing query goal answers      **
 | 
						|
** ------------------------------------------------ */
 | 
						|
 | 
						|
static inline 
 | 
						|
void CUT_store_answer(or_fr_ptr or_frame, qg_ans_fr_ptr new_answer) {
 | 
						|
  CACHE_REGS
 | 
						|
  int ltt;
 | 
						|
  qg_sol_fr_ptr *solution_ptr;
 | 
						|
 | 
						|
  ltt = BRANCH_LTT(worker_id, OrFr_depth(or_frame));
 | 
						|
  solution_ptr = & OrFr_qg_solutions(or_frame);
 | 
						|
  while (*solution_ptr && ltt > SolFr_ltt(*solution_ptr)) {
 | 
						|
    solution_ptr = & SolFr_next(*solution_ptr);
 | 
						|
  }
 | 
						|
  if (*solution_ptr && ltt == SolFr_ltt(*solution_ptr)) {
 | 
						|
    AnsFr_next(SolFr_last(*solution_ptr)) = new_answer;
 | 
						|
    SolFr_last(*solution_ptr) = new_answer;
 | 
						|
  } else {
 | 
						|
    qg_sol_fr_ptr new_solution;
 | 
						|
    ALLOC_QG_SOLUTION_FRAME(new_solution);
 | 
						|
    SolFr_next(new_solution) = *solution_ptr;
 | 
						|
    SolFr_ltt(new_solution) = ltt;
 | 
						|
    SolFr_first(new_solution) = new_answer;
 | 
						|
    SolFr_last(new_solution) = new_answer;
 | 
						|
    *solution_ptr = new_solution;
 | 
						|
  }
 | 
						|
  return;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
static inline 
 | 
						|
void CUT_store_answers(or_fr_ptr or_frame, qg_sol_fr_ptr new_solution) {
 | 
						|
  CACHE_REGS
 | 
						|
  int ltt;
 | 
						|
  qg_sol_fr_ptr *solution_ptr;
 | 
						|
 | 
						|
  ltt = BRANCH_LTT(worker_id, OrFr_depth(or_frame));
 | 
						|
  solution_ptr = & OrFr_qg_solutions(or_frame);
 | 
						|
  while (*solution_ptr && ltt > SolFr_ltt(*solution_ptr)) {
 | 
						|
    solution_ptr = & SolFr_next(*solution_ptr);
 | 
						|
  }
 | 
						|
  if (*solution_ptr && ltt == SolFr_ltt(*solution_ptr)) {
 | 
						|
    AnsFr_next(SolFr_last(*solution_ptr)) = SolFr_first(new_solution);
 | 
						|
    SolFr_last(*solution_ptr) = SolFr_last(new_solution);
 | 
						|
    FREE_QG_SOLUTION_FRAME(new_solution);
 | 
						|
  } else {
 | 
						|
    SolFr_next(new_solution) = *solution_ptr;
 | 
						|
    SolFr_ltt(new_solution) = ltt;
 | 
						|
    *solution_ptr = new_solution;
 | 
						|
  }
 | 
						|
  return;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
static inline 
 | 
						|
void CUT_join_answers_in_an_unique_frame(qg_sol_fr_ptr join_solution) {
 | 
						|
  qg_sol_fr_ptr next_solution;
 | 
						|
 | 
						|
  while ((next_solution = SolFr_next(join_solution))) {
 | 
						|
    AnsFr_next(SolFr_last(join_solution)) = SolFr_first(next_solution);
 | 
						|
    SolFr_last(join_solution) = SolFr_last(next_solution);
 | 
						|
    SolFr_next(join_solution) = SolFr_next(next_solution);
 | 
						|
    FREE_QG_SOLUTION_FRAME(next_solution);
 | 
						|
  }
 | 
						|
  return;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
static inline 
 | 
						|
void CUT_free_solution_frame(qg_sol_fr_ptr solution) {
 | 
						|
  qg_ans_fr_ptr current_answer, next_answer;
 | 
						|
 | 
						|
  current_answer = SolFr_first(solution);
 | 
						|
  do {
 | 
						|
    next_answer = AnsFr_next(current_answer);
 | 
						|
    FREE_QG_ANSWER_FRAME(current_answer);
 | 
						|
    current_answer = next_answer;
 | 
						|
  } while (current_answer);
 | 
						|
  FREE_QG_SOLUTION_FRAME(solution);
 | 
						|
  return;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
static inline 
 | 
						|
void CUT_free_solution_frames(qg_sol_fr_ptr current_solution) {
 | 
						|
  qg_sol_fr_ptr next_solution;
 | 
						|
 | 
						|
  while (current_solution) {
 | 
						|
    next_solution = SolFr_next(current_solution);
 | 
						|
    CUT_free_solution_frame(current_solution);
 | 
						|
    current_solution = next_solution;
 | 
						|
  }
 | 
						|
  return;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
static inline 
 | 
						|
qg_sol_fr_ptr CUT_prune_solution_frames(qg_sol_fr_ptr solutions, int ltt) {
 | 
						|
  qg_sol_fr_ptr next_solution;
 | 
						|
 | 
						|
  while (solutions && ltt > SolFr_ltt(solutions)) {
 | 
						|
    next_solution = SolFr_next(solutions);
 | 
						|
    CUT_free_solution_frame(solutions);
 | 
						|
    solutions = next_solution;
 | 
						|
  }
 | 
						|
  return solutions;
 | 
						|
}
 |