/* -------------------------------------------------------------------- * POP OPERATION */ int Ast_pop (Astack stack) { AstNode node = NULL; int datum; /* 0. CHECK EMPTY */ if (Ast_more(stack)==FALSE) Asystem_error("Ast_pop","Empty stack",""); /* 1. REMEMBER THE NEXT POINTER */ node = (*stack)->next; /* 2. REMEMBER THE TASK POINTER */ datum = (*stack)->datum; /* 3. FREEING THE SPACE OF THE NODE */ free(*stack); /* 4. CHANGING THE STACK POINTER */ *stack = node; /* 5. RETURNING THE TASK POINTER */ return datum; }
/* * * Graph search. Test if exists a path from a source node to a target node * * Parallelization method: Shared-Memory workers-farm * */ void testPath(int nthreads, int source, int target, tg graph) { /* SHARED STRUCTURES */ Bool *searched=NULL; Astack pool; Bool found = FALSE; int ind; /* ENDING CONTROL */ int num_waiting=0; /* 1. ALLOCATE MEMORY FOR ANCILLARY STRUCTURES */ pool = Ast_init(); searched = OSCR_calloc(tg_nodes(graph), sizeof(Bool)); for (ind=0; ind<tg_nodes(graph); ind++) { searched[ind]=FALSE; } /* 2. INIT "nodes to explore" POOL WITH THE source ID */ Ast_push(pool, source); /* 3. START TIMER */ OSCR_timer_start(0); /* 4. SPAWN WORKERS */ #pragma omp parallel default(none) \ shared(nthreads,num_waiting,graph,searched,pool,target,found) { Bool waiting = FALSE; tg_task next=TG_NULLID; task_list succs; int num_succs; int ind; #ifdef DEBUG int numPops=0; int numNoPops=0; int thread = omp_get_thread_num(); #endif /* WORKER WORKS UNTIL: * ALL WORKERS ARE WAITING (TARGET NOT FOUND) * OR SOMEONE FINDS THE TARGET */ while ( num_waiting != nthreads && !found ) { /* 1. GET NEXT ELEMENT TO PROCESS (OR WAIT UNTIL MORE ELEMENTS) */ while( next == TG_NULLID && num_waiting != nthreads && !found) { /* ALL POOL OPERATIONS ARE MONITORIZED */ #pragma omp critical { /* 1.1. CHECK THE POOL */ if ( Ast_more(pool) ) { /* 1.1.1. ELEMENTS IN THE POOL: GET NEXT */ next = Ast_pop(pool); #ifdef DEBUG numPops++; #endif /* 1.1.2. IF WAITING, CHANGE STATE */ if ( waiting ) { waiting = FALSE; num_waiting--; } } else { /* 1.1.3. EMPTY POOL: IF NOT WAITING, CHANGE STATE */ #ifdef DEBUG numNoPops++; #endif if ( !waiting ) { waiting = TRUE; num_waiting++; } } /* OMP END CRITICAL: MONITORIZED OPERATION */ } } /* END GET next ELEMENT FROM THE POOL */ /* 2. PROCESS next ELEMENT */ if ( next != TG_NULLID ) { /* 2.1. TARGET FOUND: END ALL */ if (next == target) { found = TRUE; } /* 2.2. NO SUCCESORS: END */ else if ( tg_succ_num(graph, next) == 0 ) { next = TG_NULLID; } /* 2.3. GET SUCCESORS LIST AND PUSH IT TO THE POOL */ else { /* 2.3.1. GET SUCCS LIST */ num_succs = tg_succ_num(graph, next); succs = tg_succ(graph, next); /* 2.3.2. PUSH SUCCS TO POOL: MONITORIZED OPERATION */ #pragma omp critical if ( num_succs > 0 ) { for(ind=0; ind<num_succs; ind++) { tg_task vp = succs[ind]; /* PUSH ONLY NON-EXPLORED NODES */ if ( ! searched[ vp ] ) { searched[ vp ] = TRUE; Ast_push(pool, vp); } } /* END OMP CRITICAL: MONITORIZED OPERATION */ } } /* 2.4. END PROCESSING ELEMENT */ next = TG_NULLID; } } /* END PROCESSING */ #ifdef DEBUG printf("#DEBUG Thread %d ENDING ----> Pops: %d, NoPops: %d\n",thread,numPops,numNoPops); #endif /* WORKERS END: PARALLEL REGION */ } /* 5. STOP TIMER */ OSCR_timer_stop(0); /* 6. WRITE RESULT */ printf("\nPath(%d,%d) = %d\n\n", source, target, found); /* 7. END */ }