ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • boost::asio::streambuf 분석..
    프로그래밍/c++ - boost::asio 2015. 9. 15. 15:13
    반응형

    이전에는 수신 버퍼를 직접 만들어서 쓰고 있었다. 수신 버퍼의 이름은 StreamBuffer -_-

    boost::asio::streambuf 수신 버퍼로 쓰는 코드들을 c++ 오픈소스 그룹 커뮤니티에서 보았다.

    streambuf 뭐지? 뭔가 편해 보이는데..

    이름도 streambuf인걸 보면 소켓 송수신에 쓰일 버퍼로 쓰라고 만들어놓은 같길래 여기저기서 코드 사용 예를 살펴보다가

    이전에 내가 직접 만들었던 StreamBuffer 뭔가 비슷하다고 느껴서 코드 내부를 직접 보게

     

    ** 정의

     

    std::streambuf 상속 받는다.

    복사가 불가능 (boost::noncopyable 상속)

    커스텀 할당자를 지원함

     

    ** 생성

    최대 크기(maximum_size) 인자를 지정해주지 않으면 std::numeric_limits<std::size_t>::max() 값이 지정

    Allocator 기본 할당자(std::allocator<char>) 지정

     

    ** 멤버 변수 부분..

     

    private:

      std::size_t max_size_;

      std::vector<char_type, Allocator> buffer_;

     

    멤버로 std::vector 최대 사이즈를 제한을 위한 max_size 가지고 있다.

     

     

    여기까지 파악할 있을 것들

     

    • Streambuf 크기는 가변적. 런타임에 크기를 지정하는 것도 가능하다.
    • 최대 크기를 명시적으로 제한할 있음
    • 커스텀 할당자를 사용할 있다.

     

    ** 멤버 함수들..

     

    prepare(size_t n)

    버퍼를 준비하는(prepare) 함수. Receive 함수를 호출해서 쓰기 버퍼 영역을 만들면 된다. 처음에 봤을 Prepare 자체에서 할당을 하나 했지만 기존에 있는 버퍼를 사용하는거였음. 윈속 프로그래밍을 하다보면 WSABUF라는 구조체를 사용하는데 그것과 같은 기능을 한다고 보면 것이다.

     

    reserve(size_t n)

    쓰기 공간을 예약하는 함수로 내부적으로 버퍼 트리밍하는 기능도 가지고 있다.

    [버퍼의시작] … [읽기시작부분]…..[쓰기시작부분]…[버퍼끝] 이렇게 있을 쓰기 공간이 부족하면 읽기시작부분~쓰기시작부분을 앞으로 당겨서 공간을 확보하는 기능을 .

     

    consume(size_t n)

    버퍼에서 데이터를 읽었을 읽기 인덱스를 뒤로 당기는 함수. 인자로 전달되는 n만큼 당긴다.

     

    commit(size_t n)

    버퍼에 데이터를 썼을 쓰기 인덱스를 뒤로 당기는 함수. 마찬가지로 n만큼 당김

     

    data()

    읽기 부분을 반환한다. 나는 버퍼의 시작점을 주는건줄 알았는데 -_-;;

     

    size()

    버퍼에 담겨진 데이터의 양을 반환함.

     

     

    // 공간을 예약(reserve)하는 함수

     

     

    // 버퍼에 데이터를 삽입하기 , 공간은 충분히 확보가 되어있어야 한다.

    // 따라서 데이터를 삽입을 준비할 함수가 호출된다.

    // std::length_error 예외를 던진다.

    // 버퍼의 공간을 준비하는 prepare 함수도 내부적으로 reserve 호출 공간을 반환!

    // 트림(trim) 기능도 있다!

     

      void reserve(std::size_t n)
      {
        // Get current stream positions as offsets. 얻는다 현 스트림 위치의 오프셋을
        std::size_t gnext = gptr() - &buffer_[0];
        std::size_t pnext = pptr() - &buffer_[0];
        std::size_t pend = epptr() - &buffer_[0];
     
        // Check if there is already enough space in the put area. 검사함 이미 충분히 공간이 확보되었는지
        if (n <= pend - pnext)
        {
          return;
        }
     
        // Shift existing contents of get area to start of buffer. 기존에 있던 데이터들을 버퍼의 시작 지점(&buffer[0)]으로 이동시킴
        if (gnext > 0)
        {
          pnext -= gnext;
          std::memmove(&buffer_[0], &buffer_[0] + gnext, pnext);
        }
     
        // Ensure buffer is large enough to hold at least the specified size. 확인한다 버퍼가  적어도 명시된 크기(n)를 수용할 수 있는지
        if (n > pend - pnext)
        {
          if (n <= max_size_ && pnext <= max_size_ - n)
          {
            pend = pnext + n;
            buffer_.resize((std::max<std::size_t>)(pend, 1));
          }
          else
          {
            std::length_error ex("boost::asio::streambuf too long");
            boost::asio::detail::throw_exception(ex);
          }
        }
     
        // Update stream positions. // 스트림 위치를 갱신함
        setg(&buffer_[0], &buffer_[0], &buffer_[0] + pnext);
        setp(&buffer_[0] + pnext, &buffer_[0] + pend);
      }
     
    // 데이터 receive 전, 공간을 준비하는 함수이다.
    // 인자로 전해지는 n의 크기만큼 공간을 준비한다.
    // 내부적으로 reserve 함수를 호출.
      mutable_buffers_type prepare(std::size_t n)
      {
        reserve(n);
        return boost::asio::buffer(boost::asio::mutable_buffer(
              pptr(), n * sizeof(char_type)));
      }

     

    내가 만든 StreamBuffer를 이거로 대체해도 될 듯 기능이 거의 비슷하다. 

     

    ++ 2016/04/11

     

    이건 std::streambuf에 있는 함수인데 반환하는 것들은 다음과 같다.

     

      // pbase write buffer의 처음

      // epptr write buffer의 끝

      // pptr write buffer의 현재 위치

     

      // eback read buffer의 처음

      // egptr read buffer의 끝

      // gptr read buffer의 현재 위치

     

    쓰기 버퍼의 총 량을 반환하는 함수는 다음과 같이 쓸 수 있다.

     

    1
    2
    3
    4
    5
    6
     
    size_t capacity() const  
    {    
      return epptr() - pbase(); // 쓰기 버퍼의 끝 - 쓰기 버퍼의 처음  
    }
     
     
    cs

     

    반응형
Designed by Tistory.