593 lines
		
	
	
		
			19 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
		
		
			
		
	
	
			593 lines
		
	
	
		
			19 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
|   | /* -------------------- **
 | ||
|  | **      Prototypes      ** | ||
|  | ** -------------------- */ | ||
|  | 
 | ||
|  | /* get a def for NULL */ | ||
|  | #include <stdlib.h>
 | ||
|  | 
 | ||
|  | STD_PROTO(static inline void PUT_IN_EXECUTING, (int)); | ||
|  | STD_PROTO(static inline void PUT_OUT_EXECUTING, (int)); | ||
|  | STD_PROTO(static inline void PUT_IN_FINISHED, (int)); | ||
|  | #ifdef TABLING_INNER_CUTS
 | ||
|  | STD_PROTO(static inline void PUT_IN_PRUNING, (int)); | ||
|  | STD_PROTO(static inline void PUT_OUT_PRUNING, (int)); | ||
|  | #endif /* TABLING_INNER_CUTS */
 | ||
|  | 
 | ||
|  | STD_PROTO(static inline void PUT_IN_REQUESTABLE, (int)); | ||
|  | STD_PROTO(static inline void PUT_OUT_REQUESTABLE, (int)); | ||
|  | STD_PROTO(static inline void SCH_update_local_or_tops, (void)); | ||
|  | STD_PROTO(static inline void SCH_refuse_share_request_if_any, (void)); | ||
|  | STD_PROTO(static inline void SCH_set_load, (choiceptr)); | ||
|  | STD_PROTO(static inline void SCH_new_alternative, (yamop *,yamop *)); | ||
|  | 
 | ||
|  | STD_PROTO(static inline void CUT_prune_to, (choiceptr)); | ||
|  | STD_PROTO(static inline void CUT_send_prune_request, (int, choiceptr)); | ||
|  | STD_PROTO(static inline void CUT_reset_prune_request, (void)); | ||
|  | 
 | ||
|  | STD_PROTO(static inline int CUT_last_worker_left_pending_prune, (or_fr_ptr)); | ||
|  | STD_PROTO(static inline or_fr_ptr CUT_leftmost_or_frame, (void)); | ||
|  | #ifdef TABLING_INNER_CUTS
 | ||
|  | STD_PROTO(static inline or_fr_ptr CUT_leftmost_until, (or_fr_ptr, int)); | ||
|  | #endif /* TABLING_INNER_CUTS */
 | ||
|  | 
 | ||
|  | STD_PROTO(static inline void CUT_store_answer, (or_fr_ptr, qg_ans_fr_ptr)); | ||
|  | STD_PROTO(static inline void CUT_store_answers, (or_fr_ptr, qg_sol_fr_ptr)); | ||
|  | STD_PROTO(static inline void CUT_join_answers_in_an_unique_frame, (qg_sol_fr_ptr)); | ||
|  | STD_PROTO(static inline void CUT_free_solution_frame, (qg_sol_fr_ptr)); | ||
|  | STD_PROTO(static inline void CUT_free_solution_frames, (qg_sol_fr_ptr)); | ||
|  | STD_PROTO(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.ld.or_arg)
 | ||
|  | #define YAMOP_LTT(INST)            (((INST)->u.ld.or_arg) & YAMOP_LTT_BITS)
 | ||
|  | #define YAMOP_SEQ(INST)            (((INST)->u.ld.or_arg) & YAMOP_SEQ_FLAG)
 | ||
|  | #define YAMOP_CUT(INST)            (((INST)->u.ld.or_arg) & YAMOP_CUT_FLAG)
 | ||
|  | #define YAMOP_FLAGS(INST)          (((INST)->u.ld.or_arg) & YAMOP_FLAGS_BITS)
 | ||
|  | 
 | ||
|  | #define INIT_YAMOP_LTT(INST, LTT)  (INST)->u.ld.or_arg = LTT
 | ||
|  | #define PUT_YAMOP_LTT(INST, LTT)   (INST)->u.ld.or_arg = YAMOP_FLAGS(INST) | (LTT)
 | ||
|  | #define PUT_YAMOP_SEQ(INST)        (INST)->u.ld.or_arg |= YAMOP_SEQ_FLAG
 | ||
|  | #define PUT_YAMOP_CUT(INST)        (INST)->u.ld.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)
 | ||
|  | 
 | ||
|  | 
 | ||
|  | 
 | ||
|  | /* ---------------------------- **
 | ||
|  | **      Performance Macros      ** | ||
|  | ** ---------------------------- */ | ||
|  | 
 | ||
|  | #define PERFORMANCE_OFF           0x0
 | ||
|  | #define PERFORMANCE_ON            0x1
 | ||
|  | #define PERFORMANCE_IN_EXECUTION  0x2
 | ||
|  | 
 | ||
|  | 
 | ||
|  | 
 | ||
|  | /* ----------------------- **
 | ||
|  | **      Engine Macros      ** | ||
|  | ** ----------------------- */ | ||
|  | 
 | ||
|  | #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)  (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 (LOCAL_prune_request) {    \ | ||
|  |           SCHEDULER_GET_WORK();       \ | ||
|  |         } | ||
|  | 
 | ||
|  | #if defined(ENV_COPY) || defined(SBA)
 | ||
|  | #define SCH_check_share_request()     \
 | ||
|  |         if (SCH_any_share_request) {  \ | ||
|  |           p_share_work();             \ | ||
|  |         } | ||
|  | #else /* ACOW */
 | ||
|  | #define SCH_check_share_request()     \
 | ||
|  |         if (SCH_any_share_request) {  \ | ||
|  |           if (! p_share_work())       \ | ||
|  |             goto shared_fail;         \ | ||
|  |         } | ||
|  | #endif /* ENV_COPY || SBA || ACOW */
 | ||
|  | 
 | ||
|  | #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_wait_leftmost()                                           \
 | ||
|  |         if (PARALLEL_EXECUTION_MODE) {                                \ | ||
|  |            /* 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 < 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; | ||
|  | } | ||
|  | 
 | ||
|  | extern int  vsc_op; | ||
|  | 
 | ||
|  | static inline  | ||
|  | void SCH_update_local_or_tops(void) { | ||
|  |   LOCAL_top_cp = LOCAL_top_cp->cp_b; | ||
|  |   LOCAL_top_or_fr = LOCAL_top_cp->cp_or_fr; | ||
|  |   return; | ||
|  | } | ||
|  | 
 | ||
|  | 
 | ||
|  | static inline | ||
|  | void SCH_refuse_share_request_if_any(void)  { | ||
|  |   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) { | ||
|  |   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) { | ||
|  |   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_prune_to(choiceptr prune_cp) { | ||
|  |   if (EQUAL_OR_YOUNGER_CP(prune_cp, LOCAL_top_cp)) { | ||
|  |     B = prune_cp; | ||
|  |   } else { | ||
|  |     if (! LOCAL_prune_request) | ||
|  |       prune_shared_branch(prune_cp); | ||
|  |     B = LOCAL_top_cp; | ||
|  |   } | ||
|  |   return; | ||
|  | } | ||
|  | 
 | ||
|  | 
 | ||
|  | static inline | ||
|  | void CUT_send_prune_request(int worker, choiceptr prune_cp) { | ||
|  |   LOCK_WORKER(worker); | ||
|  |   if (YOUNGER_CP(REMOTE_top_cp(worker), prune_cp) && | ||
|  |      (! REMOTE_prune_request(worker) || YOUNGER_CP(REMOTE_prune_request(worker), prune_cp))) | ||
|  |     REMOTE_prune_request(worker) = prune_cp; | ||
|  |   UNLOCK_WORKER(worker); | ||
|  |   return; | ||
|  | } | ||
|  | 
 | ||
|  | 
 | ||
|  | static inline | ||
|  | void CUT_reset_prune_request(void) { | ||
|  |   LOCK_WORKER(worker_id);  | ||
|  |   if (LOCAL_prune_request && EQUAL_OR_YOUNGER_CP(LOCAL_prune_request, LOCAL_top_cp)) | ||
|  |     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) { | ||
|  |   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 < 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) { | ||
|  |   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 < 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 < number_workers; i++) { | ||
|  |         if (BITMAP_member(members, i) &&  | ||
|  |             BRANCH_LTT(i, depth) > ltt && | ||
|  |             EQUAL_OR_YOUNGER_CP(OrFr_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 < number_workers; i++) { | ||
|  |           if (BITMAP_member(members, i) && | ||
|  |               BRANCH_LTT(i, depth) > ltt && | ||
|  |               EQUAL_OR_YOUNGER_CP(OrFr_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) { | ||
|  |   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) { | ||
|  |   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; | ||
|  | } |