1
// future1.cpp,v 4.25 2004/01/05 22:57:06 shuston Exp
3
// ============================================================================
12
// This example tests the ACE Future.
15
// Andres Kruse <Andres.Kruse@cern.ch> and Douglas C. Schmidt
16
// <schmidt@cs.wustl.edu>
18
// ============================================================================
20
#include "ace/OS_NS_string.h"
21
#include "ace/OS_main.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"
32
ACE_RCSID(Threads, future1, "future1.cpp,v 4.25 2004/01/05 22:57:06 shuston Exp")
34
#if defined (ACE_HAS_THREADS)
36
typedef ACE_Atomic_Op<ACE_Thread_Mutex, int> ATOMIC_INT;
38
// a counter for the tasks..
39
static ATOMIC_INT task_count (0);
41
// a counter for the futures..
42
static ATOMIC_INT future_count (0);
43
static ATOMIC_INT future_no (0);
45
// a counter for the capsules..
46
static ATOMIC_INT capsule_count (0);
47
static ATOMIC_INT capsule_no (0);
49
// a counter for the method objects...
50
static ATOMIC_INT methodobject_count (0);
51
static ATOMIC_INT methodobject_no (0);
53
class Scheduler : public ACE_Task_Base
55
// Active Object Scheduler.
57
friend class Method_RequestWork;
59
Scheduler (const char *, Scheduler * = 0);
60
virtual ~Scheduler (void);
62
virtual int open (void *args = 0);
63
virtual int close (u_long flags = 0);
64
virtual int svc (void);
66
ACE_Future<u_long> work (u_long param, int count = 1);
67
ACE_Future<const char*> name (void);
70
u_long work_i (u_long, int);
71
const char *name_i (void);
75
ACE_Activation_Queue activation_queue_;
76
Scheduler *scheduler_;
79
class Method_Request_work : public ACE_Method_Request
81
// Reification of the <work> method.
84
Method_Request_work (Scheduler *, u_long, int, ACE_Future<u_long> &);
85
virtual ~Method_Request_work (void);
86
virtual int call (void);
89
Scheduler *scheduler_;
92
ACE_Future<u_long> future_result_;
95
Method_Request_work::Method_Request_work (Scheduler* new_Scheduler,
98
ACE_Future<u_long> &new_result)
99
: scheduler_ (new_Scheduler),
102
future_result_ (new_result)
104
ACE_DEBUG ((LM_DEBUG,
105
"(%t) Method_Request_work created\n"));
108
Method_Request_work::~Method_Request_work (void)
110
ACE_DEBUG ((LM_DEBUG, "(%t) Method_Request_work will be deleted.\n"));
115
Method_Request_work::call (void)
117
return this->future_result_.set (this->scheduler_->work_i (this->param_, this->count_));
120
class Method_Request_name : public ACE_Method_Request
122
// Reification of the <name> method.
125
Method_Request_name (Scheduler *, ACE_Future<const char*> &);
126
virtual ~Method_Request_name (void);
127
virtual int call (void);
130
Scheduler *scheduler_;
131
ACE_Future<const char *> future_result_;
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)
139
ACE_DEBUG ((LM_DEBUG,
140
"(%t) Method_Request_name created\n"));
143
Method_Request_name::~Method_Request_name (void)
145
ACE_DEBUG ((LM_DEBUG,
146
"(%t) Method_Request_name will be deleted.\n"));
150
Method_Request_name::call (void)
152
return future_result_.set (scheduler_->name_i ());
155
class Method_Request_end : public ACE_Method_Request
157
// Reification of the <end> method.
160
Method_Request_end (Scheduler *new_scheduler): scheduler_ (new_scheduler) {}
161
virtual ~Method_Request_end (void) {}
162
virtual int call (void) { return -1; }
165
Scheduler *scheduler_;
166
// Keep track of our scheduler.
170
Scheduler::Scheduler (const char *newname,
171
Scheduler *new_scheduler)
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_));
180
Scheduler::~Scheduler (void)
182
ACE_DEBUG ((LM_DEBUG, "(%t) Scheduler %s will be destroyed\n", this->name_));
183
delete [] this->name_;
188
Scheduler::open (void *)
191
ACE_DEBUG ((LM_DEBUG, "(%t) Scheduler %s open\n", this->name_));
192
return this->activate (THR_BOUND);
197
Scheduler::close (u_long)
199
ACE_DEBUG ((LM_DEBUG, "(%t) Scheduler %s close\n", this->name_));
206
Scheduler::svc (void)
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 ());
214
ACE_DEBUG ((LM_DEBUG, "(%t) calling method object\n"));
216
if (mo->call () == -1)
218
// Destructor automatically deletes it.
226
Scheduler::end (void)
228
this->activation_queue_.enqueue (new Method_Request_end (this));
232
// Here's where the Work takes place.
234
Scheduler::work_i (u_long param,
237
ACE_UNUSED_ARG (count);
239
return ACE::is_prime (param, 2, param / 2);
243
Scheduler::name_i (void)
247
ACE_NEW_RETURN (the_name, char[ACE_OS::strlen (this->name_) + 1], 0);
248
ACE_OS::strcpy (the_name, this->name_);
253
ACE_Future<const char *>
254
Scheduler::name (void)
256
if (this->scheduler_)
257
// Delegate to the Scheduler.
258
return this->scheduler_->name ();
261
ACE_Future<const char*> new_future;
263
// @@ What happens if new fails here?
264
this->activation_queue_.enqueue
265
(new Method_Request_name (this, new_future));
272
Scheduler::work (u_long newparam,
275
if (this->scheduler_) {
276
return this->scheduler_->work (newparam, newcount);
279
ACE_Future<u_long> new_future;
281
this->activation_queue_.enqueue
282
(new Method_Request_work (this, newparam, newcount, new_future));
287
// @@ These values should be set by the command line options!
289
// Total number of loops.
290
static size_t n_loops = 100;
293
ACE_TMAIN (int, ACE_TCHAR *[])
295
Scheduler *andres, *peter, *helmut, *matias;
297
// Create active objects..
298
// @@ Should "open" be subsumed within the constructor of
300
ACE_NEW_RETURN (andres, Scheduler ("andres"), -1);
302
ACE_NEW_RETURN (peter, Scheduler ("peter"), -1);
304
ACE_NEW_RETURN (helmut, Scheduler ("helmut"), -1);
307
// Matias passes all asynchronous method calls on to Andres...
308
ACE_NEW_RETURN (matias, Scheduler ("matias", andres), -1);
311
for (size_t i = 0; i < n_loops; i++)
314
ACE_Future<u_long> fresulta, fresultb, fresultc, fresultd, fresulte;
315
ACE_Future<const char *> fname;
317
ACE_DEBUG ((LM_DEBUG, "(%t) going to do a non-blocking call\n"));
319
fresulta = andres->work (9013);
320
fresultb = peter->work (9013);
321
fresultc = helmut->work (9013);
322
fresultd = matias->work (9013);
323
fname = andres->name ();
325
// see if the result is available...
326
if (fresulta.ready ())
327
ACE_DEBUG ((LM_DEBUG, "(%t) wow.. work is ready.....\n"));
329
ACE_DEBUG ((LM_DEBUG, "(%t) non-blocking call done... now blocking...\n"));
331
// Save the result of fresulta.
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);
345
u_long resulta = 0, resultb = 0, resultc = 0, resultd = 0, resulte = 0;
347
fresulta.get (resulta);
348
fresultb.get (resultb);
349
fresultc.get (resultc);
350
fresultd.get (resultd);
351
fresulte.get (resulte);
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));
363
ACE_DEBUG ((LM_DEBUG, "(%t) name %s\n", name));
364
delete [] (char *) name;
367
ACE_DEBUG ((LM_DEBUG,
368
"(%t) task_count %d future_count %d capsule_count %d methodobject_count %d\n",
370
future_count.value (),
371
capsule_count.value (),
372
methodobject_count.value ()));
375
// Close things down.
383
ACE_DEBUG ((LM_DEBUG,
384
"(%t) task_count %d future_count %d capsule_count %d methodobject_count %d\n",
386
future_count.value (),
387
capsule_count.value (),
388
methodobject_count.value ()));
390
ACE_DEBUG ((LM_DEBUG,"(%t) th' that's all folks!\n"));
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 */
431
ACE_TMAIN (int, ACE_TCHAR *[])
433
ACE_ERROR ((LM_ERROR, "threads not supported on this platform\n"));
436
#endif /* ACE_HAS_THREADS */