StreamBuffer.h
上传用户:kx_jwh
上传日期:2021-09-03
资源大小:76k
文件大小:12k
源码类别:

STL

开发平台:

Visual C++

  1. /* vim: set tabstop=4 : */
  2. #ifndef __febird_io_StreamBuffer_h__
  3. #define __febird_io_StreamBuffer_h__
  4. #if defined(_MSC_VER) && (_MSC_VER >= 1020)
  5. # pragma once
  6. #endif
  7. #include "IOException.h"
  8. #include "IStream.h"
  9. #include "MemStream.h"
  10. #include "../refcount.h"
  11. /**
  12.  @file 以 Stream 的 Concept, 实现的 Buffer
  13.  可以和 Stream 一样的用,但提供了高速缓冲——是 C FILE 的大约 20 倍
  14.  - 使用缓冲倒置:
  15.    -# 一般的实现(BufferStream)是给 Stream 增加缓冲功能
  16.    -# 而这个实现(StreamBuffer)是给缓冲增加 Stream 功能
  17.    -# 这里的主体是 Buffer, 而非 Stream
  18.  - 高性能主要通过以下几点技法实现
  19.    -# 让调用最频繁的函数 inline, 并保持函数内容最短, 如 read/ensureRead/readByte, 等
  20.    -# 在这些 inline 函数最频繁的执行路径上, 执行最少的代码 @see InputBuffer::readByte
  21.    -# 只有极少情况下会执行的分支, 封装到一个非虚函数(非虚函数的调用代码比虚函数小)
  22.    -# 如此, inline 函数的执行效率会非常高, 在 Visual Studio 下, ensureRead 中的 memcpy 在大多数情况下完全被优化掉了:
  23.  @code
  24.   LittleEndianDataInput<InputBuffer> input(&buf);
  25.   int x;
  26.   input >> x;
  27.   // 在这个代码段中, input >> x;
  28.   // 的最频繁分支甚至被优化成了等价代码: x = *(int*)m_cur;
  29.   // 底层函数调用的 memcpy 完全被优化掉了
  30.  @endcode
  31.  - 共有五种 StreamBuffer: InputBuffer/OutputBuffer/SeekableInputBuffer/SeekableOutputBuffer/SeekableBuffer
  32.    -# 每种 buffer 都可以附加(attach)一个支持相应功能的流
  33.    -# SeekableInputBuffer 并不要求 stream 必须是 ISeekableInputStream,
  34.       只需要 stream 同时实现了 ISeekable 和 IInputStream 即可
  35.    -# SeekableBuffer 并不要求 stream 是 ISeekableStream,
  36.       只需要 stream 同时实现了 ISeekable/IInputStream/IOutputStream
  37.  */
  38. namespace febird {
  39. class FEBIRD_DLL_EXPORT IOBufferBase : public RefCounter
  40. {
  41. private:
  42. // can not copy
  43. IOBufferBase(const IOBufferBase&);
  44. const IOBufferBase& operator=(const IOBufferBase&);
  45. public:
  46. IOBufferBase();
  47. virtual ~IOBufferBase();
  48. //! 设置 buffer 尺寸并分配 buffer 内存
  49. //! 在整个生存期内只能调用一次
  50. void initbuf(size_t capacity) FEBIRD_RESTRICT;
  51. //! 如果在 init 之前调用,仅设置 buffer 尺寸
  52. //! 否则重新分配 buffer 并设置相应的指针
  53. void set_bufsize(size_t size) FEBIRD_RESTRICT;
  54. byte*  bufbeg() const { return m_beg; }
  55. byte*  bufcur() const { return m_cur; }
  56. byte*  bufend() const { return m_end; }
  57. size_t bufpos()  const { return m_cur-m_beg; }
  58. size_t bufsize() const { return m_end-m_beg; }
  59. size_t bufcapacity() const { return m_capacity; }
  60. //! only seek in buffer
  61. //!
  62. //! when dest stream is null, can seek and used as a memstream
  63. virtual void seek_cur(ptrdiff_t diff);
  64. //! set buffer eof
  65. //!
  66. //! most for m_is/m_os == 0
  67. void set_bufeof(size_t eofpos);
  68. protected:
  69. //! 当调用完 stream.read/write 时,使用该函数来同步内部 pos 变量
  70. //!
  71. //! 对 non-seekable stream, 这个函数是空, SeekableBufferBase 改写了该函数
  72. //! @see SeekableBufferBase::update_pos
  73. virtual void update_pos(size_t inc) {} // empty for non-seekable
  74. protected:
  75. // dummy, only for OutputBufferBase::attach to use
  76. void attach(void*) { }
  77. protected:
  78. // for  InputBuffer, [m_beg, m_cur) is readed,  [m_cur, m_end) is prefetched
  79. // for OutputBuffer, [m_beg, m_cur) is written, [m_cur, m_end) is undefined
  80. byte*  FEBIRD_RESTRICT m_beg; // buffer ptr
  81. byte*  FEBIRD_RESTRICT m_cur; // current read/write position
  82. byte*  FEBIRD_RESTRICT m_end;   // end mark, m_end <= m_beg + m_capacity && m_end >= m_beg
  83. size_t m_capacity; // buffer capacity
  84. };
  85. class FEBIRD_DLL_EXPORT InputBuffer : public IOBufferBase
  86. {
  87. public:
  88. // typedef IInputStream stream_t;
  89. typedef boost::mpl::false_ is_seekable;
  90. explicit InputBuffer(IInputStream* stream = 0)
  91. : m_is(stream)
  92. {
  93. }
  94. void attach(IInputStream* stream)
  95. {
  96. m_is = stream;
  97. }
  98. bool eof() const { return m_cur == m_end && (0 == m_is || m_is->eof()); }
  99. size_t read(void* FEBIRD_RESTRICT vbuf, size_t length) FEBIRD_RESTRICT
  100. {
  101. if (m_cur+length <= m_end) {
  102. memcpy(vbuf, m_cur, length);
  103. m_cur += length;
  104. return length;
  105. } else
  106. return fill_and_read(vbuf, length);
  107. }
  108. void ensureRead(void* FEBIRD_RESTRICT vbuf, size_t length) FEBIRD_RESTRICT
  109. {
  110. // 为了效率,这么实现可以让编译器更好地 inline 这个函数
  111. // inline 后的函数体并尽可能小
  112. if (m_cur+length <= m_end) {
  113. memcpy(vbuf, m_cur, length);
  114. m_cur += length;
  115. } else
  116. fill_and_ensureRead(vbuf, length);
  117. }
  118. byte readByte() FEBIRD_RESTRICT
  119. {
  120. if (m_cur < m_end)
  121. return *m_cur++;
  122. else
  123. return fill_and_read_byte();
  124. }
  125. int getByte() FEBIRD_RESTRICT
  126. {
  127. if (m_cur < m_end)
  128. return *m_cur++;
  129. else
  130. return this->fill_and_get_byte();
  131. }
  132. void getline(std::string& line, size_t maxlen);
  133. template<class OutputStream>
  134. void to_output(OutputStream& output, size_t length) FEBIRD_RESTRICT
  135. {
  136. size_t total = 0;
  137. while (total < length)
  138. {
  139. using namespace std; // for min
  140. if (m_cur == m_end)
  141. this->fill_and_read(m_beg, m_end-m_beg);
  142. size_t nWrite = min(size_t(m_end-m_cur), size_t(length-total));
  143. output.ensureWrite(m_cur, nWrite);
  144. total += nWrite;
  145. m_cur += nWrite;
  146. }
  147. }
  148. protected:
  149. size_t fill_and_read(void* FEBIRD_RESTRICT vbuf, size_t length) FEBIRD_RESTRICT;
  150. void   fill_and_ensureRead(void* FEBIRD_RESTRICT vbuf, size_t length) FEBIRD_RESTRICT;
  151. byte   fill_and_read_byte() FEBIRD_RESTRICT;
  152. int    fill_and_get_byte() FEBIRD_RESTRICT;
  153. size_t read_min_max(void* FEBIRD_RESTRICT vbuf, size_t min_length, size_t max_length) FEBIRD_RESTRICT;
  154. virtual size_t do_fill_and_read(void* FEBIRD_RESTRICT vbuf, size_t length) FEBIRD_RESTRICT;
  155. protected:
  156. IInputStream* m_is;
  157. };
  158. template<class BaseClass>
  159. class FEBIRD_DLL_EXPORT OutputBufferBase : public BaseClass
  160. {
  161. public:
  162. typedef boost::mpl::false_ is_seekable;
  163. explicit OutputBufferBase(IOutputStream* os = 0) : m_os(os)
  164. {
  165. }
  166. virtual ~OutputBufferBase();
  167. template<class Stream>
  168. void attach(Stream* stream)
  169. {
  170. BaseClass::attach(stream);
  171. m_os = stream;
  172. }
  173. void flush();
  174. size_t write(const void* FEBIRD_RESTRICT vbuf, size_t length) FEBIRD_RESTRICT
  175. {
  176. if (m_cur+length <= m_end) {
  177. memcpy(m_cur, vbuf, length);
  178. m_cur += length;
  179. return length;
  180. } else
  181. return flush_and_write(vbuf, length);
  182. }
  183. void ensureWrite(const void* FEBIRD_RESTRICT vbuf, size_t length) FEBIRD_RESTRICT
  184. {
  185. // 为了效率,这么实现可以让编译器更好地 inline 这个函数
  186. // inline 后的函数体并尽可能小
  187. if (m_cur+length <= m_end) {
  188. memcpy(m_cur, vbuf, length);
  189. m_cur += length;
  190. } else
  191. flush_and_ensureWrite(vbuf, length);
  192. }
  193. void writeByte(byte b) FEBIRD_RESTRICT
  194. {
  195. if (m_cur < m_end)
  196. *m_cur++ = b;
  197. else
  198. flush_and_write_byte(b);
  199. }
  200. template<class InputStream>
  201. void from_input(InputStream& input, size_t length) FEBIRD_RESTRICT
  202. {
  203. size_t total = 0;
  204. while (total < length)
  205. {
  206. using namespace std; // for min
  207. if (m_cur == m_end)
  208. flush_buffer();
  209. size_t nRead = min(size_t(m_end-m_cur), size_t(length-total));
  210. input.ensureRead(m_cur, nRead);
  211. total += nRead;
  212. m_cur += nRead;
  213. }
  214. }
  215. protected:
  216. size_t flush_and_write(const void* FEBIRD_RESTRICT vbuf, size_t length) FEBIRD_RESTRICT;
  217. void   flush_and_ensureWrite(const void* FEBIRD_RESTRICT vbuf, size_t length) FEBIRD_RESTRICT;
  218. void   flush_and_write_byte(byte b) FEBIRD_RESTRICT;
  219. virtual size_t do_flush_and_write(const void* FEBIRD_RESTRICT vbuf, size_t length) FEBIRD_RESTRICT;
  220. virtual void flush_buffer(); // only write to m_os, not flush m_os
  221. protected:
  222. IOutputStream* m_os;
  223. using BaseClass::m_cur;
  224. using BaseClass::m_beg;
  225. using BaseClass::m_end;
  226. using BaseClass::m_capacity;
  227. };
  228. typedef OutputBufferBase<IOBufferBase> OutputBuffer;
  229. template<class BaseClass>
  230. class FEBIRD_DLL_EXPORT SeekableBufferBase : public BaseClass
  231. {
  232. protected:
  233. using BaseClass::m_beg;
  234. using BaseClass::m_cur;
  235. using BaseClass::m_end;
  236. using BaseClass::m_capacity;
  237. public:
  238. typedef boost::mpl::true_ is_seekable;
  239. //! constructor
  240. //!
  241. //! 如果以 append 方式打开流,这个 m_stream_pos 是不对的
  242. //! 不过一般这种情况下很少会调用 seek/tell
  243. //! 如果真这么做,会导致未定义行为
  244. explicit SeekableBufferBase()
  245. {
  246. m_seekable = 0;
  247. m_stream_pos = 0;
  248. }
  249. template<class Stream>
  250. void attach(Stream* stream)
  251. {
  252. BaseClass::attach(stream);
  253. m_seekable = stream;
  254. }
  255. void seek(stream_position_t pos);
  256. void seek(stream_offset_t offset, int origin);
  257. void seek_cur(ptrdiff_t diff);
  258. stream_position_t tell() const;
  259. stream_position_t size() const;
  260. protected:
  261. virtual void update_pos(size_t inc); //!< override
  262. virtual void invalidate_buffer() = 0;
  263. //! 如果已预取,m_stream_pos 对应缓冲区末尾 m_end
  264. //! 否则 m_stream_pos 对应缓冲区开始
  265. virtual int is_prefetched() const = 0;
  266. protected:
  267. ISeekable* m_seekable;
  268. stream_position_t m_stream_pos;
  269. };
  270. class FEBIRD_DLL_EXPORT SeekableInputBuffer : public SeekableBufferBase<InputBuffer>
  271. {
  272. typedef SeekableBufferBase<InputBuffer> super;
  273. public:
  274. SeekableInputBuffer() { }
  275. protected:
  276. virtual void invalidate_buffer();
  277. virtual int is_prefetched() const;
  278. };
  279. class FEBIRD_DLL_EXPORT SeekableOutputBuffer : public SeekableBufferBase<OutputBuffer>
  280. {
  281. typedef SeekableBufferBase<OutputBuffer> super;
  282. public:
  283. // typedef boost::mpl::true_ is_seekable;
  284. //! constructor
  285. //!
  286. //! 如果以 append 方式打开流,这个 m_stream_pos 是不对的
  287. //! 不过一般这种情况下很少会调用 seek/tell
  288. //! 如果真这么做,会导致未定义行为
  289. SeekableOutputBuffer() {}
  290. protected:
  291. virtual void invalidate_buffer();
  292. virtual int is_prefetched() const;
  293. };
  294. class FEBIRD_DLL_EXPORT SeekableBuffer :
  295. public SeekableBufferBase<OutputBufferBase<InputBuffer> >
  296. {
  297. typedef SeekableBufferBase<OutputBufferBase<InputBuffer> > super;
  298. public:
  299. SeekableBuffer();
  300. ~SeekableBuffer();
  301. size_t read(void* FEBIRD_RESTRICT vbuf, size_t length) FEBIRD_RESTRICT
  302. {
  303. if (m_cur+length <= m_end && m_prefetched) {
  304. memcpy(vbuf, m_cur, length);
  305. m_cur += length;
  306. return length;
  307. } else
  308. return fill_and_read(vbuf, length);
  309. }
  310. void ensureRead(void* FEBIRD_RESTRICT vbuf, size_t length) FEBIRD_RESTRICT
  311. {
  312. // 为了效率,这么实现可以让编译器更好地 inline 这个函数
  313. // inline 后的函数体并尽可能小
  314. if (m_cur+length <= m_end && m_prefetched) {
  315. memcpy(vbuf, m_cur, length);
  316. m_cur += length;
  317. } else
  318. fill_and_ensureRead(vbuf, length);
  319. }
  320. byte readByte() FEBIRD_RESTRICT 
  321. {
  322. if (m_cur < m_end && m_prefetched)
  323. return *m_cur++;
  324. else
  325. return fill_and_read_byte();
  326. }
  327. int getByte() FEBIRD_RESTRICT 
  328. {
  329. if (m_cur < m_end && m_prefetched)
  330. return *m_cur++;
  331. else
  332. return fill_and_get_byte();
  333. }
  334. size_t write(const void* vbuf, size_t length) FEBIRD_RESTRICT 
  335. {
  336. m_dirty = true;
  337. return super::write(vbuf, length);
  338. }
  339. void ensureWrite(const void* vbuf, size_t length) FEBIRD_RESTRICT 
  340. {
  341. m_dirty = true;
  342. super::ensureWrite(vbuf, length);
  343. }
  344. void writeByte(byte b) FEBIRD_RESTRICT 
  345. {
  346. m_dirty = true;
  347. super::writeByte(b);
  348. }
  349. protected:
  350. virtual size_t do_fill_and_read(void* FEBIRD_RESTRICT vbuf, size_t length) FEBIRD_RESTRICT ; //!< override
  351. virtual size_t do_flush_and_write(const void* FEBIRD_RESTRICT vbuf, size_t length) FEBIRD_RESTRICT ; //!< override
  352. virtual void flush_buffer(); //!< override
  353. virtual void invalidate_buffer(); //!< override
  354. virtual int is_prefetched() const;
  355. private:
  356. int m_dirty;
  357. int m_prefetched;
  358. };
  359. ////////////////////////////////////////////////////////////////////////////////////////////////////////
  360. //
  361. class FEBIRD_DLL_EXPORT FileStreamBuffer : public SeekableBuffer
  362. {
  363. public:
  364. explicit FileStreamBuffer(const char* FEBIRD_RESTRICT fname, const char* FEBIRD_RESTRICT mode, size_t capacity = 8*1024);
  365. ~FileStreamBuffer();
  366. };
  367. } // febird
  368. #endif // __febird_io_StreamBuffer_h__