Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Boost asio ConstBufferSequence - c++ Templates

I am hoping for some guidance regarding C++ templates. I have been using the boost::asio library for communication over TCP. Thus far, I have been using storage containers built into the boost::asio library. For instance:

boost::array<char, 128> buf;
boost::system::error_code error;
size_t len = socket.read_some(boost::asio::buffer(buf), error);

To read from a socket, I simply wrap a buffer of type boost::asio::buffer around my boost::array object. This works fine, but now I'd like to work in the reverse direction. That is, I'd like to write back into the socket, pulling data from some custom storage classes I already have. My question is, how do I make sense of the template type requirements required to be wrappable by boost::asio::buffer, or more generally, the parameter type specified by:

template<typename ConstBufferSequence>
std::size_t send(   
   const ConstBufferSequence & buffers
);

The API lists the requirements of a ConstBufferSequence, but I can't make heads or tails of this. Can somebody help me understand? What methods would the type I want to pass to the "send" function need to expose?

like image 730
J T Avatar asked Jun 01 '11 14:06

J T


2 Answers

boost::asio::buffer returns objects implementing the ConstBufferSequence and MutableBufferSequence concepts; it doesn't expect you to implement them. The concrete types you're allowed to pass to buffer are listed here.

like image 119
ildjarn Avatar answered Oct 22 '22 11:10

ildjarn


Although boost::asio::buffer works OK if you have a contiguous set of bytes in memory that you want to use as a buffer, if you are using scatter/gather I/O --or in particular if you are using gather writes (scatter reads are much less common), you do need to have an object that behaves like a ConstBufferSequence.

[If Concepts had made it into the standard [sigh], you would need an object that implements the ConstBufferSequence concept]

Here is a snippet of code from the Codecs::DataDestination class in QuickFAST (http:://www.quickfast.org) that implements ConstBufferSequence:

class DataDestination
{
  /// @brief Support for asio gather writes: forward iterator through buffers
  ///
  /// The intent is for DataDestination to conform to the asio::ConstBufferSequence concept.
  /// This would allow it to be passed directly to the asio::write(v)
  /// Note the implication that if asynch writes are used the DataDestination must
  /// remain intact until the write completes.
  class const_iterator
  {
  public:
    /// @brief construct an iterator pointing into a DataDestination
    /// @param destination is the buffer-container
    /// @param position is the starting position for the iterator.
    const_iterator(const DataDestination & destination, size_t position)
      : destination_(destination)
      , position_(position)
    { 
    }
     /// @brief Point iterator to next buffer (preincrement)
    const_iterator & operator ++()
    {
      if(position_ < destination_.size())
      {
        ++position_;
      }
      return *this;
    }

    /// @brief Point iterator to next buffer (postincrement)
    const_iterator operator ++(int)
    {
      const_iterator result(*this);
      if(position_ < destination_.size())
      {
        ++position_;
      }
      return result;
    }

    /// @brief dereference the iterator to find the actual buffer
    boost::asio::const_buffer operator * () const
    {
      const WorkingBuffer & buffer(destination_[position_]);
      return boost::asio::const_buffer(buffer.begin(), buffer.size());
    }

    /// @brief dereference the iterator to find the actual buffer
    boost::asio::const_buffer operator -> () const
    {
      const WorkingBuffer & buffer(destination_[position_]);
        return boost::asio::const_buffer(buffer.begin(), buffer.size());
    }

    /// @brief compare iterators.
    /// @param rhs is the iterator to which this should be compared.
    bool operator == (const const_iterator & rhs) const
    {
      return position_ == rhs.position_;
    }

    /// @brief compare iterators.
    /// @param rhs is the iterator to which this should be compared.
    bool operator != (const const_iterator & rhs) const
    {
      return position_ != rhs.position_;
    }
  private:
    const_iterator & operator=(const_iterator &); // no autogenerated assignment

  private:
    const DataDestination & destination_;
    size_t position_;
  };

  /// @brief return iterator pointing to the first buffer.
  const_iterator begin()const
  {
    return const_iterator(*this, 0);
  }

  /// @brief return iterator pointing past the last buffer
  const_iterator end() const
  {
    return const_iterator(*this, used_);
  }
};
like image 20
Dale Wilson Avatar answered Oct 22 '22 13:10

Dale Wilson