Merge pull request #1844 from jrw972/monterey
[ACE_TAO.git] / TAO / docs / tutorials / Quoter / RTCORBA / Stock_Database.tpp
blob00cd8c379746b492a6b9cbd61c0a855111fdc403
1 #ifndef STOCK_DATABASE_TPP
2 #define STOCK_DATABASE_TPP
3 // local headers
4 #include "Stock_Database.h"
6 // ACE headers
7 #include <ace/OS_NS_unistd.h>
8 #include <ace/UUID.h>
10 #include <fstream>
11 #include <vector>
12 template <typename CALLBACK>
13 struct Map_Init
15   Map_Init (typename Stock_Database<CALLBACK>::Stock_Map &map)
16     : map_ (map)
17   {
18   }
20   void operator () (const typename Stock_Database<CALLBACK>::Init_Map::value_type &item)
21   {
22     typename Stock_Database<CALLBACK>::StockInfo stock_info (item.first.c_str ());
24     // If the initial value is nonzero, use that - otherwise, use a number
25     // between 0 and 100
26     stock_info.low_ =
27       stock_info.last_ =
28       stock_info.high_ = item.second ? item.second : ACE_OS::rand () % 100;
30     map_[item.first] = stock_info;
31   }
33   typename Stock_Database<CALLBACK>::Stock_Map &map_;
36 // Stock_Database
37 template <typename CALLBACK>
38 Stock_Database<CALLBACK>::Stock_Database (u_int rate)
39   : rate_ (rate),
40     active_ (false)
42   Init_Map map;
43   map["IBM"] = 0;
44   map["MSFT"] = 0;
45   map["INTEL"] = 0;
47   std::for_each (map.begin (),
48                  map.end (),
49                  Map_Init<CALLBACK> (this->stock_map_));
52 template <typename CALLBACK>
53 Stock_Database<CALLBACK>::Stock_Database (const char *file, u_int rate)
54   : filename_ (file),
55     rate_ (rate),
56     active_ (false)
58   this->handle_signal (0, 0, 0);
61 template <typename CALLBACK>
62 Stock_Database<CALLBACK>::Stock_Database (const Init_Map &stockmap,
63                                           u_int rate)
64   : rate_ (rate),
65     active_ (false)
67   std::for_each (stockmap.begin (),
68                  stockmap.end (),
69                  Map_Init<CALLBACK> (this->stock_map_));
72 // get_stock_info
73 template <typename CALLBACK>
74 typename Stock_Database<CALLBACK>::StockInfo
75 Stock_Database<CALLBACK>::get_stock_info(const char *name)
77   ACE_READ_GUARD_RETURN (ACE_RW_Thread_Mutex,
78                          guard,
79                          this->lock_,
80                          StockInfo ("Error"));
82   // Locate the <stock_name> in the database.
83   ACE_DEBUG ((LM_DEBUG,
84               "*** message: searching the stock_map_ for the stock_name\n"));
86   typename Stock_Map::iterator iter = this->stock_map_.find (std::string (name));
88   if (iter == this->stock_map_.end ())
89     throw Invalid_Stock ();
91   ACE_DEBUG ((LM_DEBUG, "*** message: returning stock_info to the client\n"));
93   return iter->second;
96 template <typename CALLBACK>
97 typename Stock_Database<CALLBACK>::Cookie
98 Stock_Database<CALLBACK>::register_callback (CALLBACK &obj)
100   ACE_Utils::UUID uuid;
101   ACE_Utils::UUID_GENERATOR::instance ()->generate_UUID (uuid);
103   this->callbacks_[uuid.to_string ()->c_str ()] = &obj;
105   return uuid.to_string ()->c_str ();
108 template <typename CALLBACK>
109 void
110 Stock_Database<CALLBACK>::update_rate (u_int rate)
112   this->rate_ = rate;
115 template <typename CALLBACK>
116 void
117 Stock_Database<CALLBACK>::start (void)
119   if (!this->active_)
120     { // Double checked locking
121       ACE_WRITE_GUARD (ACE_RW_Thread_Mutex,
122                        guard,
123                        this->lock_);
124       if (!this->active_)
125         {
126           this->active_ = true;
127           this->activate (THR_NEW_LWP | THR_JOINABLE, 1);
128         }
129     }
132 template <typename CALLBACK>
133 void
134 Stock_Database<CALLBACK>::stop (void)
136   ACE_WRITE_GUARD (ACE_RW_Thread_Mutex,
137                           guard,
138                           this->lock_);
140   this->active_ = false;
143 template <typename CALLBACK>
145 Stock_Database<CALLBACK>::handle_signal (int,
146                                          siginfo_t *,
147                                          ucontext_t *)
149   ACE_WRITE_GUARD_RETURN (ACE_RW_Thread_Mutex,
150                           guard,
151                           this->lock_,
152                           -1);
154   std::ifstream input (this->filename_.c_str ());
156   std::string name;
157   u_int value = 0;
159   typename Stock_Database<CALLBACK>::Init_Map map;
161   while (input.good ())
162     {
163       input >> name;
164       input >> value;
165       map[name] = value;
166     }
168   input.close ();
170   std::for_each (map.begin (),
171                  map.end (),
172                  Map_Init<CALLBACK> (this->stock_map_));
174   return 0;
178 template <typename CALLBACK>
179 struct Stock_Updater
181   void operator () (typename Stock_Database<CALLBACK>::Stock_Map::value_type &item)
182   {
183     // Determine if the stock has changed.
184     if (ACE_OS::rand () % 2)
185       return; // Nope! On to the next!
187     changed_.push_back (item.first);
189     // Determine the amount of change of the stock. We will
190     // only permit a 5 point change at a time in either direction
191     int delta = ACE_OS::rand () % 10 - 5;
193     // We don't want negative stock values!
194     if (item.second.last_ <= delta)
195       delta *= -1;
197     // Calculate the new values for the stock.
198     item.second.last_ += delta;
200     if (item.second.last_ < item.second.low_)
201       item.second.low_ = item.second.last_;
202     else if (item.second.last_ > item.second.high_)
203       item.second.high_ = item.second.last_;
204   }
206   void operator () (typename Stock_Database<CALLBACK>::Callback_Map::value_type &item)
207   {
208     (*item.second)  (changed_);
209   }
211 private:
212   std::vector <std::string> changed_;
215 template <typename CALLBACK>
217 Stock_Database<CALLBACK>::svc (void)
219   ACE_DEBUG ((LM_DEBUG, "tock!\n"));
221   while (this->active_)
222     {
223       {
224         // Init our functor
225         Stock_Updater<CALLBACK> updater;
227         { // Control the scope of our mutex to avoid deadlock.
228           ACE_WRITE_GUARD_RETURN (ACE_RW_Thread_Mutex,
229                                   guard,
230                                   this->lock_,
231                                   -1);
233           updater = std::for_each (this->stock_map_.begin (),
234                                    this->stock_map_.end (),
235                                    updater);
236         }
238         // Update stock prices
239         // notify callbacks
240         std::for_each (this->callbacks_.begin (),
241                        this->callbacks_.end (),
242                        updater);
243       }
245       // Sleep for one second.
246       ACE_OS::sleep (this->rate_);
247     }
249   return 0;
252 #endif /* STOCK_DATABASE_TPP */