#include #include #include #include #include #include #include #include #include #include #include #include constexpr int NIL = -1; struct Node { int value; int next; }; struct SharedData { int head; Node nodes[1]; }; std::string now() { timeval tv{}; gettimeofday(&tv, nullptr); std::ostringstream oss; oss << tv.tv_sec << "." << std::setfill('0') << std::setw(6) << tv.tv_usec; return oss.str(); } void log_start(int head, int depth) { std::cout << "PROC_START pid=" << getpid() << " ppid=" << getppid() << " depth=" << depth << " l=" << head << " r=0" << " ts=" << now() << '\n' << std::flush; } void log_end(int head, int depth) { std::cout << "PROC_END pid=" << getpid() << " ppid=" << getppid() << " depth=" << depth << " l=" << head << " r=0" << " ts=" << now() << '\n' << std::flush; } int merge_lists(Node* pool, int left_head, int right_head) { if (left_head == NIL) return right_head; if (right_head == NIL) return left_head; int res_head = NIL; int tail = NIL; auto append = [&](int node_idx) { if (res_head == NIL) { res_head = node_idx; tail = node_idx; } else { pool[tail].next = node_idx; tail = node_idx; } }; while (left_head != NIL && right_head != NIL) { if (pool[left_head].value <= pool[right_head].value) { int next = pool[left_head].next; append(left_head); left_head = next; } else { int next = pool[right_head].next; append(right_head); right_head = next; } } if (left_head != NIL) pool[tail].next = left_head; if (right_head != NIL) pool[tail].next = right_head; return res_head; } void split_list(Node* pool, int head, int& left, int& right) { if (head == NIL || pool[head].next == NIL) { left = head; right = NIL; return; } int slow = head; int fast = pool[head].next; while (fast != NIL) { fast = pool[fast].next; if (fast != NIL) { slow = pool[slow].next; fast = pool[fast].next; } } left = head; right = pool[slow].next; pool[slow].next = NIL; } int local_list_sort(Node* pool, int head) { if (head == NIL || pool[head].next == NIL) return head; int left, right; split_list(pool, head, left, right); left = local_list_sort(pool, left); right = local_list_sort(pool, right); return merge_lists(pool, left, right); } int parallel_list_sort(Node* pool, int head, int depth, int max_depth) { log_start(head, depth); if (head == NIL || pool[head].next == NIL) { log_end(head, depth); return head; } if (depth >= max_depth) { int result = local_list_sort(pool, head); log_end(result, depth); return result; } int left_part, right_part; split_list(pool, head, left_part, right_part); int pipe_l[2], pipe_r[2]; pipe(pipe_l); pipe(pipe_r); // Левый потомок pid_t pid_l = fork(); if (pid_l == 0) { close(pipe_l[0]); close(pipe_r[0]); close(pipe_r[1]); int res = parallel_list_sort(pool, left_part, depth + 1, max_depth); write(pipe_l[1], &res, sizeof(int)); close(pipe_l[1]); _exit(0); } // Правый потомок pid_t pid_r = fork(); if (pid_r == 0) { close(pipe_r[0]); close(pipe_l[0]); close(pipe_l[1]); int res = parallel_list_sort(pool, right_part, depth + 1, max_depth); write(pipe_r[1], &res, sizeof(int)); close(pipe_r[1]); _exit(0); } // Родитель ждет обоих int sorted_l, sorted_r; close(pipe_l[1]); close(pipe_r[1]); waitpid(pid_l, nullptr, 0); read(pipe_l[0], &sorted_l, sizeof(int)); waitpid(pid_r, nullptr, 0); read(pipe_r[0], &sorted_r, sizeof(int)); close(pipe_l[0]); close(pipe_r[0]); int final_head = merge_lists(pool, sorted_l, sorted_r); log_end(final_head, depth); return final_head; } int main(int argc, char* argv[]) { int n = 1000; int max_depth = 3; if (argc > 1) n = std::atoi(argv[1]); if (argc > 2) max_depth = std::atoi(argv[2]); size_t shm_size = sizeof(int) + sizeof(Node) * n; int shmid = shmget(IPC_PRIVATE, shm_size, IPC_CREAT | 0666); SharedData* data = (SharedData*)shmat(shmid, nullptr, 0); std::mt19937 rng(time(0)); std::uniform_int_distribution dist(0, 9999); for (int i = 0; i < n; ++i) { data->nodes[i].value = dist(rng); data->nodes[i].next = (i == n - 1) ? NIL : i + 1; } data->head = parallel_list_sort(data->nodes, data->head, 0, max_depth); shmdt(data); shmctl(shmid, IPC_RMID, nullptr); return 0; }