1 /*
2  *  Copyright 2019 The WebRTC Project Authors. All rights reserved.
3  *
4  *  Use of this source code is governed by a BSD-style license
5  *  that can be found in the LICENSE file in the root of the source
6  *  tree. An additional intellectual property rights grant can be found
7  *  in the file PATENTS.  All contributing project authors may
8  *  be found in the AUTHORS file in the root of the source tree.
9  */
10 
11 #ifndef RTC_BASE_MEMORY_FIFO_BUFFER_H_
12 #define RTC_BASE_MEMORY_FIFO_BUFFER_H_
13 
14 #include <memory>
15 
16 #include "rtc_base/stream.h"
17 
18 namespace rtc {
19 
20 // FifoBuffer allows for efficient, thread-safe buffering of data between
21 // writer and reader.
22 class FifoBuffer final : public StreamInterface {
23  public:
24   // Creates a FIFO buffer with the specified capacity.
25   explicit FifoBuffer(size_t length);
26   // Creates a FIFO buffer with the specified capacity and owner
27   FifoBuffer(size_t length, Thread* owner);
28   ~FifoBuffer() override;
29   // Gets the amount of data currently readable from the buffer.
30   bool GetBuffered(size_t* data_len) const;
31   // Resizes the buffer to the specified capacity. Fails if data_length_ > size
32   bool SetCapacity(size_t length);
33 
34   // Read into |buffer| with an offset from the current read position, offset
35   // is specified in number of bytes.
36   // This method doesn't adjust read position nor the number of available
37   // bytes, user has to call ConsumeReadData() to do this.
38   StreamResult ReadOffset(void* buffer,
39                           size_t bytes,
40                           size_t offset,
41                           size_t* bytes_read);
42 
43   // Write |buffer| with an offset from the current write position, offset is
44   // specified in number of bytes.
45   // This method doesn't adjust the number of buffered bytes, user has to call
46   // ConsumeWriteBuffer() to do this.
47   StreamResult WriteOffset(const void* buffer,
48                            size_t bytes,
49                            size_t offset,
50                            size_t* bytes_written);
51 
52   // StreamInterface methods
53   StreamState GetState() const override;
54   StreamResult Read(void* buffer,
55                     size_t bytes,
56                     size_t* bytes_read,
57                     int* error) override;
58   StreamResult Write(const void* buffer,
59                      size_t bytes,
60                      size_t* bytes_written,
61                      int* error) override;
62   void Close() override;
63 
64   // Seek to a byte offset from the beginning of the stream.  Returns false if
65   // the stream does not support seeking, or cannot seek to the specified
66   // position.
67   bool SetPosition(size_t position);
68 
69   // Get the byte offset of the current position from the start of the stream.
70   // Returns false if the position is not known.
71   bool GetPosition(size_t* position) const;
72 
73   // Seek to the start of the stream.
Rewind()74   bool Rewind() { return SetPosition(0); }
75 
76   // GetReadData returns a pointer to a buffer which is owned by the stream.
77   // The buffer contains data_len bytes.  null is returned if no data is
78   // available, or if the method fails.  If the caller processes the data, it
79   // must call ConsumeReadData with the number of processed bytes.  GetReadData
80   // does not require a matching call to ConsumeReadData if the data is not
81   // processed.  Read and ConsumeReadData invalidate the buffer returned by
82   // GetReadData.
83   const void* GetReadData(size_t* data_len);
84   void ConsumeReadData(size_t used);
85   // GetWriteBuffer returns a pointer to a buffer which is owned by the stream.
86   // The buffer has a capacity of buf_len bytes.  null is returned if there is
87   // no buffer available, or if the method fails.  The call may write data to
88   // the buffer, and then call ConsumeWriteBuffer with the number of bytes
89   // written.  GetWriteBuffer does not require a matching call to
90   // ConsumeWriteData if no data is written.  Write and
91   // ConsumeWriteData invalidate the buffer returned by GetWriteBuffer.
92   void* GetWriteBuffer(size_t* buf_len);
93   void ConsumeWriteBuffer(size_t used);
94 
95   // Return the number of Write()-able bytes remaining before end-of-stream.
96   // Returns false if not known.
97   bool GetWriteRemaining(size_t* size) const;
98 
99  private:
100   // Helper method that implements ReadOffset. Caller must acquire a lock
101   // when calling this method.
102   StreamResult ReadOffsetLocked(void* buffer,
103                                 size_t bytes,
104                                 size_t offset,
105                                 size_t* bytes_read)
106       RTC_EXCLUSIVE_LOCKS_REQUIRED(crit_);
107 
108   // Helper method that implements WriteOffset. Caller must acquire a lock
109   // when calling this method.
110   StreamResult WriteOffsetLocked(const void* buffer,
111                                  size_t bytes,
112                                  size_t offset,
113                                  size_t* bytes_written)
114       RTC_EXCLUSIVE_LOCKS_REQUIRED(crit_);
115 
116   // keeps the opened/closed state of the stream
117   StreamState state_ RTC_GUARDED_BY(crit_);
118   // the allocated buffer
119   std::unique_ptr<char[]> buffer_ RTC_GUARDED_BY(crit_);
120   // size of the allocated buffer
121   size_t buffer_length_ RTC_GUARDED_BY(crit_);
122   // amount of readable data in the buffer
123   size_t data_length_ RTC_GUARDED_BY(crit_);
124   // offset to the readable data
125   size_t read_position_ RTC_GUARDED_BY(crit_);
126   // stream callbacks are dispatched on this thread
127   Thread* owner_;
128   // object lock
129   CriticalSection crit_;
130   RTC_DISALLOW_COPY_AND_ASSIGN(FifoBuffer);
131 };
132 
133 }  // namespace rtc
134 
135 #endif  // RTC_BASE_MEMORY_FIFO_BUFFER_H_
136