M4104C-boost-Exo5-Corrigé

/**
 *
 *  @file    CNpThreadsBoostV2.cpp
 *
 *  @author  D. Mathieu, M. Laporte
 *
 *  @date    09/03/2011
 *
 *  @version 2.0
 *
 *  @brief   Calcul parallele de CNp avec "memoisation"
 *
 **/
#include <iostream>
#include <vector>
#include <sstream>

#include <boost/thread/thread.hpp>
#include <boost/tr1/functional.hpp>  // ou <functional> : bind()
#include <boost/thread/locks.hpp>
#include <boost/thread/condition.hpp>

//#include "CstCodErr.h"

using namespace std;
using namespace boost;

//using namespace nsUtil;             // KExcArg

namespace
{
    enum { KExcArg  = 253 };    // Erreur d'arguments de main()
    int combin [100][100];
    mutex mtx;
    condition_variable condition;

    void CNp (unsigned N, unsigned p, unsigned * pRes)
    {
        int result;
        {
            unique_lock <mutex> oneLock (mtx);
            if ((result = combin [N][p]) > 0)
            {
                *pRes = result;
                return;
            }
            if (result == 0)
            {
                while (combin [N][p] == 0) condition.wait (oneLock);

                *pRes = combin [N][p];
                return;
            }
            combin [N][p] = 0;

        } // Liberation du lock

        unsigned r1;
        unsigned r2;

        thread_group groupThreads;
        groupThreads.create_thread (bind (CNp, N - 1, p - 1, & r1));
        groupThreads.create_thread (bind (CNp, N - 1, p    , & r2));

        groupThreads.join_all ();
        *pRes = r1 + r2;
        {
            lock_guard <mutex> oneLock (mtx);
            combin [N][p] = *pRes;
        }
         condition.notify_all ();

    } // CNp()

} // namespace

int main (int argc, char * argv [])
{
    if (argc != 3)
    {
         cerr << "Usage : " << argv [0] << " <N> <p>\n";
         return KExcArg;
    }
    unsigned N;
    {
        istringstream is (argv [1]);
        is >> N;
    }
    unsigned p;
    {
        istringstream is (argv [2]);
        is >> p;
    }
    cout << "C (" << N << ", " << p << ") = " << flush;

    for (unsigned i = 1; i <= N; ++i)
    {
        combin [i][1] = i;
        for (unsigned j = 2; j <= p; ++j) combin [i][j] = -1;
    }
    for (unsigned j = 1; j <= p; ++j) combin [j][j] = 1;

    unsigned result;
    thread Thr (bind (CNp, N, p, & result));

    Thr.join ();

    cout << result << '\n';

    return 0;

} // main()