Update of /cvsroot/boost/boost/boost/asio/detail
In directory sc8-pr-cvs3.sourceforge.net:/tmp/cvs-serv6057/boost/asio/detail

Modified Files:
        epoll_reactor.hpp kqueue_reactor.hpp 
        reactive_socket_service.hpp select_reactor.hpp 
Added Files:
        deadline_timer_service.hpp timer_queue.hpp 
        timer_queue_base.hpp 
Removed Files:
        reactive_deadline_timer_service.hpp reactor_timer_queue.hpp 
Log Message:
Maintain separate timer queues for each time traits type.


--- NEW FILE: deadline_timer_service.hpp ---
//
// deadline_timer_service.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2006 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//

#ifndef BOOST_ASIO_DETAIL_DEADLINE_TIMER_SERVICE_HPP
#define BOOST_ASIO_DETAIL_DEADLINE_TIMER_SERVICE_HPP

#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)

#include <boost/asio/detail/push_options.hpp>

#include <boost/asio/detail/push_options.hpp>
#include <cstddef>
#include <boost/config.hpp>
#include <boost/date_time/posix_time/posix_time_types.hpp>
#include <boost/asio/detail/pop_options.hpp>

#include <boost/asio/error.hpp>
#include <boost/asio/io_service.hpp>
#include <boost/asio/detail/bind_handler.hpp>
#include <boost/asio/detail/noncopyable.hpp>
#include <boost/asio/detail/socket_ops.hpp>
#include <boost/asio/detail/socket_types.hpp>
#include <boost/asio/detail/timer_queue.hpp>

namespace boost {
namespace asio {
namespace detail {

template <typename Time_Traits, typename Timer_Scheduler>
class deadline_timer_service
  : public boost::asio::io_service::service
{
public:
  // The time type.
  typedef typename Time_Traits::time_type time_type;

  // The duration type.
  typedef typename Time_Traits::duration_type duration_type;

  // The implementation type of the timer. This type is dependent on the
  // underlying implementation of the timer service.
  struct implementation_type
    : private boost::asio::detail::noncopyable
  {
    time_type expiry;
    bool might_have_pending_waits;
  };

  // Constructor.
  deadline_timer_service(boost::asio::io_service& io_service)
    : boost::asio::io_service::service(io_service),
      scheduler_(boost::asio::use_service<Timer_Scheduler>(io_service))
  {
    scheduler_.add_timer_queue(timer_queue_);
  }

  // Destroy all user-defined handler objects owned by the service.
  void shutdown_service()
  {
  }

  // Construct a new timer implementation.
  void construct(implementation_type& impl)
  {
    impl.expiry = time_type();
    impl.might_have_pending_waits = false;
  }

  // Destroy a timer implementation.
  void destroy(implementation_type& impl)
  {
    cancel(impl);
  }

  // Cancel any asynchronous wait operations associated with the timer.
  std::size_t cancel(implementation_type& impl)
  {
    if (!impl.might_have_pending_waits)
      return 0;
    std::size_t count = scheduler_.cancel_timer(timer_queue_, &impl);
    impl.might_have_pending_waits = false;
    return count;
  }

  // Get the expiry time for the timer as an absolute time.
  time_type expires_at(const implementation_type& impl) const
  {
    return impl.expiry;
  }

  // Set the expiry time for the timer as an absolute time.
  std::size_t expires_at(implementation_type& impl,
      const time_type& expiry_time)
  {
    std::size_t count = cancel(impl);
    impl.expiry = expiry_time;
    return count;
  }

  // Get the expiry time for the timer relative to now.
  duration_type expires_from_now(const implementation_type& impl) const
  {
    return Time_Traits::subtract(expires_at(impl), Time_Traits::now());
  }

  // Set the expiry time for the timer relative to now.
  std::size_t expires_from_now(implementation_type& impl,
      const duration_type& expiry_time)
  {
    return expires_at(impl, Time_Traits::add(Time_Traits::now(), expiry_time));
  }

  // Perform a blocking wait on the timer.
  void wait(implementation_type& impl)
  {
    time_type now = Time_Traits::now();
    while (Time_Traits::less_than(now, impl.expiry))
    {
      boost::posix_time::time_duration timeout =
        Time_Traits::to_posix_duration(Time_Traits::subtract(impl.expiry, now));
      ::timeval tv;
      tv.tv_sec = timeout.total_seconds();
      tv.tv_usec = timeout.total_microseconds() % 1000000;
      socket_ops::select(0, 0, 0, 0, &tv);
      now = Time_Traits::now();
    }
  }

  template <typename Handler>
  class wait_handler
  {
  public:
    wait_handler(boost::asio::io_service& io_service, Handler handler)
      : io_service_(io_service),
        work_(io_service),
        handler_(handler)
    {
    }

    void operator()(int result)
    {
      boost::asio::error e(result);
      io_service_.post(detail::bind_handler(handler_, e));
    }

  private:
    boost::asio::io_service& io_service_;
    boost::asio::io_service::work work_;
    Handler handler_;
  };

  // Start an asynchronous wait on the timer.
  template <typename Handler>
  void async_wait(implementation_type& impl, Handler handler)
  {
    impl.might_have_pending_waits = true;
    scheduler_.schedule_timer(timer_queue_, impl.expiry,
        wait_handler<Handler>(owner(), handler), &impl);
  }

private:
  // The queue of timers.
  timer_queue<Time_Traits> timer_queue_;

  // The object that schedules and executes timers. Usually a reactor.
  Timer_Scheduler& scheduler_;
};

} // namespace detail
} // namespace asio
} // namespace boost

#include <boost/asio/detail/pop_options.hpp>

#endif // BOOST_ASIO_DETAIL_DEADLINE_TIMER_SERVICE_HPP

--- NEW FILE: timer_queue.hpp ---
//
// timer_queue.hpp
// ~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2006 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//

#ifndef BOOST_ASIO_DETAIL_TIMER_QUEUE_HPP
#define BOOST_ASIO_DETAIL_TIMER_QUEUE_HPP

#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)

#include <boost/asio/detail/push_options.hpp>

#include <boost/asio/detail/push_options.hpp>
#include <cstddef>
#include <functional>
#include <limits>
#include <memory>
#include <vector>
#include <boost/config.hpp>
#include <boost/asio/detail/pop_options.hpp>

#include <boost/asio/error.hpp>
#include <boost/asio/detail/hash_map.hpp>
#include <boost/asio/detail/noncopyable.hpp>
#include <boost/asio/detail/timer_queue_base.hpp>

namespace boost {
namespace asio {
namespace detail {

template <typename Time_Traits>
class timer_queue
  : public timer_queue_base
{
public:
  // The time type.
  typedef typename Time_Traits::time_type time_type;

  // The duration type.
  typedef typename Time_Traits::duration_type duration_type;

  // Constructor.
  timer_queue()
    : timers_(),
      heap_()
  {
  }

  // Add a new timer to the queue. Returns true if this is the timer that is
  // earliest in the queue, in which case the reactor's event demultiplexing
  // function call may need to be interrupted and restarted.
  template <typename Handler>
  bool enqueue_timer(const time_type& time, Handler handler, void* token)
  {
    // Ensure that there is space for the timer in the heap. We reserve here so
    // that the push_back below will not throw due to a reallocation failure.
    heap_.reserve(heap_.size() + 1);

    // Create a new timer object.
    std::auto_ptr<timer<Handler> > new_timer(
        new timer<Handler>(time, handler, token));

    // Insert the new timer into the hash.
    typedef typename hash_map<void*, timer_base*>::iterator iterator;
    typedef typename hash_map<void*, timer_base*>::value_type value_type;
    std::pair<iterator, bool> result =
      timers_.insert(value_type(token, new_timer.get()));
    if (!result.second)
    {
      result.first->second->prev_ = new_timer.get();
      new_timer->next_ = result.first->second;
      result.first->second = new_timer.get();
    }

    // Put the timer at the correct position in the heap.
    new_timer->heap_index_ = heap_.size();
    heap_.push_back(new_timer.get());
    up_heap(heap_.size() - 1);
    bool is_first = (heap_[0] == new_timer.get());

    // Ownership of the timer is transferred to the timer queue.
    new_timer.release();

    return is_first;
  }

  // Whether there are no timers in the queue.
  virtual bool empty() const
  {
    return heap_.empty();
  }

  // Get the time for the timer that is earliest in the queue.
  virtual boost::posix_time::time_duration wait_duration() const
  {
    return Time_Traits::to_posix_duration(
        Time_Traits::subtract(heap_[0]->time_, Time_Traits::now()));
  }

  // Dispatch the timers that are earlier than the specified time.
  virtual void dispatch_timers()
  {
    const time_type now = Time_Traits::now();
    while (!heap_.empty() && !Time_Traits::less_than(now, heap_[0]->time_))
    {
      timer_base* t = heap_[0];
      remove_timer(t);
      t->invoke(0);
    }
  }

  // Cancel the timer with the given token. The handler will be invoked
  // immediately with the result operation_aborted.
  std::size_t cancel_timer(void* timer_token)
  {
    std::size_t num_cancelled = 0;
    typedef typename hash_map<void*, timer_base*>::iterator iterator;
    iterator it = timers_.find(timer_token);
    if (it != timers_.end())
    {
      timer_base* t = it->second;
      while (t)
      {
        timer_base* next = t->next_;
        remove_timer(t);
        t->invoke(boost::asio::error::operation_aborted);
        t = next;
        ++num_cancelled;
      }
    }
    return num_cancelled;
  }

  // Destroy all timers.
  virtual void destroy_timers()
  {
    typename hash_map<void*, timer_base*>::iterator i = timers_.begin();
    typename hash_map<void*, timer_base*>::iterator end = timers_.end();
    while (i != end)
    {
      timer_base* t = i->second;
      typename hash_map<void*, timer_base*>::iterator old_i = i++;
      timers_.erase(old_i);
      t->destroy();
    }
    heap_.clear();
    timers_.clear();
  }

private:
  // Base class for timer operations. Function pointers are used instead of
  // virtual functions to avoid the associated overhead.
  class timer_base
  {
  public:
    // Perform the timer operation and then destroy.
    void invoke(int result)
    {
      invoke_func_(this, result);
    }

    // Destroy the timer operation.
    void destroy()
    {
      destroy_func_(this);
    }

  protected:
    typedef void (*invoke_func_type)(timer_base*, int);
    typedef void (*destroy_func_type)(timer_base*);

    // Constructor.
    timer_base(invoke_func_type invoke_func, destroy_func_type destroy_func,
        const time_type& time, void* token)
      : invoke_func_(invoke_func),
        destroy_func_(destroy_func),
        time_(time),
        token_(token),
        next_(0),
        prev_(0),
        heap_index_(
            std::numeric_limits<size_t>::max BOOST_PREVENT_MACRO_SUBSTITUTION())
    {
    }

    // Prevent deletion through this type.
    ~timer_base()
    {
    }

  private:
    friend class timer_queue<Time_Traits>;

    // The function to be called to dispatch the handler.
    invoke_func_type invoke_func_;

    // The function to be called to destroy the handler.
    destroy_func_type destroy_func_;

    // The time when the operation should fire.
    time_type time_;

    // The token associated with the timer.
    void* token_;

    // The next timer known to the queue.
    timer_base* next_;

    // The previous timer known to the queue.
    timer_base* prev_;

    // The index of the timer in the heap.
    size_t heap_index_;
  };

  // Adaptor class template for using handlers in timers.
  template <typename Handler>
  class timer
    : public timer_base
  {
  public:
    // Constructor.
    timer(const time_type& time, Handler handler, void* token)
      : timer_base(&timer<Handler>::invoke_handler,
          &timer<Handler>::destroy_handler, time, token),
        handler_(handler)
    {
    }

    // Invoke the handler and then destroy it.
    static void invoke_handler(timer_base* base, int result)
    {
      std::auto_ptr<timer<Handler> > t(static_cast<timer<Handler>*>(base));
      t->handler_(result);
    }

    // Destroy the handler.
    static void destroy_handler(timer_base* base)
    {
      delete static_cast<timer<Handler>*>(base);
    }

  private:
    Handler handler_;
  };

  // Move the item at the given index up the heap to its correct position.
  void up_heap(size_t index)
  {
    size_t parent = (index - 1) / 2;
    while (index > 0
        && Time_Traits::less_than(heap_[index]->time_, heap_[parent]->time_))
    {
      swap_heap(index, parent);
      index = parent;
      parent = (index - 1) / 2;
    }
  }

  // Move the item at the given index down the heap to its correct position.
  void down_heap(size_t index)
  {
    size_t child = index * 2 + 1;
    while (child < heap_.size())
    {
      size_t min_child = (child + 1 == heap_.size()
          || Time_Traits::less_than(
            heap_[child]->time_, heap_[child + 1]->time_))
        ? child : child + 1;
      if (Time_Traits::less_than(heap_[index]->time_, heap_[min_child]->time_))
        break;
      swap_heap(index, min_child);
      index = min_child;
      child = index * 2 + 1;
    }
  }

  // Swap two entries in the heap.
  void swap_heap(size_t index1, size_t index2)
  {
    timer_base* tmp = heap_[index1];
    heap_[index1] = heap_[index2];
    heap_[index2] = tmp;
    heap_[index1]->heap_index_ = index1;
    heap_[index2]->heap_index_ = index2;
  }

  // Remove a timer from the heap and list of timers.
  void remove_timer(timer_base* t)
  {
    // Remove the timer from the heap.
    size_t index = t->heap_index_;
    if (!heap_.empty() && index < heap_.size())
    {
      if (index == heap_.size() - 1)
      {
        heap_.pop_back();
      }
      else
      {
        swap_heap(index, heap_.size() - 1);
        heap_.pop_back();
        size_t parent = (index - 1) / 2;
        if (index > 0 && Time_Traits::less_than(t->time_, heap_[parent]->time_))
          up_heap(index);
        else
          down_heap(index);
      }
    }

    // Remove the timer from the hash.
    typedef typename hash_map<void*, timer_base*>::iterator iterator;
    iterator it = timers_.find(t->token_);
    if (it != timers_.end())
    {
      if (it->second == t)
        it->second = t->next_;
      if (t->prev_)
        t->prev_->next_ = t->next_;
      if (t->next_)
        t->next_->prev_ = t->prev_;
      if (it->second == 0)
        timers_.erase(it);
    }
  }

  // A hash of timer token to linked lists of timers.
  hash_map<void*, timer_base*> timers_;

  // The heap of timers, with the earliest timer at the front.
  std::vector<timer_base*> heap_;
};

} // namespace detail
} // namespace asio
} // namespace boost

#include <boost/asio/detail/pop_options.hpp>

#endif // BOOST_ASIO_DETAIL_TIMER_QUEUE_HPP

--- NEW FILE: timer_queue_base.hpp ---
//
// timer_queue_base.hpp
// ~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2006 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//

#ifndef BOOST_ASIO_DETAIL_TIMER_QUEUE_BASE_HPP
#define BOOST_ASIO_DETAIL_TIMER_QUEUE_BASE_HPP

#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)

#include <boost/asio/detail/push_options.hpp>

#include <boost/asio/detail/socket_types.hpp> // Must come before posix_time.

#include <boost/asio/detail/push_options.hpp>
#include <boost/date_time/posix_time/posix_time_types.hpp>
#include <boost/asio/detail/pop_options.hpp>

#include <boost/asio/detail/noncopyable.hpp>

namespace boost {
namespace asio {
namespace detail {

class timer_queue_base
  : private noncopyable
{
public:
  // Destructor.
  virtual ~timer_queue_base() {}

  // Whether there are no timers in the queue.
  virtual bool empty() const = 0;

  // Get the time to wait until the next timer.
  virtual boost::posix_time::time_duration wait_duration() const = 0;

  // Dispatch all ready timers.
  virtual void dispatch_timers() = 0;

  // Destroy all timers.
  virtual void destroy_timers() = 0;
};

} // namespace detail
} // namespace asio
} // namespace boost

#include <boost/asio/detail/pop_options.hpp>

#endif // BOOST_ASIO_DETAIL_TIMER_QUEUE_BASE_HPP

Index: epoll_reactor.hpp
===================================================================
RCS file: /cvsroot/boost/boost/boost/asio/detail/epoll_reactor.hpp,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- epoll_reactor.hpp   14 Jun 2006 22:26:30 -0000      1.1
+++ epoll_reactor.hpp   26 Jul 2006 11:23:25 -0000      1.2
@@ -38,10 +38,10 @@
 #include <boost/asio/detail/task_io_service.hpp>
 #include <boost/asio/detail/thread.hpp>
 #include <boost/asio/detail/reactor_op_queue.hpp>
-#include <boost/asio/detail/reactor_timer_queue.hpp>
 #include <boost/asio/detail/select_interrupter.hpp>
 #include <boost/asio/detail/signal_blocker.hpp>
 #include <boost/asio/detail/socket_types.hpp>
+#include <boost/asio/detail/timer_queue.hpp>
 
 namespace boost {
 namespace asio {
@@ -108,7 +108,10 @@
     read_op_queue_.destroy_operations();
     write_op_queue_.destroy_operations();
     except_op_queue_.destroy_operations();
-    timer_queue_.destroy_timers();
+
+    for (std::size_t i = 0; i < timer_queues_.size(); ++i)
+      timer_queues_[i]->destroy_timers();
+    timer_queues_.clear();
   }
 
   // Register a socket with the reactor. Returns 0 on success, system error
@@ -286,24 +289,33 @@
     cancel_ops_unlocked(descriptor);
   }
 
-  // Schedule a timer to expire at the specified absolute time. The handler
-  // object will be invoked when the timer expires.
-  template <typename Handler>
-  void schedule_timer(const boost::posix_time::ptime& time,
-      Handler handler, void* token)
+  // Add a new timer queue to the reactor.
+  template <typename Time_Traits>
+  void add_timer_queue(timer_queue<Time_Traits>& timer_queue)
+  {
+    boost::asio::detail::mutex::scoped_lock lock(mutex_);
+    timer_queues_.push_back(&timer_queue);
+  }
+
+  // Schedule a timer in the given timer queue to expire at the specified
+  // absolute time. The handler object will be invoked when the timer expires.
+  template <typename Time_Traits, typename Handler>
+  void schedule_timer(timer_queue<Time_Traits>& timer_queue,
+      const typename Time_Traits::time_type& time, Handler handler, void* 
token)
   {
     boost::asio::detail::mutex::scoped_lock lock(mutex_);
     if (!shutdown_)
-      if (timer_queue_.enqueue_timer(time, handler, token))
+      if (timer_queue.enqueue_timer(time, handler, token))
         interrupter_.interrupt();
   }
 
   // Cancel the timer associated with the given token. Returns the number of
   // handlers that have been posted or dispatched.
-  std::size_t cancel_timer(void* token)
+  template <typename Time_Traits>
+  std::size_t cancel_timer(timer_queue<Time_Traits>& timer_queue, void* token)
   {
     boost::asio::detail::mutex::scoped_lock lock(mutex_);
-    return timer_queue_.cancel_timer(token);
+    return timer_queue.cancel_timer(token);
   }
 
 private:
@@ -335,7 +347,7 @@
     // We can return immediately if there's no work to do and the reactor is
     // not supposed to block.
     if (!block && read_op_queue_.empty() && write_op_queue_.empty()
-        && except_op_queue_.empty() && timer_queue_.empty())
+        && except_op_queue_.empty() && all_timer_queues_are_empty())
     {
       // Clean up operations. We must not hold the lock since the operations 
may
       // make calls back into this reactor.
@@ -427,8 +439,8 @@
     read_op_queue_.dispatch_cancellations();
     write_op_queue_.dispatch_cancellations();
     except_op_queue_.dispatch_cancellations();
-    timer_queue_.dispatch_timers(
-        boost::posix_time::microsec_clock::universal_time());
+    for (std::size_t i = 0; i < timer_queues_.size(); ++i)
+      timer_queues_[i]->dispatch_timers();
 
     // Issue any pending cancellations.
     for (size_t i = 0; i < pending_cancellations_.size(); ++i)
@@ -483,26 +495,39 @@
     return fd;
   }
 
+  // Check if all timer queues are empty.
+  bool all_timer_queues_are_empty() const
+  {
+    for (std::size_t i = 0; i < timer_queues_.size(); ++i)
+      if (!timer_queues_[i]->empty())
+        return false;
+    return true;
+  }
+
   // Get the timeout value for the epoll_wait call. The timeout value is
   // returned as a number of milliseconds. A return value of -1 indicates
   // that epoll_wait should block indefinitely.
   int get_timeout()
   {
-    if (timer_queue_.empty())
+    if (all_timer_queues_are_empty())
       return -1;
 
-    boost::posix_time::ptime now
-      = boost::posix_time::microsec_clock::universal_time();
-    boost::posix_time::ptime earliest_timer;
-    timer_queue_.get_earliest_time(earliest_timer);
-    if (now < earliest_timer)
+    // By default we will wait no longer than 5 minutes. This will ensure that
+    // any changes to the system clock are detected after no longer than this.
+    boost::posix_time::time_duration minimum_wait_duration
+      = boost::posix_time::minutes(5);
+
+    for (std::size_t i = 0; i < timer_queues_.size(); ++i)
     {
-      boost::posix_time::time_duration timeout = earliest_timer - now;
-      const int max_timeout_in_seconds = INT_MAX / 1000;
-      if (max_timeout_in_seconds < timeout.total_seconds())
-        return max_timeout_in_seconds * 1000;
-      else
-        return timeout.total_milliseconds();
+      boost::posix_time::time_duration wait_duration
+        = timer_queues_[i]->wait_duration();
+      if (wait_duration < minimum_wait_duration)
+        minimum_wait_duration = wait_duration;
+    }
+
+    if (minimum_wait_duration > boost::posix_time::time_duration())
+    {
+      return minimum_wait_duration.total_milliseconds();
     }
     else
     {
@@ -543,8 +568,8 @@
   // The queue of except operations.
   reactor_op_queue<socket_type> except_op_queue_;
 
-  // The queue of timers.
-  reactor_timer_queue<boost::posix_time::ptime> timer_queue_;
+  // The timer queues.
+  std::vector<timer_queue_base*> timer_queues_;
 
   // The descriptors that are pending cancellation.
   std::vector<socket_type> pending_cancellations_;

Index: kqueue_reactor.hpp
===================================================================
RCS file: /cvsroot/boost/boost/boost/asio/detail/kqueue_reactor.hpp,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- kqueue_reactor.hpp  5 Jul 2006 05:26:35 -0000       1.2
+++ kqueue_reactor.hpp  26 Jul 2006 11:23:25 -0000      1.3
@@ -40,10 +40,10 @@
 #include <boost/asio/detail/task_io_service.hpp>
 #include <boost/asio/detail/thread.hpp>
 #include <boost/asio/detail/reactor_op_queue.hpp>
-#include <boost/asio/detail/reactor_timer_queue.hpp>
 #include <boost/asio/detail/select_interrupter.hpp>
 #include <boost/asio/detail/signal_blocker.hpp>
 #include <boost/asio/detail/socket_types.hpp>
+#include <boost/asio/detail/timer_queue.hpp>
 
 // Older versions of Mac OS X may not define EV_OOBAND.
 #if !defined(EV_OOBAND)
@@ -115,7 +115,10 @@
     read_op_queue_.destroy_operations();
     write_op_queue_.destroy_operations();
     except_op_queue_.destroy_operations();
-    timer_queue_.destroy_timers();
+
+    for (std::size_t i = 0; i < timer_queues_.size(); ++i)
+      timer_queues_[i]->destroy_timers();
+    timer_queues_.clear();
   }
 
   // Register a socket with the reactor. Returns 0 on success, system error
@@ -275,26 +278,33 @@
     cancel_ops_unlocked(descriptor);
   }
 
-  // Schedule a timer to expire at the specified absolute time. The
-  // do_operation function of the handler object will be invoked when the timer
-  // expires. Returns a token that may be used for cancelling the timer, but it
-  // is not valid after the timer expires.
-  template <typename Handler>
-  void schedule_timer(const boost::posix_time::ptime& time,
-      Handler handler, void* token)
+  // Add a new timer queue to the reactor.
+  template <typename Time_Traits>
+  void add_timer_queue(timer_queue<Time_Traits>& timer_queue)
+  {
+    boost::asio::detail::mutex::scoped_lock lock(mutex_);
+    timer_queues_.push_back(&timer_queue);
+  }
+
+  // Schedule a timer in the given timer queue to expire at the specified
+  // absolute time. The handler object will be invoked when the timer expires.
+  template <typename Time_Traits, typename Handler>
+  void schedule_timer(timer_queue<Time_Traits>& timer_queue,
+      const typename Time_Traits::time_type& time, Handler handler, void* 
token)
   {
     boost::asio::detail::mutex::scoped_lock lock(mutex_);
     if (!shutdown_)
-      if (timer_queue_.enqueue_timer(time, handler, token))
+      if (timer_queue.enqueue_timer(time, handler, token))
         interrupter_.interrupt();
   }
 
   // Cancel the timer associated with the given token. Returns the number of
   // handlers that have been posted or dispatched.
-  std::size_t cancel_timer(void* token)
+  template <typename Time_Traits>
+  std::size_t cancel_timer(timer_queue<Time_Traits>& timer_queue, void* token)
   {
     boost::asio::detail::mutex::scoped_lock lock(mutex_);
-    return timer_queue_.cancel_timer(token);
+    return timer_queue.cancel_timer(token);
   }
 
 private:
@@ -326,7 +336,7 @@
     // We can return immediately if there's no work to do and the reactor is
     // not supposed to block.
     if (!block && read_op_queue_.empty() && write_op_queue_.empty()
-        && except_op_queue_.empty() && timer_queue_.empty())
+        && except_op_queue_.empty() && all_timer_queues_are_empty())
     {
       // Clean up operations. We must not hold the lock since the operations 
may
       // make calls back into this reactor.
@@ -433,11 +443,11 @@
     read_op_queue_.dispatch_cancellations();
     write_op_queue_.dispatch_cancellations();
     except_op_queue_.dispatch_cancellations();
-    timer_queue_.dispatch_timers(
-        boost::posix_time::microsec_clock::universal_time());
+    for (std::size_t i = 0; i < timer_queues_.size(); ++i)
+      timer_queues_[i]->dispatch_timers();
 
     // Issue any pending cancellations.
-    for (size_t i = 0; i < pending_cancellations_.size(); ++i)
+    for (std::size_t i = 0; i < pending_cancellations_.size(); ++i)
       cancel_ops_unlocked(pending_cancellations_[i]);
     pending_cancellations_.clear();
 
@@ -486,21 +496,38 @@
     return fd;
   }
 
+  // Check if all timer queues are empty.
+  bool all_timer_queues_are_empty() const
+  {
+    for (std::size_t i = 0; i < timer_queues_.size(); ++i)
+      if (!timer_queues_[i]->empty())
+        return false;
+    return true;
+  }
+
   // Get the timeout value for the kevent call.
   timespec* get_timeout(timespec& ts)
   {
-    if (timer_queue_.empty())
+    if (all_timer_queues_are_empty())
       return 0;
 
-    boost::posix_time::ptime now
-      = boost::posix_time::microsec_clock::universal_time();
-    boost::posix_time::ptime earliest_timer;
-    timer_queue_.get_earliest_time(earliest_timer);
-    if (now < earliest_timer)
+    // By default we will wait no longer than 5 minutes. This will ensure that
+    // any changes to the system clock are detected after no longer than this.
+    boost::posix_time::time_duration minimum_wait_duration
+      = boost::posix_time::minutes(5);
+
+    for (std::size_t i = 0; i < timer_queues_.size(); ++i)
     {
-      boost::posix_time::time_duration timeout = earliest_timer - now;
-      ts.tv_sec = timeout.total_seconds();
-      ts.tv_nsec = timeout.total_nanoseconds() % 1000000000;
+      boost::posix_time::time_duration wait_duration
+        = timer_queues_[i]->wait_duration();
+      if (wait_duration < minimum_wait_duration)
+        minimum_wait_duration = wait_duration;
+    }
+
+    if (minimum_wait_duration > boost::posix_time::time_duration())
+    {
+      ts.tv_sec = minimum_wait_duration.total_seconds();
+      ts.tv_nsec = minimum_wait_duration.total_nanoseconds() % 1000000000;
     }
     else
     {
@@ -544,8 +571,8 @@
   // The queue of except operations.
   reactor_op_queue<socket_type> except_op_queue_;
 
-  // The queue of timers.
-  reactor_timer_queue<boost::posix_time::ptime> timer_queue_;
+  // The timer queues.
+  std::vector<timer_queue_base*> timer_queues_;
 
   // The descriptors that are pending cancellation.
   std::vector<socket_type> pending_cancellations_;

Index: reactive_socket_service.hpp
===================================================================
RCS file: /cvsroot/boost/boost/boost/asio/detail/reactive_socket_service.hpp,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- reactive_socket_service.hpp 9 Jul 2006 06:57:33 -0000       1.3
+++ reactive_socket_service.hpp 26 Jul 2006 11:23:25 -0000      1.4
@@ -1063,12 +1063,6 @@
       return;
     }
 
-    if (int err = socket_ops::get_error())
-    {
-      error_handler(boost::asio::error(err));
-      return;
-    }
-
     // Accept a socket.
     for (;;)
     {

Index: select_reactor.hpp
===================================================================
RCS file: /cvsroot/boost/boost/boost/asio/detail/select_reactor.hpp,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- select_reactor.hpp  14 Jun 2006 22:26:31 -0000      1.1
+++ select_reactor.hpp  26 Jul 2006 11:23:25 -0000      1.2
@@ -34,12 +34,12 @@
 #include <boost/asio/detail/task_io_service.hpp>
 #include <boost/asio/detail/thread.hpp>
 #include <boost/asio/detail/reactor_op_queue.hpp>
-#include <boost/asio/detail/reactor_timer_queue.hpp>
 #include <boost/asio/detail/select_interrupter.hpp>
 #include <boost/asio/detail/select_reactor_fwd.hpp>
 #include <boost/asio/detail/signal_blocker.hpp>
 #include <boost/asio/detail/socket_ops.hpp>
 #include <boost/asio/detail/socket_types.hpp>
+#include <boost/asio/detail/timer_queue.hpp>
 
 namespace boost {
 namespace asio {
@@ -97,7 +97,10 @@
     read_op_queue_.destroy_operations();
     write_op_queue_.destroy_operations();
     except_op_queue_.destroy_operations();
-    timer_queue_.destroy_timers();
+
+    for (std::size_t i = 0; i < timer_queues_.size(); ++i)
+      timer_queues_[i]->destroy_timers();
+    timer_queues_.clear();
   }
 
   // Register a socket with the reactor. Returns 0 on success, system error
@@ -184,24 +187,33 @@
     cancel_ops_unlocked(descriptor);
   }
 
-  // Schedule a timer to expire at the specified absolute time. The handler
-  // object will be invoked when the timer expires.
-  template <typename Handler>
-  void schedule_timer(const boost::posix_time::ptime& time,
-      Handler handler, void* token)
+  // Add a new timer queue to the reactor.
+  template <typename Time_Traits>
+  void add_timer_queue(timer_queue<Time_Traits>& timer_queue)
+  {
+    boost::asio::detail::mutex::scoped_lock lock(mutex_);
+    timer_queues_.push_back(&timer_queue);
+  }
+
+  // Schedule a timer in the given timer queue to expire at the specified
+  // absolute time. The handler object will be invoked when the timer expires.
+  template <typename Time_Traits, typename Handler>
+  void schedule_timer(timer_queue<Time_Traits>& timer_queue,
+      const typename Time_Traits::time_type& time, Handler handler, void* 
token)
   {
     boost::asio::detail::mutex::scoped_lock lock(mutex_);
     if (!shutdown_)
-      if (timer_queue_.enqueue_timer(time, handler, token))
+      if (timer_queue.enqueue_timer(time, handler, token))
         interrupter_.interrupt();
   }
 
   // Cancel the timer associated with the given token. Returns the number of
   // handlers that have been posted or dispatched.
-  std::size_t cancel_timer(void* token)
+  template <typename Time_Traits>
+  std::size_t cancel_timer(timer_queue<Time_Traits>& timer_queue, void* token)
   {
     boost::asio::detail::mutex::scoped_lock lock(mutex_);
-    return timer_queue_.cancel_timer(token);
+    return timer_queue.cancel_timer(token);
   }
 
 private:
@@ -233,7 +245,7 @@
     // We can return immediately if there's no work to do and the reactor is
     // not supposed to block.
     if (!block && read_op_queue_.empty() && write_op_queue_.empty()
-        && except_op_queue_.empty() && timer_queue_.empty())
+        && except_op_queue_.empty() && all_timer_queues_are_empty())
     {
       // Clean up operations. We must not hold the lock since the operations 
may
       // make calls back into this reactor.
@@ -288,8 +300,8 @@
       read_op_queue_.dispatch_cancellations();
       write_op_queue_.dispatch_cancellations();
     }
-    timer_queue_.dispatch_timers(
-        boost::posix_time::microsec_clock::universal_time());
+    for (std::size_t i = 0; i < timer_queues_.size(); ++i)
+      timer_queues_[i]->dispatch_timers();
 
     // Issue any pending cancellations.
     for (size_t i = 0; i < pending_cancellations_.size(); ++i)
@@ -328,21 +340,38 @@
     interrupter_.interrupt();
   }
 
+  // Check if all timer queues are empty.
+  bool all_timer_queues_are_empty() const
+  {
+    for (std::size_t i = 0; i < timer_queues_.size(); ++i)
+      if (!timer_queues_[i]->empty())
+        return false;
+    return true;
+  }
+
   // Get the timeout value for the select call.
   timeval* get_timeout(timeval& tv)
   {
-    if (timer_queue_.empty())
+    if (all_timer_queues_are_empty())
       return 0;
 
-    boost::posix_time::ptime now
-      = boost::posix_time::microsec_clock::universal_time();
-    boost::posix_time::ptime earliest_timer;
-    timer_queue_.get_earliest_time(earliest_timer);
-    if (now < earliest_timer)
+    // By default we will wait no longer than 5 minutes. This will ensure that
+    // any changes to the system clock are detected after no longer than this.
+    boost::posix_time::time_duration minimum_wait_duration
+      = boost::posix_time::minutes(5);
+
+    for (std::size_t i = 0; i < timer_queues_.size(); ++i)
     {
-      boost::posix_time::time_duration timeout = earliest_timer - now;
-      tv.tv_sec = timeout.total_seconds();
-      tv.tv_usec = timeout.total_microseconds() % 1000000;
+      boost::posix_time::time_duration wait_duration
+        = timer_queues_[i]->wait_duration();
+      if (wait_duration < minimum_wait_duration)
+        minimum_wait_duration = wait_duration;
+    }
+
+    if (minimum_wait_duration > boost::posix_time::time_duration())
+    {
+      tv.tv_sec = minimum_wait_duration.total_seconds();
+      tv.tv_usec = minimum_wait_duration.total_microseconds() % 1000000;
     }
     else
     {
@@ -383,8 +412,8 @@
   // The queue of exception operations.
   reactor_op_queue<socket_type> except_op_queue_;
 
-  // The queue of timers.
-  reactor_timer_queue<boost::posix_time::ptime> timer_queue_;
+  // The timer queues.
+  std::vector<timer_queue_base*> timer_queues_;
 
   // The descriptors that are pending cancellation.
   std::vector<socket_type> pending_cancellations_;

--- reactive_deadline_timer_service.hpp DELETED ---

--- reactor_timer_queue.hpp DELETED ---


-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys -- and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
_______________________________________________
Boost-cvs mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/boost-cvs

Reply via email to