typedef struct { char state; // PLAYER_OUT: no player; PLAYER_IN: player in the game char who; // SERVER_MOVE: server has responded; PLAYER_MOVE: player has made new attempt char move[N_BOARD]; // last attempt of player or last response of server int attempts; // number of attempts } struct_player;Synchronization between server and clients should be done with semaphores. When a client sends an attempt to the server, it should go into sleep mode until the server responds. On the other hand, the server should also sleep when there are no more attempts to answer to. To ensure a fair response time, the server should use a round-robin strategy to answer to the clients.
The server and the clients should be initialized with different executables. As a suggestion, consider the following starting code for the server and for the clients.
Programming for shared memory with processes. (NQueens)
Develop an application to solve in parallel the problem of placing
N-queens in a chess board. The problem consists in finding all
possible arrangements of N queens in a chess board of dimension N,
such that no two queens attack each other. Two queens attack each other
if they are in the same line, column or diagonal. The figure shows
the positions that are attacked by a queen placed in board of
dimension 7x7 and, on the side, it shows a possible solution for such
board.
A procedure to place the N queens in the board is to start by the first row and consider the N available column positions available. Then, for each position in the first row, consider the positions in the second row that will not attack the first queen. Apply this idea to the other rows, to obtain all possible solutions. As we progress with the rows, it is necessary to save valid intermediate combinations. This can be done with a queue of tasks where we save these combinations.
Starting from the following code structure, implement a sequential version of the queue of tasks. Then make a first parallel version in which the different workers synchronize in the two operations that access the queue of tasks.
Last, extend the parallel version to support multiple task queues associated with groups of workers. Each group of workers only consumes tasks from its task queue, but distributes its intermediate combinations by all queues in a round-robin fashion.