2.4.14. age_fifo.cpp
#
2.4.14.1. Source code#
1// University of Florida EEL6528
2// Tan F. Wong
3// Jan 17, 2021
4
5#include <uhd/utils/safe_main.hpp>
6#include <uhd/utils/thread.hpp>
7#include <boost/program_options.hpp>
8#include <thread>
9#include <csignal>
10#include <sstream>
11#include "queue.hpp"
12
13namespace po = boost::program_options;
14
15// Interrupt signal handlers
16static bool stop_signal_called = false;
17void sig_int_handler(int){
18 stop_signal_called = true;
19}
20
21// worker function to generate age message and push it to FIFO
22void print_age(std::string name, int age, bool nice, MutexFIFO<std::string>& fifo) {
23
24 // Set thread priority to highest
25 uhd::set_thread_priority_safe(1.0, true);
26 std::ostringstream message;
27 if (nice) {
28 // nice printing
29 if (age < 0) {
30 message << "Main thread popped message from Thread #" << std::this_thread::get_id() << ": " << name << "'s age is unknown." << std::endl;
31 } else {
32 message << "Main thread popped message from Thread #" << std::this_thread::get_id() << ": " << name << " is " << age << " years old." << std::endl;
33 }
34 } else {
35 // not nice printing
36 message << "Main thread popped message from Thread #" << std::this_thread::get_id() << ": " << std::endl << "Name = " << name << std::endl << "Age = " << age << std::endl;
37 }
38 while (not stop_signal_called) {
39 fifo.push(message.str());
40 std::this_thread::sleep_for(std::chrono::seconds(1)); // Just don't go too fast
41 }
42}
43
44int UHD_SAFE_MAIN(int argc, char *argv[]){
45
46 // Set main thread priority to highest
47 uhd::set_thread_priority_safe(1.0, true);
48
49 //variables to be set by po
50 std::string name;
51 int age;
52
53 //setup the program options
54 po::options_description desc("Allowed options");
55 desc.add_options()
56 ("help", "help message")
57 ("name,n", po::value<std::string>(&name)->default_value("This person"), "The person's name")
58 ("age,a", po::value<int>(&age)->default_value(-1), "The person's age")
59 ("nice-print", "Print out the info nicely")
60 ;
61
62 po::variables_map vm;
63 po::store(po::parse_command_line(argc, argv, desc), vm);
64 po::notify(vm);
65
66 //print the help message
67 if (vm.count("help")){
68 std::cout << desc << std::endl;
69 return EXIT_SUCCESS;
70 }
71
72 std::signal(SIGINT, &sig_int_handler);
73
74 // Construct FIFO to hold all messages
75 MutexFIFO<std::string> fifo;
76
77 // Spawn 10 worker threads
78 int num_threads = 10;
79 std::thread worker[num_threads];
80 for (int i=0; i<num_threads; i++) {
81 worker[i] = std::thread(&print_age, name, age, vm.count("nice-print"), std::ref(fifo));
82 }
83
84 std::string message;
85
86 // Keep running until CTRL-C issued
87 while (not stop_signal_called) {
88 if (fifo.pop(message))
89 std::cout << message << " (" << fifo.size() << " messages left in FIFO)" << std::endl;
90 else
91 std::cout << " FIFO is empty!" << std::endl;
92 // The sleep_for time here determines the service rate
93 std::this_thread::sleep_for(std::chrono::milliseconds(80));
94 }
95
96 // Join all worker threads
97 for (int i=0; i<10; i++) {
98 if (worker[i].joinable()) worker[i].join();
99 }
100
101 std::cout << std::endl;
102 return EXIT_SUCCESS;
103}
Ten worker threads push messages to the FIFO queue. Each thread pushes one message into the FIFO queue each second. Hence, the total arrival rate is 10 messages per second.
The main thread pops messages out of the FIFO queue. The service rate is determined by the
sleep_for
time on line 93.
Experiment
Study the source code . Compile and run it. What results do you observe?
Why don’t we need to use the mutexed
SharedPrinter
object here?Vary the
sleep_for
time on line 93 to see its effects on the queue size.