runnig

Alarm System

Feb 22nd, 2013
185
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 4.12 KB | None | 0 0
  1. // Design an abstract alarm system
  2.  
  3. #include "stdafx.h"
  4. #include <queue>
  5. #include <thread>
  6. #include <mutex>
  7. #include <atomic>
  8. #include <chrono>
  9. #include <condition_variable>
  10. #include <functional>
  11. #include <iostream>
  12. #include <time.h>
  13. #include <random>
  14. #include <memory>
  15. #include <string>
  16. #include <future>
  17.  
  18. using std::chrono::system_clock;
  19.  
  20. typedef std::chrono::system_clock::time_point timestamp_t;
  21.  
  22. std::mutex print_mut;
  23.  
  24. std::string fmt_timestamp(const timestamp_t & ts)
  25. {
  26.     const time_t t = std::chrono::system_clock::to_time_t(ts);
  27.  
  28.     struct tm loctime;
  29.     localtime_s(&loctime, &t);
  30.  
  31.     char buf[128];
  32.     strftime(buf, 128, "%X", &loctime);
  33.    
  34.     return std::string(buf);
  35. }
  36.  
  37. struct Alarm
  38. {
  39.     timestamp_t timestamp;
  40.     int data;
  41.  
  42.     void execute(Alarm & a)
  43.     {
  44.         std::lock_guard<std::mutex> lk(print_mut);
  45.         std::cout << "\tAlarm " << data << ", @ " << fmt_timestamp(a.timestamp) <<
  46.             ", now: " << fmt_timestamp(std::chrono::system_clock::now()) << '\n';      
  47.     }
  48. };
  49.  
  50. bool operator < (const Alarm & a, const Alarm & b)
  51. {
  52.     // default priority_queue is MAX-HEAP
  53.  
  54.     // we want earlier Alarms to stay
  55.     // at the head of the heap, i.e. MIN-HEAP
  56.     return a.timestamp > b.timestamp;
  57. }
  58.  
  59. // thoughts
  60. class AlarmSystem
  61. {
  62.     bool running;
  63.     std::priority_queue<Alarm> Q;  
  64.     std::mutex mut;
  65.     std::condition_variable signal;        
  66.     std::thread loop;
  67.  
  68.  
  69. public:
  70.  
  71.     AlarmSystem() : running(true), loop(&AlarmSystem::run, this){}
  72.  
  73.     ~AlarmSystem()
  74.     {
  75.         running = false;
  76.         {
  77.             std::lock_guard<std::mutex> lk(mut);
  78.             signal.notify_one();
  79.         }
  80.         loop.join();
  81.     }
  82.  
  83.  
  84.     void add(Alarm & a)
  85.     {              
  86.         std::lock_guard<std::mutex> lk(mut);
  87.         Q.push(a);
  88.         signal.notify_one();
  89.     }
  90.  
  91.     size_t size() { return Q.size(); }
  92.  
  93.     void run()
  94.     {
  95.         while(running)
  96.         {
  97.             std::unique_lock<std::mutex> lk(mut);
  98.  
  99.             // wait either 1 second or while Queue empty or until running
  100.             if(Q.empty()) { signal.wait(lk); }                  
  101.  
  102.             // sometimes signal wakes up accidently
  103.             // need to check the queue again
  104.             if(Q.empty()) { continue; }
  105.  
  106.             const timestamp_t at = Q.top().timestamp;
  107.             const timestamp_t curtime = std::chrono::system_clock::now();
  108.             if(curtime < at)
  109.             {              
  110.                 const std::chrono::system_clock::duration dur = at - curtime;                              
  111.  
  112.                 // wait with time out
  113.                 signal.wait_for(lk, dur);    
  114.                 continue;
  115.             }
  116.  
  117.             Alarm a = Q.top(); // copy the earliest alarm from the top of the queue
  118.             Q.pop();           // remove it from the queue
  119.  
  120.             // asynchronously launch alarm handler
  121.             std::async(std::launch::async, [a](Alarm a) { a.execute(a); }, a);
  122.         }
  123.     }      
  124. };
  125.  
  126. struct Timer
  127. {
  128.     bool running;
  129.     std::thread timer_thread;
  130.     Timer() : running(true), timer_thread(&Timer::run_timer, this) {}
  131.  
  132.  
  133.     void run_timer()
  134.     {
  135.         while(running)
  136.         {
  137.             std::this_thread::sleep_for(std::chrono::duration<int>(1));
  138.             std::string now(fmt_timestamp(std::chrono::system_clock::now()));
  139.  
  140.             std::lock_guard<std::mutex> lk(print_mut);
  141.             std::cout << "Timer:" << now << '\n';
  142.         }
  143.     }
  144.  
  145.     ~Timer() { running = false; timer_thread.join(); }
  146. };
  147.  
  148. int _tmain(int argc, _TCHAR* argv[])
  149. {
  150.     unsigned seed = 1;
  151.  
  152.     std::random_device rd;
  153.     std::mt19937 RANDOM(rd());
  154.  
  155.     const int MAX_FUTURE = 10;
  156.     const int MAX_ALARMS = 1000;
  157.  
  158.     std::uniform_int_distribution<> uniform(1, MAX_FUTURE);
  159.    
  160.     typedef std::chrono::duration<int> seconds_t;
  161.  
  162.     AlarmSystem alarm_system;
  163.     Timer timer;
  164.  
  165.    
  166.     timestamp_t now = std::chrono::system_clock::now();
  167.     timestamp_t last_alarm = now;
  168.  
  169.     int id = 0;
  170.  
  171.     for(int j = 0; j < MAX_ALARMS; ++j, ++id)
  172.     {
  173.         int d = uniform(RANDOM);
  174.         Alarm a;
  175.  
  176.         a.data = id;
  177.  
  178.         now = std::chrono::system_clock::now();
  179.         a.timestamp = now + seconds_t(d);
  180.  
  181.         last_alarm = std::max(a.timestamp, last_alarm);        
  182.  
  183.         {
  184.             std::lock_guard<std::mutex> lk(print_mut);         
  185.             std::cout << "size: "<< alarm_system.size() << '\t' << a.data << " scheduled at: " << fmt_timestamp(a.timestamp) << '\n';          
  186.         }
  187.         alarm_system.add(a);
  188.         std::this_thread::sleep_for(std::chrono::milliseconds(uniform(RANDOM)));       
  189.     }
  190.  
  191.     std::this_thread::sleep_until(last_alarm);
  192.        
  193.     return 0;
  194.  
  195. }
Advertisement
Add Comment
Please, Sign In to add comment