Esempio n. 1
0
/*
 * Assign a child-thread starting point within the maze.  Return 1 if
 * successful, return 0 if not.  For example, if some other thread
 * already is starting at the desired point, a second attempt to assign
 * that same point will fail.  Just ABORT() if invalid starting point
 * given.
 */
int maze_solve_start_assign(struct maze *mp, int tid, int r, int c)
{
	cell_t *cp;
	int i;
	struct maze_child *mcp = mp->msp->mcp;

	/* Die if the point lies outside of the maze. */
	if (!maze_cell_exists(mp, r, c) || tid >= nthreads)
		ABORT();

	/*
	 * Return 0 if this point is already assigned to some other thread.
	 * Or if some other point is already assigned to this thread, for
	 * that matter.
	 */
	cp = maze_get_cell_addr(mp, r, c);
	if (*cp & VISITED || mcp[tid].startrow != -1)
		return 0;

	/* Assign the point. */
	mcp[tid].startrow = r;
	mcp[tid].startcol = c;
	mcp[tid].visited[0].row = r;
	mcp[tid].visited[0].col = c;
	mcp[tid].vi = 1;
	*cp |= VISITED | tid;
	maze_set_cell_distance(mp, r, c, 1);
	return 1;
}
Esempio n. 2
0
/* Remove visitation, solution, and distance tags to allow maze to be solved. */
void maze_unvisit_all(struct maze *mp)
{
	cell_t *cp;
	int i;
	int j;

	for (i = 0; i < mp->nrows; i++)
		for (j = 0; j < mp->ncols; j++) {
			cp = maze_get_cell_addr(mp, i, j);
			*cp &= ~(VISITED | SOLUTION | COOKIE);
			maze_set_cell_distance(mp, i, j, 0);
		}
	mp->vi = 0;
}
Esempio n. 3
0
/* Visit the specified cell.  Die if already visited. */
void maze_visit_cell(struct maze *mp, int row, int col, int distance)
{
	cell_t *cp = maze_get_cell_addr(mp, row, col);

	if (*cp & VISITED)
		ABORT();
	if (mp->visited != NULL) {
		if (mp->vi >= mp->nrows * mp->ncols)
			ABORT();
		mp->visited[mp->vi].row = row;
		mp->visited[mp->vi].col = col;
		mp->vi++;
	}
	*cp |= VISITED;
	maze_set_cell_distance(mp, row, col, distance);
}
Esempio n. 4
0
/* Attempt to visit a cell, return 0 if it has already been visited.  */
int maze_try_visit_cell(struct maze *mp, int cr, int cc, int tr, int tc,
			int *nextrow, int *nextcol, int distance)
{
	cell_t t;
	cell_t *tp;
	int vi;

	if (!maze_cells_connected(mp, cr, cc, tr, tc))
		return -1;
	tp = maze_get_cell_addr(mp, tr, tc);
	do {
		t = ACCESS_ONCE(*tp);
		if (t & VISITED) {
			record_encounter(mp, cr, cc, tr, tc);
			return 1;
		}
	} while (!__sync_bool_compare_and_swap(tp, t, t | VISITED | myid));
	maze_set_cell_distance(mp, tr, tc, distance);
	*nextrow = tr;
	*nextcol = tc;

	/* If we are solving the maze, mymcp is non-NULL.  */
	if (mymcp != NULL) {
		/* Use this thread's state. */
		vi = mymcp->vi++;
		mymcp->visited[vi].row = tr;
		mymcp->visited[vi].col = tc;
		if (nthreads == 1 &&
		    tr == mymcp->mcsp->endrow && tc == mymcp->mcsp->endcol)
			mymcp->mcsp->done = 1;
	} else {
		/* Use global state. */
		vi = mp->vi++;
		mp->visited[vi].row = tr;
		mp->visited[vi].col = tc;
	}
	return 0;
}