Advertisement
Guest User

timeout manager

a guest
Jul 19th, 2011
161
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
D 6.00 KB | None | 0 0
  1. // Implementation of timer wheel algorithm
  2. // More info: http://www.ibm.com/developerworks/aix/library/au-lowertime/index.html
  3. //
  4. // License: public domain
  5. //
  6. // "Params" is an argument list for timeout callback function
  7. module timeouts;
  8.  
  9. import std.datetime;
  10. import core.thread, core.sync.mutex, core.sync.condition;
  11.  
  12. class TimeoutWorker(Params...)
  13. {
  14.     private alias void function(Params) TimeoutCallback;
  15.    
  16.     private struct Timeout
  17.     {
  18.         size_t rounds;
  19.         int slot;
  20.         TimeoutCallback callback;
  21.         static if (Params.length)
  22.             Params params;
  23.        
  24.         Timeout* prev;
  25.         Timeout* next;
  26.         bool waiting;
  27.     }
  28.  
  29.     this()
  30.     {
  31.         thread = new Thread(&worker);
  32.         c = new Condition(new Mutex(this));
  33.     }
  34.    
  35.     void start()
  36.     {
  37.         thread.start();
  38.         //c.wait();
  39.     }
  40.  
  41.     void stop()
  42.     {
  43.         run = false;
  44.         thread.join();
  45.     }
  46.    
  47.     void* addTimeout(int interval, TimeoutCallback callback, Params params)
  48.     in
  49.     {
  50.         assert(interval >= 0);
  51.     }
  52.     body
  53.     {
  54.         Timeout* timeout = new Timeout;
  55.         timeout.callback = callback;
  56.         static if (Params.length)
  57.             timeout.params = params;
  58.        
  59.         restartTimeout(timeout, interval);
  60.        
  61.         return timeout;
  62.     }
  63.    
  64.     void cancelTimeout(void* handle)
  65.     {
  66.         restartTimeout(handle, -1);
  67.     }
  68.    
  69.     void restartTimeout(void* handle, int interval)
  70.     {
  71.         Timeout* timeout = cast(Timeout*)handle;
  72.        
  73.         synchronized (this)
  74.         {
  75.             if (timeout.waiting)
  76.             {
  77.                 Timeout* prev = timeout.prev;
  78.                 Timeout* next = timeout.next;
  79.                
  80.                 if (prev)
  81.                     prev.next = next;
  82.                 else
  83.                     timeouts[timeout.slot] = next;
  84.                
  85.                 if (next)
  86.                     next.prev = prev;
  87.                
  88.                 timeout.waiting = false;
  89.             }
  90.            
  91.             if (interval < 0)
  92.                 return;
  93.            
  94.             size_t newSlot = (currentSlot + (interval / 10)) % 100;
  95.             size_t rounds = (currentSlot + (interval / 10)) / 100;
  96.  
  97.             Timeout* list = timeouts[newSlot];
  98.            
  99.             timeout.rounds = rounds;
  100.             timeout.slot = newSlot;
  101.             timeout.next = list;
  102.             timeout.prev = null;
  103.            
  104.             if (list)
  105.                 list.prev = timeout;
  106.            
  107.             timeout.waiting = true;
  108.             timeouts[newSlot] = timeout;
  109.         }
  110.     }
  111.    
  112.     void setCallback(void* handle, TimeoutCallback callback)
  113.     {
  114.         Timeout* timeout = cast(Timeout*)handle;
  115.  
  116.         synchronized (this)
  117.         {
  118.             timeout.callback = callback;            
  119.         }
  120.     }
  121.    
  122.     static if (Params.length)
  123.     {
  124.         void setParams(void* handle, Params params)
  125.         {
  126.             Timeout* timeout = cast(Timeout*)handle;
  127.  
  128.             synchronized (this)
  129.             {
  130.                 timeout.params = params;
  131.             }
  132.         }
  133.        
  134.         void setCallbackAndParams(void* handle, TimeoutCallback callback, Params params)
  135.         {
  136.             Timeout* timeout = cast(Timeout*)handle;
  137.  
  138.             synchronized (this)
  139.             {
  140.                 timeout.callback = callback;
  141.                 timeout.params = params;
  142.             }
  143.         }
  144.     }
  145.    
  146. private:
  147.    
  148.     Thread thread;
  149.     Timeout*[100] timeouts;
  150.     size_t currentSlot;
  151.     bool run;
  152.     Condition c;
  153.    
  154.     void worker()
  155.     {
  156.         currentSlot = 0;
  157.         long lastTicks = Clock.currStdTime;
  158.         run = true;
  159.        
  160.         c.notify();
  161.        
  162.         while (run)
  163.         {
  164.             Timeout* callList = null;
  165.             long newTicks;
  166.            
  167.             synchronized (this)
  168.             {
  169.                 newTicks = Clock.currStdTime;
  170.                 long interval = newTicks - lastTicks;
  171.                
  172.                 long wheelTicks = interval / 100000;
  173.                
  174.                 foreach (i; 0 .. wheelTicks)
  175.                 {
  176.                     Timeout* list = timeouts[currentSlot];
  177.                    
  178.                     while (list)
  179.                     {
  180.                         if ((*list).rounds == 0)
  181.                         {
  182.                             Timeout* prev = (*list).prev;
  183.                             Timeout* next = (*list).next;
  184.                            
  185.                             if (prev)
  186.                                 (*prev).next = next;
  187.                             else
  188.                                 timeouts[currentSlot] = next;
  189.                            
  190.                             if (next)
  191.                                 (*next).prev = prev;
  192.  
  193.                             if (callList)
  194.                                 (*list).prev = callList;
  195.                             else
  196.                                 (*list).prev = null;
  197.                            
  198.                             callList = list;
  199.                         }
  200.                         else
  201.                             (*list).rounds--;
  202.                        
  203.                         list = (*list).next;
  204.                     }
  205.                    
  206.                     currentSlot = (currentSlot + 1) % 100;
  207.                 }
  208.                
  209.                 lastTicks += wheelTicks * 100000;
  210.             }
  211.            
  212.             while (callList)
  213.             {
  214.                 callList.waiting = false;
  215.                
  216.                 static if (Params.length)
  217.                     (*callList).callback((*callList).params);
  218.                 else
  219.                     (*callList).callback();
  220.                    
  221.                 callList = (*callList).prev;
  222.             }
  223.            
  224.             long sleep = 100000 - (Clock.currStdTime - newTicks);
  225.             if (sleep > 0)
  226.                 Thread.sleep(sleep);
  227.         }
  228.     }
  229. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement