Merge pull request #2317 from jwillemsen/jwi-deleteop
[ACE_TAO.git] / ACE / tests / Future_Stress_Test.cpp
blob832a8d148519abb40f703ac65638819015a7a70a
2 //=============================================================================
3 /**
4 * @file Future_Stress_Test.cpp
6 * This example tests the ACE Future set() and get() operations in
7 * multithreaded environment and concurrent access.
9 * Usage: Future_Stress_Test [-t <duration in seconds>]
10 * [-n <number of threads>]
12 * @see https://github.com/DOCGroup/ACE_TAO/issues/2163
14 * @author Andres Kruse <Frank.Hilliger@cs-sol.de>
16 //=============================================================================
18 #include "test_config.h"
19 #include <ace/Time_Value.h>
20 #include <ace/Countdown_Time.h>
21 #include <ace/Future.h>
22 #include <ace/Get_Opt.h>
24 #include <random>
27 #if defined (ACE_HAS_THREADS)
29 struct Worker_Config
31 int a;
32 int b;
33 int c;
34 ACE_Future<int> result;
37 void* worker (void* args)
39 Worker_Config* config = static_cast<Worker_Config*>(args);
40 int r = config->a + config->b * config->c;
41 config->result.set(r);
43 return 0;
46 void* runner (void* args)
48 ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("(%t) runner start\n")));
50 std::random_device rd;
51 std::mt19937 gen(rd());
52 std::uniform_int_distribution<> dis(1,1000000);
53 ACE_Time_Value* duration = static_cast<ACE_Time_Value*>(args);
54 ACE_Countdown_Time timer(duration);
55 timer.start();
56 uint64_t runNum = 0;
59 if( ++runNum % 5000 == 0 )
61 ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("(%t) runner iteration %u\n"), runNum));
63 ACE_Future<int> result;
64 Worker_Config config;
65 config.a = dis(gen);
66 config.b = dis(gen);
67 config.c = dis(gen);
68 config.result = result;
69 ACE_hthread_t thread_id;
70 int expected_res = config.a+config.b*config.c;
71 int actual_res = -1;
72 if (ACE_Thread::spawn((ACE_THR_FUNC)worker,
73 static_cast<void*>(&config), THR_NEW_LWP | THR_JOINABLE, 0,
74 &thread_id) == -1)
76 ACE_ERROR ((LM_INFO,
77 ACE_TEXT ("worker thread spawn failed\n")));
79 result.get(actual_res);
80 if( actual_res != expected_res )
82 // hit the bug...
83 ACE_ERROR ((LM_INFO,
84 ACE_TEXT ("unexpected ACE_Future result\n")));
85 abort();
87 ACE_THR_FUNC_RETURN status;
88 ACE_Thread::join(thread_id, &status);
89 timer.update();
90 } while( *duration != ACE_Time_Value::zero );
91 ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("(%t) runner done\n"), runNum));
93 return 0;
96 int
97 run_main (int argc, ACE_TCHAR *argv[])
99 ACE_START_TEST (ACE_TEXT ("Future_Stress_Test"));
101 ACE_Time_Value duration(5);
102 long n_threads = 5;
104 ACE_Get_Opt getopt (argc, argv, ACE_TEXT ("t:n:"));
105 bool valid = true;
106 int c;
107 while ((c = getopt ()) != -1 && valid)
109 //FUZZ: enable check_for_lack_ACE_OS
110 switch (c)
112 case 't':
113 duration.set(ACE_OS::atoi (getopt.opt_arg ()));
114 break;
115 case 'n':
116 n_threads = ACE_OS::atoi (getopt.opt_arg ());
117 break;
118 default:
119 ACE_ERROR ((LM_ERROR,
120 "Usage: Future_Stress_Test [-t <duration in seconds>]"
121 "\t[-n <number of threads>]\n"));
122 valid = false;
123 break;
127 if (valid)
129 ACE_Thread_Manager::instance ()->spawn_n (n_threads,
130 ACE_THR_FUNC (runner),
131 static_cast<void*>(&duration),
132 THR_NEW_LWP | THR_DETACHED);
134 ACE_Thread_Manager::instance ()->wait ();
135 ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("(%t) All threads finished, cleanup and exit\n")));
137 ACE_END_TEST;
138 return 0;
141 #else
143 run_main (int, ACE_TCHAR *[])
145 ACE_ERROR ((LM_INFO,
146 ACE_TEXT ("threads not supported on this platform\n")));
148 #endif /* ACE_HAS_THREADS */