aboutsummaryrefslogtreecommitdiff
path: root/semestr-5/so/lista5/so21_lista_5/mergesort.c
diff options
context:
space:
mode:
Diffstat (limited to 'semestr-5/so/lista5/so21_lista_5/mergesort.c')
-rw-r--r--semestr-5/so/lista5/so21_lista_5/mergesort.c141
1 files changed, 141 insertions, 0 deletions
diff --git a/semestr-5/so/lista5/so21_lista_5/mergesort.c b/semestr-5/so/lista5/so21_lista_5/mergesort.c
new file mode 100644
index 0000000..b5328b6
--- /dev/null
+++ b/semestr-5/so/lista5/so21_lista_5/mergesort.c
@@ -0,0 +1,141 @@
+#include "csapp.h"
+
+typedef struct {
+ int child_fd;
+ int parent_fd;
+} sockpair_t;
+
+static sockpair_t MakeSocketPair(void) {
+ int sv[2];
+ Socketpair(AF_UNIX, SOCK_STREAM, 0, sv);
+ return (sockpair_t){.child_fd = sv[0], .parent_fd = sv[1]};
+}
+
+static bool MaybeReadNum(int fd, int *num_p) {
+ return Read(fd, num_p, sizeof(int)) == sizeof(int);
+}
+
+static int ReadNum(int fd) {
+ int num;
+ if (Read(fd, &num, sizeof(int)) < sizeof(int))
+ app_error("ReadNum error");
+ return num;
+}
+
+static void WriteNum(int fd, int num) {
+ if (Write(fd, &num, sizeof(int)) < sizeof(int))
+ app_error("WriteNum error");
+}
+
+static void SendElem(int parent_fd, int child_fd, int nelem) {
+ WriteNum(child_fd, nelem);
+ for (int i = 0; i < nelem; i++)
+ WriteNum(child_fd, ReadNum(parent_fd));
+}
+
+static void Merge(int left_fd, int right_fd, int parent_fd) {
+ bool has_left = true;
+ bool has_right = true;
+ int left = ReadNum(left_fd);
+ int right = ReadNum(right_fd);
+
+ do {
+ if ((has_left && has_right) ? left < right : has_left) {
+ WriteNum(parent_fd, left);
+ has_left = MaybeReadNum(left_fd, &left);
+ } else {
+ WriteNum(parent_fd, right);
+ has_right = MaybeReadNum(right_fd, &right);
+ }
+ } while (has_left || has_right);
+}
+
+static void Sort(int parent_fd) {
+ int nelem = ReadNum(parent_fd);
+
+ if (nelem < 2) {
+ WriteNum(parent_fd, ReadNum(parent_fd));
+ Close(parent_fd);
+ return;
+ }
+
+ sockpair_t left = MakeSocketPair();
+
+ int left_fd = left.parent_fd;
+ int lnelem = nelem/2;
+
+ if (Fork()) {
+ Close(left.child_fd);
+ SendElem(parent_fd, left_fd, lnelem);
+ }
+ else {
+ Close(left.parent_fd);
+ Sort(left.child_fd);
+ return;
+ }
+
+ sockpair_t right = MakeSocketPair();
+ /* TODO: Spawn right child. */
+ int right_fd = right.parent_fd;
+ int rnelem = nelem - nelem/2;
+
+ if (Fork()) {
+ Close(right.child_fd);
+ SendElem(parent_fd, right_fd, rnelem);
+ }
+ else {
+ Close(right.parent_fd);
+ Sort(right.child_fd);
+ return;
+ }
+
+ /* TODO: Send elements to children and merge returned values afterwards. */
+ Merge(left_fd, right_fd, parent_fd);
+
+ /* Wait for both children. */
+ Wait(NULL);
+ Wait(NULL);
+}
+
+static int GetNumber(void) {
+ char buf[20];
+ if (fgets(buf, sizeof(buf), stdin) == NULL)
+ app_error("GetNumber error");
+ return strtol(buf, NULL, 10);
+}
+
+int main(void) {
+ sockpair_t sort = MakeSocketPair();
+
+ if (Fork()) {
+ /* parent */
+ int nelem = GetNumber();
+ if (nelem < 2)
+ app_error("Number of sorted elements must be at least 2!\n");
+ Close(sort.child_fd);
+
+ /* Write unsorted numbers to mergesort */
+ WriteNum(sort.parent_fd, nelem);
+ for (int i = 0; i < nelem; i++) {
+ WriteNum(sort.parent_fd, GetNumber());
+ }
+
+ /* Read sorted numbers from mergesort */
+ int prev = INT_MIN;
+ for (int i = 0; i < nelem; i++) {
+ int elem = ReadNum(sort.parent_fd);
+ fprintf(stderr, "%d\n", elem);
+ assert(prev <= elem);
+ prev = elem;
+ }
+ Close(sort.parent_fd);
+
+ Wait(NULL);
+ } else {
+ /* child */
+ Close(sort.parent_fd);
+ Sort(sort.child_fd);
+ }
+
+ return 0;
+}