xorp

delay_queue.hh

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__
 All Classes Namespaces Functions Variables Typedefs Enumerations