Home | History | Annotate | Download | only in detail
      1 //
      2 // detail/op_queue.hpp
      3 // ~~~~~~~~~~~~~~~~~~~
      4 //
      5 // Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com)
      6 //
      7 // Distributed under the Boost Software License, Version 1.0. (See accompanying
      8 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
      9 //
     10 
     11 #ifndef ASIO_DETAIL_OP_QUEUE_HPP
     12 #define ASIO_DETAIL_OP_QUEUE_HPP
     13 
     14 
     15 #include "asio/detail/noncopyable.hpp"
     16 
     17 #include "asio/detail/push_options.hpp"
     18 
     19 namespace asio {
     20 namespace detail {
     21 
     22 template <typename Operation>
     23 class op_queue;
     24 
     25 class op_queue_access
     26 {
     27 public:
     28   template <typename Operation>
     29   static Operation* next(Operation* o)
     30   {
     31     return static_cast<Operation*>(o->next_);
     32   }
     33 
     34   template <typename Operation1, typename Operation2>
     35   static void next(Operation1*& o1, Operation2* o2)
     36   {
     37     o1->next_ = o2;
     38   }
     39 
     40   template <typename Operation>
     41   static void destroy(Operation* o)
     42   {
     43     o->destroy();
     44   }
     45 
     46   template <typename Operation>
     47   static Operation*& front(op_queue<Operation>& q)
     48   {
     49     return q.front_;
     50   }
     51 
     52   template <typename Operation>
     53   static Operation*& back(op_queue<Operation>& q)
     54   {
     55     return q.back_;
     56   }
     57 };
     58 
     59 template <typename Operation>
     60 class op_queue
     61   : private noncopyable
     62 {
     63 public:
     64   // Constructor.
     65   op_queue()
     66     : front_(0),
     67       back_(0)
     68   {
     69   }
     70 
     71   // Destructor destroys all operations.
     72   ~op_queue()
     73   {
     74     while (Operation* op = front_)
     75     {
     76       pop();
     77       op_queue_access::destroy(op);
     78     }
     79   }
     80 
     81   // Get the operation at the front of the queue.
     82   Operation* front()
     83   {
     84     return front_;
     85   }
     86 
     87   // Pop an operation from the front of the queue.
     88   void pop()
     89   {
     90     if (front_)
     91     {
     92       Operation* tmp = front_;
     93       front_ = op_queue_access::next(front_);
     94       if (front_ == 0)
     95         back_ = 0;
     96       op_queue_access::next(tmp, static_cast<Operation*>(0));
     97     }
     98   }
     99 
    100   // Push an operation on to the back of the queue.
    101   void push(Operation* h)
    102   {
    103     op_queue_access::next(h, static_cast<Operation*>(0));
    104     if (back_)
    105     {
    106       op_queue_access::next(back_, h);
    107       back_ = h;
    108     }
    109     else
    110     {
    111       front_ = back_ = h;
    112     }
    113   }
    114 
    115   // Push all operations from another queue on to the back of the queue. The
    116   // source queue may contain operations of a derived type.
    117   template <typename OtherOperation>
    118   void push(op_queue<OtherOperation>& q)
    119   {
    120     if (Operation* other_front = op_queue_access::front(q))
    121     {
    122       if (back_)
    123         op_queue_access::next(back_, other_front);
    124       else
    125         front_ = other_front;
    126       back_ = op_queue_access::back(q);
    127       op_queue_access::front(q) = 0;
    128       op_queue_access::back(q) = 0;
    129     }
    130   }
    131 
    132   // Whether the queue is empty.
    133   bool empty() const
    134   {
    135     return front_ == 0;
    136   }
    137 
    138 private:
    139   friend class op_queue_access;
    140 
    141   // The front of the queue.
    142   Operation* front_;
    143 
    144   // The back of the queue.
    145   Operation* back_;
    146 };
    147 
    148 } // namespace detail
    149 } // namespace asio
    150 
    151 #include "asio/detail/pop_options.hpp"
    152 
    153 #endif // ASIO_DETAIL_OP_QUEUE_HPP
    154