smemPi.cpp

URL: https://mirkwood.cs.edinboro.edu/~bennett/class/cmsc4000/spring2026/notes/ch3/code/smemPi.cpp
 
#include <iostream>
#include <stdio.h>

// fork and wait
#include <unistd.h>
#include <signal.h>
#include <wait.h>

// for the memory mapping
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/mman.h>

using namespace std;

long double Pi(int iterations);
const string MEM_NAME{"BENNETT_PI"};

int main(int argc, char * argv[]) {

    int procs{10};
    int iterations {1'000'000};

    if (argc > 1) {
       int tmp{stoi(argv[1])};
       if (tmp > 1 and tmp < 1000) {
          procs = tmp;
       }
    }
    if (argc > 2) {
       int tmp{stoi(argv[2])};
       if (tmp > 1) {
          iterations = tmp;
       }
    }

    int flags{O_RDWR | O_CREAT | O_TRUNC};
    int mode{S_IRUSR | S_IWUSR};

    // create the shared memory segment
    int fd = shm_open(MEM_NAME.c_str(), flags, mode);
    if (fd == -1) {
       perror("shm_open:");
       return 1;
    } 

    // make it the right size
    if(-1 == ftruncate(fd, sizeof(long double) * procs)) {
       perror("ftruncate:");
       shm_unlink(MEM_NAME.c_str());
       return 1;
    }

    // open it as an array
    long double * results{
         static_cast<long double *>(    
             mmap(nullptr, sizeof(long double)*procs, 
                  PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0)
        )
    };

    if (results == nullptr) {
       perror("mmap:");
       shm_unlink(MEM_NAME.c_str());
       return 1;
    }

    shm_unlink(MEM_NAME.c_str());

    cout << "Computing pi with " 
         << procs << " processes for " 
         << iterations << " iterations." << endl;


    // compute the value on each child
    // note we could compute on the parent as well, 
    // but i would like to keep it simple 
    for(int i = 0; i < procs; ++i) {
        if (fork() == 0) {
           srand(time(nullptr)*(i+1));
           long double myPi {Pi(iterations)};

           cout << " process " << i << " got " <<  myPi  << endl;
           results[i] = myPi;
           return 0;
        }
    }
    
    // wait for all of the children to exit
    for(int i = 0; i < procs; ++i) {
       wait(nullptr);
    }

    cout << endl << endl;
    cout << "The children have exited" << endl;
    cout << endl;

    // compute the average
    long double pi{0};
    for(int i = 0; i < procs; ++i) {
       cout << results[i] << " from child " << i << endl;
       pi += results[i];
    }

    pi /= static_cast<long double> (procs);
    cout << "The final pi is " << pi  << endl;

    return (0);
}

long double Pi(int iterations){
    long double  pi{0};

    long long count{0};
    long double  x, y;
    for(int i = 0 ; i < iterations; ++i) {
       x = rand() / static_cast<long double>(RAND_MAX);
       y = rand() / static_cast<long double>(RAND_MAX);
       if (x*x + y*y <= 1) {
          ++count;
       }
    }

    return static_cast<long double>(count) 
           / static_cast<long double>(iterations) * 4;
}