|
xorp
|
00001 // -*- c-basic-offset: 4; tab-width: 8; indent-tabs-mode: t -*- 00002 // vim:set sts=4 ts=8: 00003 00004 // Copyright (c) 2001-2009 XORP, Inc. 00005 // 00006 // This program is free software; you can redistribute it and/or modify 00007 // it under the terms of the GNU General Public License, Version 2, June 00008 // 1991 as published by the Free Software Foundation. Redistribution 00009 // and/or modification of this program under the terms of any other 00010 // version of the GNU General Public License is not permitted. 00011 // 00012 // This program is distributed in the hope that it will be useful, but 00013 // WITHOUT ANY WARRANTY; without even the implied warranty of 00014 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For more details, 00015 // see the GNU General Public License, Version 2, a copy of which can be 00016 // found in the XORP LICENSE.gpl file. 00017 // 00018 // XORP Inc, 2953 Bunker Hill Lane, Suite 204, Santa Clara, CA 95054, USA; 00019 // http://xorp.net 00020 00021 // $XORP: xorp/ospf/delay_queue.hh,v 1.10 2008/10/02 21:57:47 bms Exp $ 00022 00023 #ifndef __OSPF_DELAY_QUEUE_HH__ 00024 #define __OSPF_DELAY_QUEUE_HH__ 00025 00030 template <typename _Entry> 00031 class DelayQueue { 00032 public: 00033 typedef typename XorpCallback1<void, _Entry>::RefPtr DelayCallback; 00034 00035 DelayQueue(EventLoop& eventloop, uint32_t delay, DelayCallback forward) 00036 : _eventloop(eventloop), _delay(delay), _forward(forward) 00037 {} 00038 00043 void add(_Entry entry); 00044 00048 void fire(); 00049 00050 private: 00051 EventLoop& _eventloop; 00052 deque<_Entry> _queue; 00053 const uint32_t _delay; // Delay in seconds. 00054 DelayCallback _forward; // Invoked to forward an entry from the queue. 00055 XorpTimer _timer; // Timer that services the queue. 00056 00060 void next(); 00061 }; 00062 00063 template <typename _Entry> 00064 void 00065 DelayQueue<_Entry>::add(_Entry entry) 00066 { 00067 // If this entry is already on the queue just return. 00068 if (_queue.end() != find(_queue.begin(), _queue.end(), entry)) 00069 return; 00070 00071 // If the timer is running push this entry to the back of the 00072 // queue and return. 00073 if (_timer.scheduled()) { 00074 _queue.push_back(entry); 00075 return; 00076 } 00077 00078 // If the timer isn't running then we have been idle for more than 00079 // delay seconds. Forward this entry immediately and start the 00080 // timer. Start the timer first in case this code is re-entered. 00081 00082 _timer = _eventloop.new_oneoff_after(TimeVal(_delay, 0), 00083 callback(this, &DelayQueue::next)); 00084 00085 _forward->dispatch(entry); 00086 } 00087 00088 template <typename _Entry> 00089 void 00090 DelayQueue<_Entry>::fire() 00091 { 00092 if (_timer.scheduled()) 00093 return; 00094 00095 _timer = _eventloop.new_oneoff_after(TimeVal(_delay, 0), 00096 callback(this, &DelayQueue::next)); 00097 } 00098 00099 template <typename _Entry> 00100 void 00101 DelayQueue<_Entry>::next() 00102 { 00103 if (_queue.empty()) 00104 return; 00105 00106 _timer = _eventloop.new_oneoff_after(TimeVal(_delay, 0), 00107 callback(this, &DelayQueue::next)); 00108 00109 _Entry entry = _queue.front(); 00110 _queue.pop_front(); 00111 00112 _forward->dispatch(entry); 00113 } 00114 00115 #endif // __OSPF_DELAY_QUEUE_HH__