/**
*
* @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()