Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(8)

Side by Side Diff: media/blink/multibuffer.h

Issue 1165903002: Multi reader/writer cache/buffer (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: lru unit tests Created 5 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #ifndef MEDIA_BLINK_MULTIBUFFER_H_
6 #define MEDIA_BLINK_MULTIBUFFER_H_
7
8 #include <stdint.h>
9
10 #include <map>
11
12 #include "base/callback.h"
13 #include "base/memory/ref_counted.h"
14 #include "media/base/data_buffer.h"
15 #include "media/blink/lru.h"
16 #include "media/blink/rangemap.h"
17 #include "media/blink/waiter_index.h"
18
19 namespace media {
20
21 const int kMaxFreesPerAdd = 10;
22 const int kMaxWaitForWriterOffset = 5;
23
24 // MultiBuffers are multi-reader multi-writer cache/buffers with
25 // prefetching and pinning. Data is stored internally in ref-counted
26 // blocks of identical size. |block_size_shift| is log2 of the block
27 // size.
28 class MultiBuffer {
liberato (no reviews please) 2015/06/09 15:00:54 the name "MultiBuffer" is a little confusing. may
hubbe 2015/06/09 21:23:48 It's meant to replace multiple preloading buffers.
29 public:
30 explicit MultiBuffer(int32_t block_size_shift);
31 virtual ~MultiBuffer();
32
33 typedef std::map<int32_t, scoped_refptr<DataBuffer> > DataMap;
34
35 // Adds a writer. This writer becomes responsible
36 // for writing data at |pos| and forwards.
37 // Takes ownership of |writer|.
38 void AddWriter(int32_t pos, Waiter* writer);
liberato (no reviews please) 2015/06/09 15:00:53 are all the positions in byte offsets or block off
hubbe 2015/06/09 21:23:48 Yes. (the new typedef makes that clear)
39
40 // Remove a writer.
41 // Caller takes ownership of |writer|.
42 void RemoveWriter(int32_t pos, Waiter* writer);
43
44 // Wait for block |pos| to become available.
45 // Starts new Writers as needed.
46 void WaitFor(int32_t pos, Waiter* reader);
47
48 // Let the buffer that we're going to want to read
49 // block |pos|, but we're ok with the current level
50 // of buffering, so no worries.
51 void DeferredWaitFor(int32_t pos, Waiter* reader);
liberato (no reviews please) 2015/06/09 15:00:53 why do we need WaitFor vs DeferredWaitFor? should
hubbe 2015/06/09 21:23:48 This class doesn't know about any preload specs.
52
53 // Stop waiting for block |pos|.
54 // Often followed by a call to WaitFor(pos + 1, ...);
55 void StopWaitFor(int32_t pos, Waiter* reader);
56
57 // Returns true if block |pos| is available in the cache.
58 bool Contains(int32_t pos) const;
59
60 // Returns true if some reader is currently waiting for
61 // block |pos|.
62 bool WantNow(int32_t pos) const;
63
64 // Returns true if some reader is will want block |pos| soon.
65 bool WantSoon(int32_t pos) const;
66
67 // Add a data block to the cache, notifying readers as
68 // needed and prune old blocks if cache is too big.
69 void AddData(int32_t pos, scoped_refptr<DataBuffer> data);
70
71 // Change the pin count for a range of data blocks.
72 // Note that blocks do not have to be present in the
73 // cache to be pinned.
74 // Examples:
75 // Pin block 3, 4 & 5: PinRange(3, 6, 1);
76 // Unpin block 4 & 5: PinRange(4, 6, -1);
77 void PinRange(int32_t from, int32_t to, int32_t howmuch);
78
79 // Increment max cache size by |size|.
80 void IncrementMaxSize(int32_t size);
81
82 // Accessors.
83 const DataMap& map() const { return data_; }
84 int32_t block_size_shift() const { return block_size_shift_; }
85
86 protected:
87 // Start a new writer at |pos|.
88 // Should call AddWriter().
89 virtual void StartWriter(int32_t pos) = 0;
liberato (no reviews please) 2015/06/09 15:00:53 MultiBuffer::StartWriter => new Writer => MultiBuf
hubbe 2015/06/09 21:23:48 I could break out the cache itself into something
90
91 private:
92 // Free elements from cache if needed and possible.
93 void Prune();
94
95 // Current number of blocks.
96 int32_t size_;
97
98 // Max number of blocks.
99 int32_t max_size_;
100
101 // log2 of block size.
102 int32_t block_size_shift_;
103
104 // Stores the actual data.
105 DataMap data_;
106
107 // Keeps track of readers waiting for data.
108 WaiterIndex reader_index_;
109
110 // Keeps track of readers that will want data soon.
111 WaiterIndex deferred_reader_index_;
112
113 // Keeps track of what writers are waiting.
114 WaiterIndex writer_index_;
115
116 // The LRU should contain all blocks which are not pinned.
117 LRU<int32_t> lru_;
118
119 // Keeps track of what blocks are pinned. If block p is pinned,
120 // then pinned_[p] > 0. Pinned blocks cannot be freed and are
121 // not present in |lru_|.
122 RangeMap<int32_t, int32_t> pinned_;
123 };
124
125 // Typically, calling MultiBuffer::StartWriter() will
126 // instantiate a subclass of this class. Writers are
127 // responsible for writing data into the cache.
128 // Writers are owned by the MultiBuffer.
129 class MultiBufferWriter : public Waiter {
liberato (no reviews please) 2015/06/09 15:00:54 this might be better off in another .h
hubbe 2015/06/09 21:23:48 They really are meant to be used as a set. Origina
130 MultiBufferWriter(MultiBuffer* multibuffer, int32_t pos);
131
132 ~MultiBufferWriter() override;
133
134 // Waiter implementation.
135 void Continue() override;
136
137 protected:
138 virtual void SetDeferred(bool deferred) = 0;
139
140 // Write |data| to |pos_| in the cache and update |pos_|.
141 void Write(scoped_refptr<DataBuffer> data);
142
143 int32_t pos_;
144 MultiBuffer* multibuffer_;
145 };
146
147 // Wrapper for MultiBuffer that offers a simple byte-reading
148 // interface with prefetch.
149 class MultiBufferReader : public Waiter {
150 public:
151 MultiBufferReader(MultiBuffer* multibuffer,
152 int64_t start,
153 int64_t end,
154 int64_t preload,
155 int64_t max_buffer_forward,
156 int64_t max_buffer_backward);
157
158 ~MultiBufferReader() override;
159
160 // Returns number of bytes available for reading.
161 // If the actual number of bytes available is greater
162 // than |preload|, then it might return a number between
163 // |preload| and and the actual number.
164 int64_t Available() const;
165
166 // Seek to a different position.
167 void Seek(int64_t pos);
168
169 // Tries to read |len| bytes and advance position.
170 // Returns true if successful.
171 bool TryRead(unsigned char *data, int64_t len);
172
173 // Wait until |len| bytes are available for reading.
174 void Wait(int64_t len, base::Closure cb);
175
176 // Waiter implementation.
177 void Continue() override;
178
179 private:
180 // Returns the block for a particular byte position.
181 int32_t block(int64_t byte_pos) const;
182
183 // Returns the block for a particular byte position, rounding up.
184 int32_t block_ciel(int64_t byte_pos) const;
185
186 // Check if wait operation can complete now.
187 void CheckWait();
188
189 // Increment preload position if data has been added to the buffer.
190 void IncrementPreloadPos();
191
192 // We're not interested in reading past this position.
193 const int64_t end_;
194
195 // Defer reading once we have this much data.
196 const int64_t preload_;
197
198 // Pin this much data in the cache from the current position.
199 const int64_t max_buffer_forward_;
200 const int64_t max_buffer_backward_;
201
202 // Current position in bytes.
203 int64_t pos_;
204
205 // [block(pos_)..preload_pos_) are known to be in the cache.
206 // preload_pos_ is only allowed to point to a filled
207 // cache position if it is equal to end_ or pos_+preload_.
208 // This is a pointer to a slot in the cache, so the unit is
209 // blocks.
210 int32_t preload_pos_;
211
212 // When Available() > current_wait_size_ we call cb_.
213 int64_t current_wait_size_;
214 base::Closure cb_;
215
216 // The multibuffer we're wrapping, not owned.
217 MultiBuffer* multibuffer_;
218 };
219
220 } // namespace media
221
222 #endif // MEDIA_BLINK_MULTIBUFFER_H_
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698