muduo 源码阅读:Buffer

2021-03-17  本文已影响0人  wayyyy

为什么non-blocking 网络编程中应用层Buffer是必须的?

TODO

Buffer 数据结构

class Buffer
{
public:
    static const size_t kCheapPrepend = 8;
    static const size_t kInitialSize = 1024;
public:
private:
    std::vector<char> buffer_;
    size_t readerIndex_;
    size_t writerIndex_;
};
image.png

Buffer 操作

size_t readableBytes() const {  return writerIndex_ - readerIndex_;  }
size_t writableBytes() const  {  return buffer_.size() - writerIndex_;  }
size_t prependableBytes() const  {  return readerIndex_;  }
const char *peek() const  {  return begin() + readerIndex_;  }
char *beginWrite()  {  return begin() + writerIndex_;  }
写入数据
void appendInt32(int32_t x)
{
    int32_t be32 = sockets::hostToNetwork32(x);
    append(&be32, sizeof(be32));
}

void append(const void * /*restrict*/ data, size_t len)
{
    append(static_cast<const char *>(data), len);
}

void append(const char * /*restrict*/ data, size_t len)
{
    ensureWritableBytes(len);
    std::copy(data, data + len, beginWrite());
    hasWritten(len);
}

void ensureWritableBytes(size_t len)
{
    if (writableBytes() < len)
    {
        makeSpace(len);
    }
    assert(writableBytes() >= len);
}

void makeSpace(size_t len)
{
    if (writableBytes() + prependableBytes() < len + kCheapPrepend)
    {
         // FIXME: move readable data
         buffer_.resize(writerIndex_ + len);
    }
    else
    {
        // move readable data to the front, make space inside buffer
        assert(kCheapPrepend < readerIndex_);
        size_t readable = readableBytes();
        std::copy(begin() + readerIndex_, 
                  begin() + writerIndex_, 
                  begin() + kCheapPrepend);
        readerIndex_ = kCheapPrepend;
        writerIndex_ = readerIndex_ + readable;
        assert(readable == readableBytes());
    }
}

void hasWritten(size_t len)
{
    assert(len <= writableBytes());
    writerIndex_ += len;
}
读取数据
int32_t readInt32()
{
    int32_t result = peekInt32();
    retrieveInt32();
    return result;
}

void retrieveInt32()
{
    retrieve(sizeof(int32_t));
}     

void retrieve(size_t len)
{
    assert(len <= readableBytes());
    if (len < readableBytes()) 
    {
        readerIndex_ += len;
    }
    else  // len == readableBytes()
    {
        retrieveAll();
    }
}

void retrieveAll()
{
    readerIndex_ = kCheapPrepend;
    writerIndex_ = kCheapPrepend;
}

prehead

readFd

ssize_t Buffer::readFd(int fd, int* savedErrno)
{
    // saved an ioctl()/FIONREAD call to tell how much to read
    char extrabuf[65536];
    struct iovec vec[2];
    const size_t writable = writableBytes();
    vec[0].iov_base = begin()+writerIndex_;
    vec[0].iov_len = writable;
    vec[1].iov_base = extrabuf;
    vec[1].iov_len = sizeof extrabuf;
    // when there is enough space in this buffer, don't read into extrabuf.
    // when extrabuf is used, we read 128k-1 bytes at most.
    const int iovcnt = (writable < sizeof extrabuf) ? 2 : 1;
    const ssize_t n = sockets::readv(fd, vec, iovcnt);
    if (n < 0)
    {
        *savedErrno = errno;
    }
    else if (implicit_cast<size_t>(n) <= writable)
    {
      writerIndex_ += n;
    }
    else
    {
      writerIndex_ = buffer_.size();
      append(extrabuf, n - writable);
    }
    
    return n;
}
上一篇 下一篇

猜你喜欢

热点阅读