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