#include "sopnamsp.h" #include "machdefs.h" #include "zthread.h" #include #include #include #include // Include file pour PI #include "pisysdep.h" #include PIAPP_H #include PIMENU_H #include PISTDWDG_H #include PIWIN_H #include PIPERIODIC_H #include "picons.h" // Include file Sophya (TArray) #include "tarrinit.h" #include "array.h" #include "timing.h" using namespace std; // .......................................................... // Programme interactive de test des threads ZThread // avec les arrays de Sophya et PI // R. Ansari LAL-IN2P3/CNRS 02/2001 // .......................................................... // ................... MtxComputer ................... // A thread class for doing matrix computation class PIZTApp; class MtxComputer : public ZThread // { public: MtxComputer(PIZTApp * app, PIScale * sc, int id, int sz, int nloop); virtual ~MtxComputer(); virtual void run(); protected: int id_; int sz_; int nloop_; PIZTApp * zapp_; PIScale * sc_; }; // ................... CPUTimer ................... // Periodic class for CPU and elapsed time counting class CPUTimer : public PIPeriodic { public: CPUTimer(PIZTApp * app); virtual void DoPeriodic(); protected: PIZTApp * zapp; int dt; }; // ................... PIZTApp ................... // La classe application // class PIZTApp : public PIApplication , public ZThread { class PIZTApp : public PIApplication { // Pas oblige d'en faire un Thread public: PIZTApp(int narg, char* arg[]); ~PIZTApp(); virtual void Process(PIMessage msg, PIMsgHandler* sender, void* data=NULL); virtual void UpdateCPUTime(); virtual void run(); // // virtual void Run(); Si pas thread ZMutex & getMutex(); // for synchronization protected: PIMenu * m[3]; PIScale *sc[2]; PILabel *tlab[2]; PILabel *cputlab; PIConsole* cons; // CPU and elapsed time CPUTimer tm; clock_t cput0; time_t t0; // The computing threads ZThread * thr[2]; // // for synchronization with other threads ZMutex amon; // int syn_cntrl; }; // ......................................................... // ............. PIZTApp implementation ................. // ......................................................... PIZTApp::PIZTApp(int narg, char* arg[]) : PIApplication(600, 400, narg, arg) , tm(this) // 200 ms timer { if (narg < 3) throw ParmError("PIZTApp::PIZTApp() narg<3 !"); m[0] = new PIMenu(Menubar(),"Fichier"); m[0]->AppendItem("Start", 10101); m[0]->AppendItem("Exit", 10110); AppendMenu(m[0]); m[1] = new PIMenu(Menubar(),"Thread-1"); m[1]->AppendItem("Stop", 10203); AppendMenu(m[1]); m[2] = new PIMenu(Menubar(),"Thread-2"); m[2]->AppendItem("Stop", 10303); AppendMenu(m[2]); cputlab = new PILabel(MainWin(), "CPUTime", 590, 30, 5, 5); cputlab->SetBorderWidth(1); tlab[0] = new PILabel(MainWin(), "Thr-1", 50, 30, 10, 40); sc[0] = new PIScale(MainWin(), "Sc-Thr-1", 510, kSDirLtoR, 220, 40, 70, 40); sc[0]->SetValue(0); tlab[1] = new PILabel(MainWin(), "Thr-2", 50, 30, 300, 40); sc[1] = new PIScale(MainWin(), "Sc-Thr-2", 520, kSDirLtoR, 220, 40, 360, 40); sc[1]->SetValue(0); // Creating the console and redirecting output cons = new PIConsole(MainWin(), "PIConsole", 700, 500, 80, 600, 315, 0, 85, true ); cons->SetBinding(PIBK_fixed, PIBK_fixed, PIBK_fixed, PIBK_fixed); RedirectOutStream(cons); //RedirectErrStream(cons); // Creating matrix Computing thread int nloop = atoi(arg[1]); int size = atoi(arg[2]); thr[0] = new MtxComputer(this, sc[0], 0, size, nloop); thr[1] = new MtxComputer(this, sc[1], 1, size, nloop); cput0 = clock(); t0 = time(NULL); tm.Start(); // We start our cpu timer syn_cntrl = 0; // Normal event loop } PIZTApp::~PIZTApp() { cout << " Getting in PIZTApp::~PIZTApp() - " << endl; int k; cout << " PIZTApp::~PIZTApp() - deleting m[0..2] ... " << endl; for(k=0; k<3; k++) delete m; cout << " PIZTApp::~PIZTApp() - deleting tlab/sc[0..1] ... " << endl; for(k=0; k<2; k++) { delete tlab[k]; delete sc[k]; } cout << " PIZTApp::~PIZTApp() - deleting cputlab ... " << endl; delete cputlab; cout << " PIZTApp::~PIZTApp() - deleting thr[0..1] ... " << endl; delete thr[0]; delete thr[1]; cout << " PIZTApp::~PIZTApp() - deleting cons ... " << endl; delete cons; } void PIZTApp::UpdateCPUTime() { clock_t cput; time_t elt; time_t tm; struct tm * stm; elt = time(&tm); stm = localtime(&tm); cput = clock(); float tcal = ( (float)(cput) - (float)(cput0) ) / (float)(CLOCKS_PER_SEC); float etm = elt - t0; float percen = (elt > t0) ? (tcal*100.)/etm : 0.; char buff[192]; sprintf(buff, "%02d:%02d:%02d CPUTime= %g sec Elapsed= %g sec (%g %%)", stm->tm_hour, stm->tm_min, stm->tm_sec, tcal, etm, percen); string s = buff; cputlab->SetLabel(s); } ZMutex & PIZTApp::getMutex() { syn_cntrl++; return amon; } void PIZTApp::run() // void PIZTApp::Run() Si pas thread { XEvent evt; int szx, szy, szf; XtAppContext * appctx = PIXtAppCtx(szx, szy, szf); // Pour appeler FinishCreate() des objets dans la fenetre principale if (mStop) { // C'est la premiere fois topcont->SetSize(topcont->XSize(), topcont->YSize()); MBCont()->FinishCreate(); } else mStop = true; // On rerentre apres un stop cout << "DBG-PIZTApp::run/Run Starting event loop " << endl; try { while (mStop) { // while (syn_cntrl > 0) { // amon.wait(); // // syn_cntrl = 0; // } while (XtAppPending(*appctx) != 0) { amon.lock(); // XtAppNextEvent(*appctx, &evt); XtDispatchEvent(&evt); amon.unlock(); // } // usleep(1000); } } catch (PThrowable & e) { cerr << "PIZTApp::Run() Catched Exception Msg= " << e.Msg() << endl; } catch (...) { cerr << "PIZTApp::run() Catched ... exception " << endl; } } void PIZTApp::Process(PIMessage msg, PIMsgHandler* sender, void* data) { int num; try { switch(UserMsg(msg)) { case 10101 : // starting computing threads thr[0]->start(); // thr[1]->start(); // break; case 10110 : // stoping computing threads RedirectOutStream(NULL); RedirectErrStream(NULL); cout << " PIZTApp::Process() Waiting for threads to terminate ... " << endl; thr[0]->join(); // thr[1]->join(); // Stop(); break; case 10203 : case 10303 : num = (UserMsg(msg)-10203)/100; thr[num]->stop(); // break; } } catch (ZThreadExc & e) { // cerr << "PIZTApp::Process() Catched ZThreadExc Msg= " << e.Msg() << endl; } catch (...) { cerr << "PIZTApp::Process() Catched ... exception " << endl; } } // ......................................................... // ............. CPUTimer implementation ................. // ......................................................... CPUTimer::CPUTimer(PIZTApp * app) : PIPeriodic(1) { zapp = app; dt = -1; SetIntervalms(200); // 200 ms interval timer } void CPUTimer::DoPeriodic() { dt++; if ((dt == 0) || (dt >= 5)) { zapp->UpdateCPUTime(); dt = 0; } } // ......................................................... // ............. MtxComputer implementation ............... // ......................................................... // A global monitor for print synchronisation ZMutex prtmon; // MtxComputer::MtxComputer(PIZTApp * app, PIScale * sc, int id, int sz, int nloop) { id_ = id; sz_ = sz; nloop_ = nloop; zapp_ = app; sc_ = sc; } MtxComputer::~MtxComputer() { } void MtxComputer::run() { int n = sz_; double seuil = 1.e-6; Matrix id; id = IdentityMatrix(1.,n); double gmax = -1.e99; double gmin = 1.e99; int npb = 0; // Loop creating a random matrix, inverting it // and checking the result for(int k=0; k max) max = diff(i,j); if (fabs(x) > seuil) nerr++; } if (min < gmin) gmin = min; if (max > gmax) gmax = max; if (nerr > 0) npb++; { // Synchronized writing to cout stream ZSync sync(prtmon); // cout << " ------- Thread[" << id_ << "] K= " << k << " NErr = " << nerr << endl; cout << " Min(Diff) = " << min << " Max(Diff) = " << max << endl; if (k == nloop_-1) { double frac = (double)npb*100./(double)nloop_; cout << " ...... Thread[" << id_ << "] End NPb= " << npb << " / NTot= " << nloop_ << " ( = " << frac << " %) " << endl; cout << " GMin(Diff) = " << gmin << " GMax(Diff) = " << gmax << endl; cout << " ..................................................... " << endl; } } { // Synchronized updating of Scale Widget ZSync sync(zapp_->getMutex()); // // The event loop should be stopped until the end of the block int percentage = 100*(k+1)/nloop_; sc_->SetValue(percentage); } } catch (ZThreadExc const & e) { // cerr << "MtxComputer Catched ZThreadExc in Thread(" // << (string)getName() << ") Msg= " << e.Msg() << endl; } catch (PException const & e) { cerr << "MtxComputer Catched PException in Thread(" // << (string)getName() << ") Msg= " << e.Msg() << endl; } } } static void run_piapp(void * x) { PIZTApp * t = (PIZTApp *)x; t->run(); return; } // ......................................................... // ................... The main program .................... // ......................................................... int main(int narg, char* arg[]) { if (narg < 3) { cout << " pizthr - ZThread/PI/Sophya::TArray Test \n " << " ... Usage pizthr NLoop MtxSize [-JTCss ... \n" << " NLoop=10...10^4 MtxSize=10...10^3 \n" << endl; exit(0); } InitTim(); // Initializing the CPU timer int nloop = atoi(arg[1]); int size = atoi(arg[2]); cout << " ::::: pizthr - ZThread/PI/Sophya::TArray Test ::::: \n" << " NLoop= " << nloop << " MtxSize= " << size << endl; try { SophyaInit(); // Sophya Initialization PIZTApp * t = new PIZTApp(narg, arg); // // t->Run(); ZThread * zt = new ZThread(50000); zt->setAction(run_piapp, t); zt->start(); // - starting event loop cout << " Waiting for PIZTApp thread to end ... " << endl; zt->join(); // Waiting for thread to end // PIZTApp * t = new PIZTApp(narg, arg); Si pas thread // t->Run(); Si pas thread cout << " PIZTApp thread ended - deleting PIZTApplication ... " << endl; delete zt; delete t; } catch (PThrowable const & e) { cerr << " Catched PThrowable in main Msg= " << e.Msg() << endl; } catch(...) { cerr << " Catched ... exception in main " << endl; } PrtTim("End of pizthr"); }