Salome HOME
Copyrights update 2015.
[modules/yacs.git] / src / bases / Test / basesTest.cxx
1 // Copyright (C) 2006-2015  CEA/DEN, EDF R&D
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19
20 #include "basesTest.hxx"
21
22 #include <iostream>
23 #include <sstream>
24
25 using namespace YACS::BASES;
26 using namespace YACS;
27 using namespace std;
28
29 //#define _DEVDEBUG_
30 #include "YacsTrace.hxx"
31     
32 Mutex BasesTest::_m;
33 Semaphore BasesTest::_s1;
34 Semaphore BasesTest::_s2;
35 Condition BasesTest::_cond;
36 ostringstream BasesTest::_glob;
37 int BasesTest::_var=7;
38
39 const int BasesTest::THREAD_NUM=5;
40
41 const int BasesTest::LOOPS=4;
42
43 const int BasesTest::MAX_RESOURCE=7;
44
45 int BasesTest::_value=0;
46 int BasesTest::_waiting=0;
47 int BasesTest::_resources=BasesTest::MAX_RESOURCE;
48 int BasesTest::_ownedResources[THREAD_NUM];
49
50 void *BasesTest::th1_1(void *st)
51 {
52   char myName=*((char *) st);
53   _s1.wait();
54   _glob<< myName << _var;
55   _var+=2;
56   _s1.post();
57   _s2.post();
58   return 0;
59 }
60
61 void *BasesTest::th1_2(void *st)
62 {
63   char myName=*((char *) st);
64   _s2.wait();
65   _glob<< myName << _var;
66   _s2.post();
67   return 0;
68 }
69
70 void *BasesTest::th1_3(void *st)
71 {
72   char myName=*((char *) st);
73   _glob<< myName << _var++;
74   _s1.post();
75   return 0;
76 }
77
78 void *BasesTest::th2_1(void *)
79 {
80   int i, tmp;
81   int rc = 0;      
82   for (i=0; i<LOOPS; ++i)
83     {
84       _m.lock();
85       tmp = _value;
86       tmp = tmp+1;
87       Thread::sleep(1000);
88       _value = tmp;
89       _m.unLock();
90       Thread::sleep(100000);
91     }
92   return 0;
93 }
94
95 void *BasesTest::myFunc(void *n)
96 {
97   int id = *((int*) n);
98
99   for (int i=3; i>0; i--)
100     {
101       DEBTRACE("thread " << id << " asks for " << i << " resources");
102       get_resources(id, i);
103       DEBTRACE("thread " << id << " has got " << i << " resources");
104       CPPUNIT_ASSERT(count_resources() == BasesTest::MAX_RESOURCE);
105       Thread::sleep(10000);
106       CPPUNIT_ASSERT(count_resources() == BasesTest::MAX_RESOURCE);
107       DEBTRACE("thread " << id << " frees " << i << " resources");
108       free_resources(id, i);
109     }
110   return 0;
111  }
112
113 void BasesTest::get_resources(int id, int amount)
114 {
115   _m.lock();
116   while (_resources < amount)
117     {
118       _waiting++;
119       _cond.wait(_m); // _m is unlocked during the wait
120     }
121   _resources -= amount;
122   _ownedResources[id] = amount;
123   _m.unLock();
124 }
125
126 void BasesTest::free_resources(int id, int amount)
127 {
128   _m.lock();
129   _resources += amount;
130   _ownedResources[id] = 0;
131   if (_waiting > 0)
132     {
133       _waiting = 0;
134       _cond.notify_all();
135     }
136   _m.unLock();
137 }
138
139 int BasesTest::count_resources()
140 {
141   int resources = 0;
142   int totOwned = 0;
143   {
144     _m.lock();
145     resources = _resources;
146     for (int i=0; i<THREAD_NUM; i++)
147       {
148         totOwned += _ownedResources[i];
149       }
150     _m.unLock();
151   }
152   int total = resources + totOwned;
153   DEBTRACE("resources:: owned by threads: " << totOwned << " remaining: " << resources << " total: " << total);
154   return total;
155 }
156
157 void BasesTest::setUp()
158 {
159 }
160
161 void BasesTest::tearDown()
162 {
163 }
164
165
166 void BasesTest::test1()
167 {
168   char t1Name='A'; char t2Name='B'; char t3Name='C';
169   Thread t1(th1_1,&t1Name);
170   Thread t2(th1_2,&t2Name);
171   Thread t3(th1_3,&t3Name);
172   t1.join();
173   t2.join();
174   t3.join();
175   CPPUNIT_ASSERT( _glob.str() == "C7A8B10" );
176 }
177
178 void BasesTest::test2()
179 {
180   int i;
181   Thread **ths=new Thread *[THREAD_NUM];
182   for (i=0; i<THREAD_NUM; ++i)
183     {
184       ths[i]=new Thread(th2_1,0);
185     }
186   for (i=0; i<THREAD_NUM; ++i)
187     {
188       ths[i]->join();
189       delete ths[i];
190     }
191   delete [] ths;
192   CPPUNIT_ASSERT( _value == THREAD_NUM*LOOPS );
193 }
194
195 void BasesTest::test3()
196 {
197   int i;
198   void *ret;
199   Thread **ths=new Thread *[THREAD_NUM];
200
201   int id[THREAD_NUM];
202   for (i=0; i<THREAD_NUM; i++)
203     {
204       id[i] = i;
205       _ownedResources[i] = 0;
206     }
207   
208   for (i=0; i<THREAD_NUM; i++)
209     {      
210       ths[i] = new Thread(myFunc, &id[i]);
211       CPPUNIT_ASSERT(count_resources() == BasesTest::MAX_RESOURCE);
212     }
213
214   for (i=0; i<THREAD_NUM; i++)
215     {
216       ths[i]->join();
217       delete ths[i];
218       DEBTRACE("thread " << id[i] << " is finished");
219       CPPUNIT_ASSERT(count_resources() == BasesTest::MAX_RESOURCE);
220     }
221 }
222
223 typedef double (*FctPt)(double);
224
225 void BasesTest::testDL()
226 {
227   DynLibLoader *loader=new DynLibLoader("libYACSDLTest");
228   void *symb=loader->getHandleOnSymbolWithName("myYacsFct");
229   FctPt f=(FctPt) symb;
230   double res=f(1.7);
231   CPPUNIT_ASSERT_DOUBLES_EQUAL( 20.23, res, 1e-13);
232   res=f(2.3);
233   CPPUNIT_ASSERT_DOUBLES_EQUAL( 37.03, res, 1e-13);
234   delete loader;
235 }