blob: de3ebcd5e8ee98eb9b279e9a8173e9234c25408f [file] [log] [blame]
Niels Möller13339482019-03-28 13:30:15 +01001/*
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"
Markus Handell18523c32020-07-08 17:55:58 +020017#include "rtc_base/synchronization/mutex.h"
Tommi04482982020-10-05 12:43:53 +000018#include "rtc_base/task_utils/pending_task_safety_flag.h"
19#include "rtc_base/task_utils/to_queued_task.h"
Niels Möller13339482019-03-28 13:30:15 +010020
21namespace rtc {
22
23// FifoBuffer allows for efficient, thread-safe buffering of data between
24// writer and reader.
25class FifoBuffer final : public StreamInterface {
26 public:
27 // Creates a FIFO buffer with the specified capacity.
28 explicit FifoBuffer(size_t length);
29 // Creates a FIFO buffer with the specified capacity and owner
30 FifoBuffer(size_t length, Thread* owner);
31 ~FifoBuffer() override;
32 // Gets the amount of data currently readable from the buffer.
33 bool GetBuffered(size_t* data_len) const;
34 // Resizes the buffer to the specified capacity. Fails if data_length_ > size
35 bool SetCapacity(size_t length);
36
Artem Titov96e3b992021-07-26 16:03:14 +020037 // Read into `buffer` with an offset from the current read position, offset
Niels Möller13339482019-03-28 13:30:15 +010038 // is specified in number of bytes.
39 // This method doesn't adjust read position nor the number of available
40 // bytes, user has to call ConsumeReadData() to do this.
41 StreamResult ReadOffset(void* buffer,
42 size_t bytes,
43 size_t offset,
44 size_t* bytes_read);
45
Artem Titov96e3b992021-07-26 16:03:14 +020046 // Write `buffer` with an offset from the current write position, offset is
Niels Möller13339482019-03-28 13:30:15 +010047 // specified in number of bytes.
48 // This method doesn't adjust the number of buffered bytes, user has to call
49 // ConsumeWriteBuffer() to do this.
50 StreamResult WriteOffset(const void* buffer,
51 size_t bytes,
52 size_t offset,
53 size_t* bytes_written);
54
55 // StreamInterface methods
56 StreamState GetState() const override;
57 StreamResult Read(void* buffer,
58 size_t bytes,
59 size_t* bytes_read,
60 int* error) override;
61 StreamResult Write(const void* buffer,
62 size_t bytes,
63 size_t* bytes_written,
64 int* error) override;
65 void Close() override;
66
67 // Seek to a byte offset from the beginning of the stream. Returns false if
68 // the stream does not support seeking, or cannot seek to the specified
69 // position.
70 bool SetPosition(size_t position);
71
72 // Get the byte offset of the current position from the start of the stream.
73 // Returns false if the position is not known.
74 bool GetPosition(size_t* position) const;
75
76 // Seek to the start of the stream.
77 bool Rewind() { return SetPosition(0); }
78
79 // GetReadData returns a pointer to a buffer which is owned by the stream.
80 // The buffer contains data_len bytes. null is returned if no data is
81 // available, or if the method fails. If the caller processes the data, it
82 // must call ConsumeReadData with the number of processed bytes. GetReadData
83 // does not require a matching call to ConsumeReadData if the data is not
84 // processed. Read and ConsumeReadData invalidate the buffer returned by
85 // GetReadData.
86 const void* GetReadData(size_t* data_len);
87 void ConsumeReadData(size_t used);
88 // GetWriteBuffer returns a pointer to a buffer which is owned by the stream.
89 // The buffer has a capacity of buf_len bytes. null is returned if there is
90 // no buffer available, or if the method fails. The call may write data to
91 // the buffer, and then call ConsumeWriteBuffer with the number of bytes
92 // written. GetWriteBuffer does not require a matching call to
93 // ConsumeWriteData if no data is written. Write and
94 // ConsumeWriteData invalidate the buffer returned by GetWriteBuffer.
95 void* GetWriteBuffer(size_t* buf_len);
96 void ConsumeWriteBuffer(size_t used);
97
98 // Return the number of Write()-able bytes remaining before end-of-stream.
99 // Returns false if not known.
100 bool GetWriteRemaining(size_t* size) const;
101
102 private:
Tommi04482982020-10-05 12:43:53 +0000103 void PostEvent(int events, int err) {
104 owner_->PostTask(webrtc::ToQueuedTask(task_safety_, [this, events, err]() {
105 SignalEvent(this, events, err);
106 }));
107 }
108
Niels Möller13339482019-03-28 13:30:15 +0100109 // Helper method that implements ReadOffset. Caller must acquire a lock
110 // when calling this method.
111 StreamResult ReadOffsetLocked(void* buffer,
112 size_t bytes,
113 size_t offset,
114 size_t* bytes_read)
Markus Handell18523c32020-07-08 17:55:58 +0200115 RTC_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
Niels Möller13339482019-03-28 13:30:15 +0100116
117 // Helper method that implements WriteOffset. Caller must acquire a lock
118 // when calling this method.
119 StreamResult WriteOffsetLocked(const void* buffer,
120 size_t bytes,
121 size_t offset,
122 size_t* bytes_written)
Markus Handell18523c32020-07-08 17:55:58 +0200123 RTC_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
Niels Möller13339482019-03-28 13:30:15 +0100124
Tommi04482982020-10-05 12:43:53 +0000125 webrtc::ScopedTaskSafety task_safety_;
126
Niels Möller13339482019-03-28 13:30:15 +0100127 // keeps the opened/closed state of the stream
Markus Handell18523c32020-07-08 17:55:58 +0200128 StreamState state_ RTC_GUARDED_BY(mutex_);
Niels Möller13339482019-03-28 13:30:15 +0100129 // the allocated buffer
Markus Handell18523c32020-07-08 17:55:58 +0200130 std::unique_ptr<char[]> buffer_ RTC_GUARDED_BY(mutex_);
Niels Möller13339482019-03-28 13:30:15 +0100131 // size of the allocated buffer
Markus Handell18523c32020-07-08 17:55:58 +0200132 size_t buffer_length_ RTC_GUARDED_BY(mutex_);
Niels Möller13339482019-03-28 13:30:15 +0100133 // amount of readable data in the buffer
Markus Handell18523c32020-07-08 17:55:58 +0200134 size_t data_length_ RTC_GUARDED_BY(mutex_);
Niels Möller13339482019-03-28 13:30:15 +0100135 // offset to the readable data
Markus Handell18523c32020-07-08 17:55:58 +0200136 size_t read_position_ RTC_GUARDED_BY(mutex_);
Niels Möller13339482019-03-28 13:30:15 +0100137 // stream callbacks are dispatched on this thread
Tommi04482982020-10-05 12:43:53 +0000138 Thread* const owner_;
Niels Möller13339482019-03-28 13:30:15 +0100139 // object lock
Markus Handell18523c32020-07-08 17:55:58 +0200140 mutable webrtc::Mutex mutex_;
Niels Möller13339482019-03-28 13:30:15 +0100141 RTC_DISALLOW_COPY_AND_ASSIGN(FifoBuffer);
142};
143
144} // namespace rtc
145
146#endif // RTC_BASE_MEMORY_FIFO_BUFFER_H_