Salome HOME
Merge from V6_main 01/04/2013
[modules/yacs.git] / src / bases / Test / basesTest.cxx
1 // Copyright (C) 2006-2013  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.
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 }
59
60 void *BasesTest::th1_2(void *st)
61 {
62   char myName=*((char *) st);
63   _s2.wait();
64   _glob<< myName << _var;
65   _s2.post();
66 }
67
68 void *BasesTest::th1_3(void *st)
69 {
70   char myName=*((char *) st);
71   _glob<< myName << _var++;
72   _s1.post();
73 }
74
75 void *BasesTest::th2_1(void *)
76 {
77   int i, tmp;
78   int rc = 0;      
79   for (i=0; i<LOOPS; ++i)
80     {
81       _m.lock();
82       tmp = _value;
83       tmp = tmp+1;
84       Thread::sleep(1000);
85       _value = tmp;
86       _m.unlock();
87       Thread::sleep(100000);
88     }
89 }
90
91 void *BasesTest::myFunc(void *n)
92 {
93   int id = *((int*) n);
94
95   for (int i=3; i>0; i--)
96     {
97       DEBTRACE("thread " << id << " asks for " << i << " resources");
98       get_resources(id, i);
99       DEBTRACE("thread " << id << " has got " << i << " resources");
100       CPPUNIT_ASSERT(count_resources() == BasesTest::MAX_RESOURCE);
101       Thread::sleep(10000);
102       CPPUNIT_ASSERT(count_resources() == BasesTest::MAX_RESOURCE);
103       DEBTRACE("thread " << id << " frees " << i << " resources");
104       free_resources(id, i);
105     }
106 }
107
108 void BasesTest::get_resources(int id, int amount)
109 {
110   _m.lock();
111   while (_resources < amount)
112     {
113       _waiting++;
114       _cond.wait(_m); // _m is unlocked during the wait
115     }
116   _resources -= amount;
117   _ownedResources[id] = amount;
118   _m.unlock(); 
119 }
120
121 void BasesTest::free_resources(int id, int amount)
122 {
123   _m.lock();
124   _resources += amount;
125   _ownedResources[id] = 0;
126   if (_waiting > 0)
127     {
128       _waiting = 0;
129       _cond.notify_all();
130     }
131   _m.unlock();
132 }
133
134 int BasesTest::count_resources()
135 {
136   int resources = 0;
137   int totOwned = 0;
138   {
139     _m.lock();
140     resources = _resources;
141     for (int i=0; i<THREAD_NUM; i++)
142       {
143         totOwned += _ownedResources[i];
144       }
145     _m.unlock();
146   }
147   int total = resources + totOwned;
148   DEBTRACE("resources:: owned by threads: " << totOwned << " remaining: " << resources << " total: " << total);
149   return total;
150 }
151
152 void BasesTest::setUp()
153 {
154 }
155
156 void BasesTest::tearDown()
157 {
158 }
159
160
161 void BasesTest::test1()
162 {
163   char t1Name='A'; char t2Name='B'; char t3Name='C';
164   Thread t1(th1_1,&t1Name);
165   Thread t2(th1_2,&t2Name);
166   Thread t3(th1_3,&t3Name);
167   t1.join();
168   t2.join();
169   t3.join();
170   CPPUNIT_ASSERT( _glob.str() == "C7A8B10" );
171 }
172
173 void BasesTest::test2()
174 {
175   int i;
176   Thread **ths=new Thread *[THREAD_NUM];
177   for (i=0; i<THREAD_NUM; ++i)
178     {
179       ths[i]=new Thread(th2_1,0);
180     }
181   for (i=0; i<THREAD_NUM; ++i)
182     {
183       ths[i]->join();
184       delete ths[i];
185     }
186   delete [] ths;
187   CPPUNIT_ASSERT( _value == THREAD_NUM*LOOPS );
188 }
189
190 void BasesTest::test3()
191 {
192   int i;
193   void *ret;
194   Thread **ths=new Thread *[THREAD_NUM];
195
196   int id[THREAD_NUM];
197   for (i=0; i<THREAD_NUM; i++)
198     {
199       id[i] = i;
200       _ownedResources[i] = 0;
201     }
202   
203   for (i=0; i<THREAD_NUM; i++)
204     {
205       ths[i] = new Thread(myFunc, &id[i]);
206       CPPUNIT_ASSERT(count_resources() == BasesTest::MAX_RESOURCE);
207     }
208
209   for (i=0; i<THREAD_NUM; i++)
210     {
211       ths[i]->join();
212       delete ths[i];
213       DEBTRACE("thread " << id[i] << " is finished");
214       CPPUNIT_ASSERT(count_resources() == BasesTest::MAX_RESOURCE);
215     }
216 }
217
218 typedef double (*FctPt)(double);
219
220 void BasesTest::testDL()
221 {
222   DynLibLoader *loader=new DynLibLoader(".libs/libYACSDLTest");
223   void *symb=loader->getHandleOnSymbolWithName("myYacsFct");
224   FctPt f=(FctPt) symb;
225   double res=f(1.7);
226   CPPUNIT_ASSERT_DOUBLES_EQUAL( 20.23, res, 1e-13);
227   res=f(2.3);
228   CPPUNIT_ASSERT_DOUBLES_EQUAL( 37.03, res, 1e-13);
229   delete loader;
230 }