pipePi.cpp

URL: https://mirkwood.cs.edinboro.edu/~bennett/class/cmsc4000/spring2026/notes/ch3/code/pipePi.cpp
 
#include <iostream>
#include <unistd.h>
#include <stdio.h>
#include <vector>
#include <fcntl.h>
#include <wait.h>
#include <iomanip>

using namespace std;

const int PROCESSES {20};
const int ITERATIONS{200'000'000};

void DoPi(int myid, int fd);

int main() {
   int fd[2];
   int id;

   if (-1 == pipe(fd)) {
       perror("Pipe failed"); 
       exit(1);
   } 

   for(id = 1; id <= PROCESSES; ++id) {
       pid_t pid = fork();
       if (pid == -1) {
           perror("Fork failed");
           exit(1);
       }

       if (pid == 0) {
          // this is the child and it will write 
          close (fd[STDIN_FILENO]);

          DoPi(id, fd[STDOUT_FILENO]);
          return 0;
      }
   }

   // onlny main gets here.
   int count{0};
   double sum{4};
   int status;
   pid_t child;
   double  tempNum;
   ssize_t size;

   // I will not write the the pipe
   close(fd[STDOUT_FILENO]);

   while (count < PROCESSES) {
      // read from the pipe.
      size = read(fd[STDIN_FILENO], &tempNum, sizeof(double));
      if (size > 0) {
         sum += tempNum;
      }

      // once I have a read, get rid of the child.
      child = waitpid(0,&status, WNOHANG);
      if (child != 0) {
         ++count;
      } 
   }

   cout << setprecision(20);
   cout << "pi = " << sum << endl;

   return 0;
}


// 4 - 4/3  + 4/5 - 4/7 + ...
void DoPi(int myid, int fd) {
   double sum{0};
   int i;

   long denom = 2*myid +1;

   for(i = 0; i < ITERATIONS; ++i) {
       if (denom % 4 == 1) {
           sum += 4.0 / static_cast<double>(denom);
       } else {
           sum -= 4.0 / static_cast<double>(denom);
       }
       denom += 2*PROCESSES;
   }

   write(fd, &sum, sizeof(double));
   return;
}