~ubuntu-branches/ubuntu/breezy/ace/breezy

« back to all changes in this revision

Viewing changes to examples/Threads/future1.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Adam Conrad, Benjamin Montgomery, Adam Conrad
  • Date: 2005-09-18 22:51:38 UTC
  • mfrom: (1.2.1 upstream) (2.1.1 sarge) (0.1.2 woody)
  • Revision ID: james.westby@ubuntu.com-20050918225138-seav22q6fyylb536
Tags: 5.4.7-3ubuntu1
[ Benjamin Montgomery ]
* Added a patch for amd64 and powerpc that disables the compiler
  option -fvisibility-inlines-hidden

[ Adam Conrad ]
* Added DPATCH_OPTION_CPP=1 to debian/patches/00options to make
  Benjamin's above changes work correctly with dpatch.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
// future1.cpp,v 4.25 2004/01/05 22:57:06 shuston Exp
2
 
 
3
 
// ============================================================================
4
 
//
5
 
// = LIBRARY
6
 
//    tests
7
 
//
8
 
// = FILENAME
9
 
//    Test_Future.cpp
10
 
//
11
 
// = DESCRIPTION
12
 
//    This example tests the ACE Future.
13
 
//
14
 
// = AUTHOR
15
 
//    Andres Kruse <Andres.Kruse@cern.ch> and Douglas C. Schmidt
16
 
//    <schmidt@cs.wustl.edu>
17
 
//
18
 
// ============================================================================
19
 
 
20
 
#include "ace/OS_NS_string.h"
21
 
#include "ace/OS_main.h"
22
 
#include "ace/ACE.h"
23
 
#include "ace/Task.h"
24
 
#include "ace/Thread_Mutex.h"
25
 
#include "ace/Message_Queue.h"
26
 
#include "ace/Future.h"
27
 
#include "ace/Method_Request.h"
28
 
#include "ace/Activation_Queue.h"
29
 
#include "ace/Auto_Ptr.h"
30
 
#include "ace/Atomic_Op.h"
31
 
 
32
 
ACE_RCSID(Threads, future1, "future1.cpp,v 4.25 2004/01/05 22:57:06 shuston Exp")
33
 
 
34
 
#if defined (ACE_HAS_THREADS)
35
 
 
36
 
typedef ACE_Atomic_Op<ACE_Thread_Mutex, int> ATOMIC_INT;
37
 
 
38
 
// a counter for the tasks..
39
 
static ATOMIC_INT task_count (0);
40
 
 
41
 
// a counter for the futures..
42
 
static ATOMIC_INT future_count (0);
43
 
static ATOMIC_INT future_no (0);
44
 
 
45
 
// a counter for the capsules..
46
 
static ATOMIC_INT capsule_count (0);
47
 
static ATOMIC_INT capsule_no (0);
48
 
 
49
 
// a counter for the method objects...
50
 
static ATOMIC_INT methodobject_count (0);
51
 
static ATOMIC_INT methodobject_no (0);
52
 
 
53
 
class Scheduler : public ACE_Task_Base
54
 
  // = TITLE
55
 
  //     Active Object Scheduler.
56
 
{
57
 
  friend class Method_RequestWork;
58
 
public:
59
 
  Scheduler (const char *, Scheduler * = 0);
60
 
  virtual ~Scheduler (void);
61
 
 
62
 
  virtual int open (void *args = 0);
63
 
  virtual int close (u_long flags = 0);
64
 
  virtual int svc (void);
65
 
 
66
 
  ACE_Future<u_long> work (u_long param, int count = 1);
67
 
  ACE_Future<const char*> name (void);
68
 
  void end (void);
69
 
 
70
 
  u_long work_i (u_long, int);
71
 
  const char *name_i (void);
72
 
 
73
 
private:
74
 
  char *name_;
75
 
  ACE_Activation_Queue activation_queue_;
76
 
  Scheduler *scheduler_;
77
 
};
78
 
 
79
 
class Method_Request_work : public ACE_Method_Request
80
 
  // = TITLE
81
 
  //     Reification of the <work> method.
82
 
{
83
 
public:
84
 
  Method_Request_work (Scheduler *, u_long, int, ACE_Future<u_long> &);
85
 
  virtual ~Method_Request_work (void);
86
 
  virtual int call (void);
87
 
 
88
 
private:
89
 
  Scheduler *scheduler_;
90
 
  u_long param_;
91
 
  int count_;
92
 
  ACE_Future<u_long> future_result_;
93
 
};
94
 
 
95
 
Method_Request_work::Method_Request_work (Scheduler* new_Scheduler,
96
 
                                        u_long new_param,
97
 
                                        int new_count,
98
 
                                        ACE_Future<u_long> &new_result)
99
 
  :   scheduler_ (new_Scheduler),
100
 
      param_ (new_param),
101
 
      count_ (new_count),
102
 
      future_result_ (new_result)
103
 
{
104
 
  ACE_DEBUG ((LM_DEBUG,
105
 
              "(%t) Method_Request_work created\n"));
106
 
}
107
 
 
108
 
Method_Request_work::~Method_Request_work (void)
109
 
{
110
 
  ACE_DEBUG ((LM_DEBUG, "(%t) Method_Request_work will be deleted.\n"));
111
 
}
112
 
 
113
 
 
114
 
int
115
 
Method_Request_work::call (void)
116
 
{
117
 
  return this->future_result_.set (this->scheduler_->work_i (this->param_, this->count_));
118
 
}
119
 
 
120
 
class Method_Request_name : public ACE_Method_Request
121
 
  // = TITLE
122
 
  //     Reification of the <name> method.
123
 
{
124
 
public:
125
 
  Method_Request_name (Scheduler *, ACE_Future<const char*> &);
126
 
  virtual ~Method_Request_name (void);
127
 
  virtual int call (void);
128
 
 
129
 
private:
130
 
  Scheduler *scheduler_;
131
 
  ACE_Future<const char *> future_result_;
132
 
};
133
 
 
134
 
Method_Request_name::Method_Request_name (Scheduler *new_scheduler,
135
 
                                        ACE_Future<const char *> &new_result)
136
 
  : scheduler_ (new_scheduler),
137
 
    future_result_ (new_result)
138
 
{
139
 
  ACE_DEBUG ((LM_DEBUG,
140
 
              "(%t) Method_Request_name created\n"));
141
 
}
142
 
 
143
 
Method_Request_name::~Method_Request_name (void)
144
 
{
145
 
  ACE_DEBUG ((LM_DEBUG,
146
 
              "(%t) Method_Request_name will be deleted.\n"));
147
 
}
148
 
 
149
 
int
150
 
Method_Request_name::call (void)
151
 
{
152
 
  return future_result_.set (scheduler_->name_i ());
153
 
}
154
 
 
155
 
class Method_Request_end : public ACE_Method_Request
156
 
  // = TITLE
157
 
  //     Reification of the <end> method.
158
 
{
159
 
public:
160
 
  Method_Request_end (Scheduler *new_scheduler): scheduler_ (new_scheduler) {}
161
 
  virtual ~Method_Request_end (void) {}
162
 
  virtual int call (void) { return -1; }
163
 
 
164
 
private:
165
 
  Scheduler *scheduler_;
166
 
  // Keep track of our scheduler.
167
 
};
168
 
 
169
 
// Constructor.
170
 
Scheduler::Scheduler (const char *newname,
171
 
                      Scheduler *new_scheduler)
172
 
{
173
 
  ACE_NEW (this->name_, char[ACE_OS::strlen (newname) + 1]);
174
 
  ACE_OS::strcpy (this->name_, newname);
175
 
  this->scheduler_ = new_scheduler;
176
 
  ACE_DEBUG ((LM_DEBUG, "(%t) Scheduler %s created\n", this->name_));
177
 
}
178
 
 
179
 
// Destructor
180
 
Scheduler::~Scheduler (void)
181
 
{
182
 
  ACE_DEBUG ((LM_DEBUG, "(%t) Scheduler %s will be destroyed\n", this->name_));
183
 
  delete [] this->name_;
184
 
}
185
 
 
186
 
// open
187
 
int
188
 
Scheduler::open (void *)
189
 
{
190
 
  task_count++;
191
 
  ACE_DEBUG ((LM_DEBUG, "(%t) Scheduler %s open\n", this->name_));
192
 
  return this->activate (THR_BOUND);
193
 
}
194
 
 
195
 
// close
196
 
int
197
 
Scheduler::close (u_long)
198
 
{
199
 
  ACE_DEBUG ((LM_DEBUG, "(%t) Scheduler %s close\n", this->name_));
200
 
  task_count--;
201
 
  return 0;
202
 
}
203
 
 
204
 
// service..
205
 
int
206
 
Scheduler::svc (void)
207
 
{
208
 
  for (;;)
209
 
    {
210
 
      // Dequeue the next method object (we use an auto pointer in
211
 
      // case an exception is thrown in the <call>).
212
 
      auto_ptr<ACE_Method_Request> mo (this->activation_queue_.dequeue ());
213
 
 
214
 
      ACE_DEBUG ((LM_DEBUG, "(%t) calling method object\n"));
215
 
      // Call it.
216
 
      if (mo->call () == -1)
217
 
        break;
218
 
      // Destructor automatically deletes it.
219
 
    }
220
 
 
221
 
  /* NOTREACHED */
222
 
  return 0;
223
 
}
224
 
 
225
 
void
226
 
Scheduler::end (void)
227
 
{
228
 
  this->activation_queue_.enqueue (new Method_Request_end (this));
229
 
}
230
 
 
231
 
 
232
 
// Here's where the Work takes place.
233
 
u_long
234
 
Scheduler::work_i (u_long param,
235
 
                   int count)
236
 
{
237
 
  ACE_UNUSED_ARG (count);
238
 
 
239
 
  return ACE::is_prime (param, 2, param / 2);
240
 
}
241
 
 
242
 
const char *
243
 
Scheduler::name_i (void)
244
 
{
245
 
  char *the_name;
246
 
 
247
 
  ACE_NEW_RETURN (the_name, char[ACE_OS::strlen (this->name_) + 1], 0);
248
 
  ACE_OS::strcpy (the_name, this->name_);
249
 
 
250
 
  return the_name;
251
 
}
252
 
 
253
 
ACE_Future<const char *>
254
 
Scheduler::name (void)
255
 
{
256
 
  if (this->scheduler_)
257
 
    // Delegate to the Scheduler.
258
 
    return this->scheduler_->name ();
259
 
  else
260
 
    {
261
 
      ACE_Future<const char*> new_future;
262
 
 
263
 
      // @@ What happens if new fails here?
264
 
      this->activation_queue_.enqueue
265
 
        (new Method_Request_name (this, new_future));
266
 
 
267
 
      return new_future;
268
 
    }
269
 
}
270
 
 
271
 
ACE_Future<u_long>
272
 
Scheduler::work (u_long newparam,
273
 
                 int newcount)
274
 
{
275
 
  if (this->scheduler_) {
276
 
    return this->scheduler_->work (newparam, newcount);
277
 
  }
278
 
  else {
279
 
    ACE_Future<u_long> new_future;
280
 
 
281
 
    this->activation_queue_.enqueue
282
 
      (new Method_Request_work (this, newparam, newcount, new_future));
283
 
    return new_future;
284
 
  }
285
 
}
286
 
 
287
 
// @@ These values should be set by the command line options!
288
 
 
289
 
// Total number of loops.
290
 
static size_t n_loops = 100;
291
 
 
292
 
int
293
 
ACE_TMAIN (int, ACE_TCHAR *[])
294
 
{
295
 
  Scheduler *andres, *peter, *helmut, *matias;
296
 
 
297
 
  // Create active objects..
298
 
  // @@ Should "open" be subsumed within the constructor of
299
 
  // Scheduler()?
300
 
  ACE_NEW_RETURN (andres, Scheduler ("andres"), -1);
301
 
  andres->open ();
302
 
  ACE_NEW_RETURN (peter, Scheduler ("peter"), -1);
303
 
  peter->open ();
304
 
  ACE_NEW_RETURN (helmut, Scheduler ("helmut"), -1);
305
 
  helmut->open ();
306
 
 
307
 
  // Matias passes all asynchronous method calls on to Andres...
308
 
  ACE_NEW_RETURN (matias, Scheduler ("matias", andres), -1);
309
 
  matias->open ();
310
 
 
311
 
  for (size_t i = 0; i < n_loops; i++)
312
 
    {
313
 
      {
314
 
        ACE_Future<u_long> fresulta, fresultb, fresultc, fresultd, fresulte;
315
 
        ACE_Future<const char *> fname;
316
 
 
317
 
        ACE_DEBUG ((LM_DEBUG, "(%t) going to do a non-blocking call\n"));
318
 
 
319
 
        fresulta = andres->work (9013);
320
 
        fresultb = peter->work (9013);
321
 
        fresultc = helmut->work (9013);
322
 
        fresultd = matias->work (9013);
323
 
        fname = andres->name ();
324
 
 
325
 
        // see if the result is available...
326
 
        if (fresulta.ready ())
327
 
          ACE_DEBUG ((LM_DEBUG, "(%t) wow.. work is ready.....\n"));
328
 
 
329
 
        ACE_DEBUG ((LM_DEBUG, "(%t) non-blocking call done... now blocking...\n"));
330
 
 
331
 
        // Save the result of fresulta.
332
 
 
333
 
        fresulte = fresulta;
334
 
 
335
 
        if (i % 3 == 0)
336
 
          {
337
 
            // Every 3rd time... disconnect the futures...
338
 
            // but "fresulte" should still contain the result...
339
 
            fresulta.cancel (10);
340
 
            fresultb.cancel (20);
341
 
            fresultc.cancel (30);
342
 
            fresultd.cancel (40);
343
 
          }
344
 
 
345
 
        u_long resulta = 0, resultb = 0, resultc = 0, resultd = 0, resulte = 0;
346
 
 
347
 
        fresulta.get (resulta);
348
 
        fresultb.get (resultb);
349
 
        fresultc.get (resultc);
350
 
        fresultd.get (resultd);
351
 
        fresulte.get (resulte);
352
 
 
353
 
        ACE_DEBUG ((LM_DEBUG, "(%t) result a %u\n", (u_int) resulte));
354
 
        ACE_DEBUG ((LM_DEBUG, "(%t) result b %u\n", (u_int) resulta));
355
 
        ACE_DEBUG ((LM_DEBUG, "(%t) result c %u\n", (u_int) resultb));
356
 
        ACE_DEBUG ((LM_DEBUG, "(%t) result d %u\n", (u_int) resultc));
357
 
        ACE_DEBUG ((LM_DEBUG, "(%t) result e %u\n", (u_int) resultd));
358
 
 
359
 
        const char *name;
360
 
 
361
 
        fname.get (name);
362
 
 
363
 
        ACE_DEBUG ((LM_DEBUG, "(%t) name %s\n", name));
364
 
        delete [] (char *) name;
365
 
      }
366
 
 
367
 
      ACE_DEBUG ((LM_DEBUG,
368
 
                  "(%t) task_count %d future_count %d capsule_count %d methodobject_count %d\n",
369
 
                  task_count.value (),
370
 
                  future_count.value (),
371
 
                  capsule_count.value (),
372
 
                  methodobject_count.value ()));
373
 
    }
374
 
 
375
 
  // Close things down.
376
 
  andres->end ();
377
 
  peter->end ();
378
 
  helmut->end ();
379
 
  matias->end ();
380
 
 
381
 
  ACE_OS::sleep (2);
382
 
 
383
 
  ACE_DEBUG ((LM_DEBUG,
384
 
              "(%t) task_count %d future_count %d capsule_count %d methodobject_count %d\n",
385
 
              task_count.value (),
386
 
              future_count.value (),
387
 
              capsule_count.value (),
388
 
              methodobject_count.value ()));
389
 
 
390
 
  ACE_DEBUG ((LM_DEBUG,"(%t) th' that's all folks!\n"));
391
 
 
392
 
  ACE_OS::sleep (5);
393
 
  return 0;
394
 
}
395
 
 
396
 
#if defined (ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION)
397
 
template class ACE_Atomic_Op_Ex<ACE_Thread_Mutex, int>;
398
 
template class ACE_Atomic_Op<ACE_Thread_Mutex, int>;
399
 
template class ACE_Future<const char *>;
400
 
template class ACE_Future<u_long>;
401
 
template class ACE_Future_Rep<const char *>;
402
 
template class ACE_Future_Rep<u_long>;
403
 
template class auto_ptr<ACE_Method_Request>;
404
 
template class ACE_Auto_Basic_Ptr<ACE_Method_Request>;
405
 
template class ACE_Node<ACE_Future_Observer<const char *> *>;
406
 
template class ACE_Node<ACE_Future_Observer<u_long> *>;
407
 
template class ACE_Unbounded_Set<ACE_Future_Observer<const char *> *>;
408
 
template class ACE_Unbounded_Set<ACE_Future_Observer<u_long> *>;
409
 
template class ACE_Unbounded_Set_Iterator<ACE_Future_Observer<const char *> *>;
410
 
template class ACE_Unbounded_Set_Iterator<ACE_Future_Observer<u_long> *>;
411
 
#elif defined (ACE_HAS_TEMPLATE_INSTANTIATION_PRAGMA)
412
 
#pragma instantiate ACE_Atomic_Op_Ex<ACE_Thread_Mutex, int>
413
 
#pragma instantiate ACE_Atomic_Op<ACE_Thread_Mutex, int>
414
 
#pragma instantiate ACE_Atomic_Op_Ex<ACE_Thread_Mutex, int>
415
 
#pragma instantiate ACE_Future<const char *>
416
 
#pragma instantiate ACE_Future<u_long>
417
 
#pragma instantiate ACE_Future_Rep<const char *>
418
 
#pragma instantiate ACE_Future_Rep<u_long>
419
 
#pragma instantiate auto_ptr<ACE_Method_Request>
420
 
#pragma instantiate ACE_Auto_Basic_Ptr<ACE_Method_Request>
421
 
#pragma instantiate ACE_Node<ACE_Future_Observer<const char *> *>
422
 
#pragma instantiate ACE_Node<ACE_Future_Observer<u_long> *>
423
 
#pragma instantiate ACE_Unbounded_Set<ACE_Future_Observer<const char *> *>
424
 
#pragma instantiate ACE_Unbounded_Set<ACE_Future_Observer<u_long> *>
425
 
#pragma instantiate ACE_Unbounded_Set_Iterator<ACE_Future_Observer<const char *> *>
426
 
#pragma instantiate ACE_Unbounded_Set_Iterator<ACE_Future_Observer<u_long> *>
427
 
#endif /* ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION */
428
 
 
429
 
#else
430
 
int
431
 
ACE_TMAIN (int, ACE_TCHAR *[])
432
 
{
433
 
  ACE_ERROR ((LM_ERROR, "threads not supported on this platform\n"));
434
 
  return 0;
435
 
}
436
 
#endif /* ACE_HAS_THREADS */