lab0-实现ByteStream
这篇文章以 CS144 Lab0 为背景,系统讲解了固定容量 ByteStream 的核心实现策略,并延伸讨论了动态缓冲区的工程做法。固定容量缓冲区设计关键做法是让 readIdx/writeIdx 持续自增,仅在访问底层数组时取模。通过 writeIdx - readIdx 可直接得到可读区大小,避免环形队列判空/判…
CS144 lab0 lab0具体的相关事宜可以查看博客:https://kiprey.github.io/2021/11/cs144-lab0/ 完整项目代码: CS144缓冲区实现固定大小 lab0要求实现的缓冲区就是固定大小的,具体要求是需要实现一个可读可写的缓冲区.我们先讲讲实现的逻辑,如下图: img 由于大小固定,我们通过模运算得到每次需要读取或写入的实际位置,而 readIdx 和 writeIdx 则一直+1即可,每次在需要读取的时候判断当前可读区域的大小,我们始终只需要通过 readIdx 和 writeIdx 的相对位置得到刻度区域的大小,而 writeIdx 永远是大于 readIdx ,只有实际读写的时候通过模运算获得需要读写的具体位置,这样就可以避免 writeIdx 在具体逻辑中可能在 readIdx 之后的情况,readIdx 和 writeIdx 是直接存入的取模的结果那么就需要特殊处理可读区域为空以及可写区域为空两种情况(因为这个时候都满足 readIdx==writeIdx).所以我们是通过一直自增,存取的时候再取模的方式完美的避开了无法判空和判满的情况,每次只要计算出可读区域的大小 writeIdx - readIdx ,可写区域的大小就确定了 (capacity-可读区域大小),然后我们就只管根据 writeIdx 或者 readIdx 模运算得到起始位置,然后一直+1再取模得到具体的值即可完成对应操作. 并且这种方式实现的缓冲区, writeIdx 直接表示总共写入多少个字节,readIdx 表示总共读取多少个字节,正好就对应我们需要实现的 bytes_written 方法和 bytes_read 方法.动态大小 当缓冲区需要动态大小的时候,上述策略将变得毫无意义,因为每次扩容的时候需要重新拷贝之前的数据,所以我们需要改变复用内存的模运算策略. 这种动态大小的缓冲区,一般都是在需要扩容的时候,把整体的可读区域重新迁移到最前面,再更新可写指针,这样我们就只需要拷贝部分数据了. 具体的应用有很多,比如muduo网络库种或go标准库种的buffer都是这样实现的. 我写的一个网络库 netpoll-cpp 也有类似的实现: netpoll-cpp/netpoll/util/message_buffer.h netpoll-cpp/netpoll/util/message_buffer.ccByteStream实现声明 前面对固定大小缓冲区的实现方式已经描述完毕,现在我们来看看需要实现的函数声明:class ByteStream { private: bool _error{}; //!< Flag indicating that the stream suffered an error. bool _eof{}; size_t _readIdx{}; size_t _writeIdx{}; std::vector<char> _buffer; public: explicit ByteStream(size_t capacity); size_t write(const std::string &data); size_t remaining_capacity() const; void end_input(); //! Indicate that the stream suffered an error. void set_error() { _error = true; } std::string peek_output(const size_t len) const; //! Remove bytes from the buffer void pop_output(const size_t len); std::string read(const size_t len); //! \returns `true` if the stream input has ended bool input_ended() const; //! \returns `true` if the stream has suffered an error bool error() const { return _error; } //! \returns the maximum amount that can currently be read from the stream size_t buffer_size() const; //! \returns `true` if the buffer is empty bool buffer_empty() const; //! \returns `true`…
正在初始化 WebAssembly 引擎…
首次编译原生模块可能需要数秒
就绪后,页面交互将以接近原生的速度运行