Rework children creation and add recursive calls

This commit is contained in:
Ivaylo Ivanov 2018-12-15 18:45:22 +01:00
parent 446ac678db
commit c70db7363d
1 changed files with 120 additions and 74 deletions

View File

@ -60,7 +60,28 @@ float get_distance(float x1, float x2, float y1, float y2);
node_t * find_shortest_distance(node_t * list);
int wait_for_termination(pid_t child);
int main(void) {
int main(int argc, char *argv[]) {
if (argc > 1) {
puts("The command takes no additional arguments.");
puts("Usage: cpair");
exit(EXIT_FAILURE);
}
fprintf(stderr, "Process id: %d\n", getpid());
/**
* Create the pipe file descriptors and inititalize the pipes
*
* fd[0] - input side of pipe
* fd[1] - output side of pipe
*
**/
int in_pipe_a[2], out_pipe_a[2], in_pipe_b[2], out_pipe_b[2];
if(pipe(in_pipe_a) < 0 || pipe(in_pipe_b) < 0 || pipe(out_pipe_a) < 0 || pipe(out_pipe_b) < 0) {
fprintf(stderr, "ERROR: Failed creating the pipes\n");
exit(EXIT_FAILURE);
}
char input[__UINT8_MAX__] = ""; ///< An array to save the input to
int point_num = 0; ///< Save the number of points
node_t * head = NULL;
@ -101,101 +122,126 @@ int main(void) {
exit(EXIT_SUCCESS);
}
float x_mean = get_x_mean(head);
node_t * first_part = malloc(sizeof(node_t));
node_t * second_part = malloc(sizeof(node_t));
node_t * first_part_buff = first_part;
node_t * second_part_buff = second_part;
/// Separate the lists based on the mean
current = head;
while(current != NULL) {
if(current -> points[0] <= x_mean) {
first_part_buff -> points[0] = current -> points[0];
first_part_buff -> next = malloc(sizeof(node_t));
first_part_buff = first_part_buff -> next;
} else {
second_part_buff -> points[0] = current -> points[0];
second_part_buff -> next = malloc(sizeof(node_t));
second_part_buff = second_part_buff -> next;
}
current = current -> next;
}
/**
* Create the pipe file descriptors and inititalize the pipes
*
* fd[0] - input side of pipe
* fd[1] - output side of pipe
*
**/
int pipe_a[2], pipe_b[2];
if(pipe(pipe_a) < 0 || pipe(pipe_b) < 0) {
fprintf(stderr, "ERROR: Failed creating the pipe\n");
exit(EXIT_FAILURE);
}
pid_t child_a, child_b; ///< Create variables for the child processes
node_t * child_a_part = NULL;
node_t * child_b_part = NULL;
write(pipe_a[0], first_part, sizeof(node_t)); ///< Send the first part of the array to the child
/// Create first child
switch(child_a = fork()) {
case -1:
fprintf(stderr ,"ERROR: Couldn't fork child\n");
exit(EXIT_FAILURE);
case 0:
if(read(pipe_a[0], child_a_part, sizeof(node_t)) < 0) {
fprintf(stderr, "ERROR: Failed reading from pipe\n");
/// Child execution
fprintf(stderr, "Child 1 id: %d\n", getpid());
close(out_pipe_a[0]);
close(in_pipe_a[1]);
close(STDIN_FILENO);
if(dup2(in_pipe_a[0], STDIN_FILENO) != STDIN_FILENO) {
fprintf(stderr, "ERROR: Failed duplicating STDIN");
exit(EXIT_FAILURE);
}
if(write(pipe_a[1], find_shortest_distance(child_a_part), sizeof(node_t)) < 0) {
fprintf(stderr, "ERROR: Failed writing to pipe\n");
exit(EXIT_FAILURE);
}
exit(EXIT_SUCCESS);
break;
execlp(argv[0], argv[0], NULL);
fprintf(stderr, "ERROR: Failed to load program into child");
exit(EXIT_FAILURE);
default:
write(pipe_b[0], second_part, sizeof(node_t));
/// Parent execution
/// Create second child
switch(child_b = fork()) {
case -1:
fprintf(stderr, "ERROR: Couldn't fork child\n");
exit(EXIT_FAILURE);
case 0:
if(read(pipe_b[0], child_b_part, sizeof(node_t)) < 0) {
fprintf(stderr, "ERROR: Failed reading from pipe\n");
/// Child execution
fprintf(stderr, "Child 2 id: %d\n", getpid());
close(out_pipe_b[0]);
close(in_pipe_b[1]);
close(STDIN_FILENO);
if(dup2(in_pipe_b[0], STDIN_FILENO) != STDIN_FILENO) {
fprintf(stderr, "ERROR: Failed duplicating STDIN");
exit(EXIT_FAILURE);
}
if(write(pipe_b[1], find_shortest_distance(child_b_part), sizeof(node_t)) < 0) {
fprintf(stderr, "ERROR: Failed writing to pipe\n");
exit(EXIT_FAILURE);
}
exit(EXIT_SUCCESS);
break;
execlp(argv[0], argv[0], NULL);
fprintf(stderr, "ERROR: Failed to load program into child");
exit(EXIT_FAILURE);
default:
/// Parent execution
close(in_pipe_a[0]);
close(in_pipe_b[0]);
close(STDOUT_FILENO);
float x_mean = get_x_mean(head);
node_t * first_part = malloc(sizeof(node_t));
int first_part_len = 1;
node_t * second_part = malloc(sizeof(node_t));
int second_part_len = 1;
node_t * first_part_buff = first_part;
node_t * second_part_buff = second_part;
/// Separate the lists based on the mean
current = head;
while(current != NULL) {
if(current -> points[0] <= x_mean) {
first_part_buff -> points[0] = current -> points[0];
first_part_buff -> next = malloc(sizeof(node_t));
first_part_buff = first_part_buff -> next;
first_part_len ++;
} else {
second_part_buff -> points[0] = current -> points[0];
second_part_buff -> next = malloc(sizeof(node_t));
second_part_buff = second_part_buff -> next;
second_part_len ++;
}
current = current -> next;
}
/**
* Send the correct lists to the children
**/
/// First half
if(dup2(in_pipe_a[1], STDIN_FILENO) != STDIN_FILENO) {
fprintf(stderr, "ERROR: Failed duplicating STDIN");
exit(EXIT_FAILURE);
}
if (write(in_pipe_a[1], first_part_buff, first_part_len*sizeof(node_t)) < 0) {
fprintf(stderr, "ERROR: Failed writing to child\n");
exit(EXIT_FAILURE);
}
close(STDOUT_FILENO);
///Second half
if(dup2(in_pipe_b[1], STDIN_FILENO) != STDIN_FILENO) {
fprintf(stderr, "ERROR: Failed duplicating STDIN");
exit(EXIT_FAILURE);
}
if (write(in_pipe_b[1], first_part_buff, second_part_len*sizeof(node_t)) < 0) {
fprintf(stderr, "ERROR: Failed writing to child\n");
exit(EXIT_FAILURE);
}
close(STDOUT_FILENO);
/// Wait for the correct exit of the children
if(wait_for_termination(child_a) != EXIT_SUCCESS || wait_for_termination(child_b) != EXIT_SUCCESS) {
fprintf(stderr, "ERROR: Children didn't terminate successfully");
exit(EXIT_FAILURE);
}
/// Free the memory
free(head);
free(first_part);
free(first_part_buff);
free(second_part);
free(second_part_buff);
free(current);
break;
}
break;
}
if(wait_for_termination(child_a) != EXIT_SUCCESS)
exit(EXIT_FAILURE);
if(wait_for_termination(child_b) != EXIT_SUCCESS)
exit(EXIT_FAILURE);
/// Free the memory
free(head);
free(first_part);
free(first_part_buff);
free(second_part);
free(second_part_buff);
free(current);
exit(EXIT_SUCCESS);
}