MBDyn-1.7.3
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups
inusetest.cc
Go to the documentation of this file.
1 /* $Header: /var/cvs/mbdyn/mbdyn/mbdyn-1.0/mbdyn/base/inusetest.cc,v 1.8 2017/01/12 14:46:09 masarati Exp $ */
2 /*
3  * MBDyn (C) is a multibody analysis code.
4  * http://www.mbdyn.org
5  *
6  * Copyright (C) 1996-2017
7  *
8  * Pierangelo Masarati <masarati@aero.polimi.it>
9  * Paolo Mantegazza <mantegazza@aero.polimi.it>
10  *
11  * Dipartimento di Ingegneria Aerospaziale - Politecnico di Milano
12  * via La Masa, 34 - 20156 Milano, Italy
13  * http://www.aero.polimi.it
14  *
15  * Changing this copyright notice is forbidden.
16  *
17  * This program is free software; you can redistribute it and/or modify
18  * it under the terms of the GNU General Public License as published by
19  * the Free Software Foundation (version 2 of the License).
20  *
21  *
22  * This program is distributed in the hope that it will be useful,
23  * but WITHOUT ANY WARRANTY; without even the implied warranty of
24  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25  * GNU General Public License for more details.
26  *
27  * You should have received a copy of the GNU General Public License
28  * along with this program; if not, write to the Free Software
29  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
30  */
31 
32 #include "mbconfig.h" /* This goes first in every *.c,*.cc file */
33 
34 #include <stdlib.h>
35 #include <iostream>
36 #include <cstring>
37 #include "ac/getopt.h"
38 
39 #ifdef USE_MULTITHREAD
40 
41 #include <unistd.h>
42 #include "ac/pthread.h" /* includes POSIX semaphores */
43 
44 #include "mbconfig.h"
45 #include "veciter.h"
46 #include "filename.h"
47 #include "mbsleep.h"
48 
49 unsigned dst = 100;
50 unsigned rst = 10;
51 
52 class A : public InUse {
53 private:
54  unsigned label;
55  unsigned who;
56 public:
57  A(unsigned l) : label(l) {};
58  virtual ~A(void) {};
59 
60  unsigned Label(void) const { return label; };
61  void Set(unsigned w) {
62  who = w;
63 
64  double d = 1.e-6*dst;
65  if (rst) {
66  d += 1.e-6 * (rand() % rst);
67  }
68  mbsleep_t s;
69  mbsleep_real2sleep(d, &s);
70  if (!MBSLEEP_ISZERO(s)) {
71  mbsleep(&s);
72  }
73  };
74  unsigned Get(void) const { return who; };
75 };
76 
77 struct Arg {
78  unsigned n;
79  unsigned cnt;
80  bool stop;
81  pthread_t t;
82  sem_t s;
83  MT_VecIter<A *> i;
84  unsigned *c;
85 };
86 
87 pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
88 pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
89 
90 static void
91 f2(VecIter<A *> &i, unsigned n, unsigned &cnt)
92 {
93  A* pA = NULL;
94 
95  cnt = 0;
96 
97  if (i.bGetFirst(pA)) {
98  do {
99  pA->Set(n);
100  cnt++;
101  } while (i.bGetNext(pA));
102  }
103 }
104 
105 void *
106 f(void *p)
107 {
108  Arg *arg = (Arg *)p;
109 
110  while (true) {
111  sem_wait(&arg->s);
112 
113  if (arg->stop) {
114  break;
115  }
116 
117  f2(arg->i, arg->n, arg->cnt);
118 
119  pthread_mutex_lock(&mutex);
120  --*(arg->c);
121  silent_cout("f: count " << *arg->c + 1 << " => " << *arg->c << std::endl);
122  if (*arg->c == 0) {
123  silent_cout("f: finished" << std::endl);
124  pthread_cond_signal(&cond);
125  }
126  pthread_mutex_unlock(&mutex);
127  }
128 
129  return NULL;
130 }
131 
132 int
133 main(int argc, char* argv[])
134 {
135  unsigned size = 1000;
136  unsigned nt = 1;
137  unsigned loops = 1;
138 
139  if (argc == 1) {
140 usage:;
141  char *s = std::strrchr(argv[0], DIR_SEP);
142 
143  if (s) {
144  s++;
145  } else {
146  s = argv[0];
147  }
148 
149  std::cout << "usage: " << s << " [lnsSt]" << std::endl
150  << "\t-l <loops>" << std::endl
151  << "\t-n <size>" << std::endl
152  << "\t-s <sleeptime>" << std::endl
153  << "\t-S <random sleeptime>" << std::endl
154  << "\t-t <threads number>" << std::endl;
155  exit(EXIT_SUCCESS);
156  }
157 
158  while (true) {
159  char *next;
160  int opt = getopt(argc, argv, "l:n:s:S:t:");
161 
162  if (opt == EOF) {
163  break;
164  }
165 
166  switch (opt) {
167  case 'l':
168  loops = strtoul(optarg, &next, 10);
169  break;
170 
171  case 'n':
172  size = strtoul(optarg, &next, 10);
173  break;
174 
175  case 's':
176  dst = strtoul(optarg, &next, 10);
177  break;
178 
179  case 'S':
180  rst = strtoul(optarg, &next, 10);
181  break;
182 
183  case 't':
184  nt = strtoul(optarg, &next, 10);
185  break;
186 
187  default:
188  goto usage;
189  }
190  }
191 
192  if (nt < 1) {
193  nt = 1;
194  }
195 
196  Arg *arg = NULL;
197  arg = new Arg[nt];
198  unsigned c;
199 
200  A** ppA = new A*[size];
201  for (unsigned i = 0; i < size; i++) {
202  ppA[i] = new A(i);
203  }
204 
205  for (unsigned i = 0; i < nt; i++) {
206  arg[i].n = i;
207  arg[i].i.Init(ppA, size);
208  arg[i].c = &c;
209  arg[i].cnt = 0;
210  arg[i].stop = false;
211 
212  if (i == 0) continue;
213 
214  sem_init(&arg[i].s, 0, 0);
215  pthread_create(&arg[i].t, NULL, f, &arg[i]);
216  }
217 
218  for (unsigned k = 0; k < 10; k++) {
219  arg[0].i.ResetAccessData();
220  c = nt - 1;
221 
222  for (unsigned i = 1; i < nt; i++) {
223  sem_post(&arg[i].s);
224  }
225 
226  f2(arg[0].i, arg[0].n, arg[0].cnt);
227 
228  if (nt > 1) {
229  pthread_mutex_lock(&mutex);
230  if (c) {
231  silent_cout("main: count " << c << std::endl);
232  pthread_cond_wait(&cond, &mutex);
233  silent_cout("main: wait is over; count" << c << std::endl);
234  }
235  pthread_mutex_unlock(&mutex);
236  }
237 
238  c = arg[0].cnt;
239  fprintf(stderr, "cnt = {%u", arg[0].cnt);
240  for (unsigned i = 1; i < nt; i++) {
241  fprintf(stderr, ", %u", arg[i].cnt);
242  c += arg[i].cnt;
243  }
244  fprintf(stderr, "} = %u\n", c);
245 
246  unsigned who[nt];
247  memset(who, 0, sizeof(who));
248  for (unsigned i = 0; i < size; i++) {
249  who[ppA[i]->Get()]++;
250  }
251 
252  c = who[0];
253  fprintf(stderr, "who = {%u", who[0]);
254  for (unsigned i = 1; i < nt; i++) {
255  fprintf(stderr, ", %u", who[i]);
256  c += who[i];
257  }
258  fprintf(stderr, "} = %u\n", c);
259  }
260 
261  for (unsigned i = 1; i < nt; i++) {
262  arg[i].stop = true;
263  sem_post(&arg[i].s);
264  pthread_join(arg[i].t, NULL);
265  }
266 
267  delete[] arg;
268 
269  return 0;
270 }
271 
272 #else /* ! USE_MULTITHREAD */
273 
274 int
275 main(void)
276 {
277  std::cerr << "need --enable-multithread" << std::endl;
278  exit(EXIT_FAILURE);
279 }
280 
281 #endif /* ! USE_MULTITHREAD */
282 
#define MBSLEEP_ISZERO(mbs)
Definition: mbsleep.h:52
bool bGetNext(T &TReturn) const
Definition: veciter.h:118
int mbsleep(const mbsleep_t *t)
Definition: mbsleep.c:90
unsigned long mbsleep_t
Definition: mbsleep.h:51
int main(void)
Definition: inusetest.cc:275
const char DIR_SEP
Definition: filename.h:88
static void usage(void)
Definition: cctest.cc:65
static std::stack< cleanup * > c
Definition: cleanup.cc:59
int getopt(int argc, char *const argv[], const char *opts)
Definition: getopt.c:93
bool bGetFirst(T &TReturn) const
Definition: veciter.h:88
char * optarg
Definition: getopt.c:74
int mbsleep_real2sleep(doublereal d, mbsleep_t *t)
Definition: mbsleep.c:49