Line data Source code
1 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* vim:set ts=2 sw=2 sts=2 et cindent: */
3 : /* This Source Code Form is subject to the terms of the Mozilla Public
4 : * License, v. 2.0. If a copy of the MPL was not distributed with this file,
5 : * You can obtain one at http://mozilla.org/MPL/2.0/. */
6 :
7 : #ifndef MEMORY_BLOCK_CACHE_H_
8 : #define MEMORY_BLOCK_CACHE_H_
9 :
10 : #include "MediaBlockCacheBase.h"
11 : #include "mozilla/Mutex.h"
12 :
13 : namespace mozilla {
14 :
15 : // Manages block management for the media cache. Data comes in over the network
16 : // via callbacks on the main thread, however we don't want to write the
17 : // incoming data to the media cache on the main thread, as this could block
18 : // causing UI jank.
19 : //
20 : // So MediaBlockCacheBase provides an abstraction for a temporary memory buffer
21 : // as an array of blocks, which supports a block move operation, and
22 : // allows synchronous reading and writing from any thread.
23 : //
24 : // Writes and cache block moves (which require reading) may be deferred to
25 : // their own non-main thread. This object also ensures that data which has
26 : // been scheduled to be written, but hasn't actually *been* written, is read
27 : // as if it had, i.e. pending writes are cached in readable memory until
28 : // they're flushed to file.
29 : //
30 : // To improve efficiency, writes can only be done at block granularity,
31 : // whereas reads can be done with byte granularity.
32 : class MemoryBlockCache : public MediaBlockCacheBase
33 : {
34 : public:
35 : explicit MemoryBlockCache(int64_t aContentLength);
36 :
37 : protected:
38 : virtual ~MemoryBlockCache();
39 :
40 : public:
41 : // Allocate initial buffer.
42 : // If re-initializing, clear buffer.
43 : virtual nsresult Init() override;
44 :
45 : // Maximum number of blocks allowed in this block cache.
46 : // Based on initial content length, and minimum usable block cache.
47 0 : int32_t GetMaxBlocks() const override { return mMaxBlocks; }
48 :
49 : // Can be called on any thread.
50 : virtual nsresult WriteBlock(uint32_t aBlockIndex,
51 : Span<const uint8_t> aData1,
52 : Span<const uint8_t> aData2) override;
53 :
54 : // Synchronously reads data from buffer.
55 : virtual nsresult Read(int64_t aOffset,
56 : uint8_t* aData,
57 : int32_t aLength,
58 : int32_t* aBytes) override;
59 :
60 : // Moves a block. Can be called on any thread.
61 : virtual nsresult MoveBlock(int32_t aSourceBlockIndex,
62 : int32_t aDestBlockIndex) override;
63 :
64 : private:
65 0 : static size_t BlockIndexToOffset(uint32_t aBlockIndex)
66 : {
67 0 : return static_cast<size_t>(aBlockIndex) * BLOCK_SIZE;
68 : }
69 :
70 : // Ensure the buffer has at least a multiple of BLOCK_SIZE that can contain
71 : // aContentLength bytes. Buffer size can only grow.
72 : // Returns false if allocation failed.
73 : bool EnsureBufferCanContain(size_t aContentLength);
74 :
75 : // Initial content length.
76 : const size_t mInitialContentLength;
77 :
78 : // Maximum number of blocks that this MemoryBlockCache expects.
79 : const int32_t mMaxBlocks;
80 :
81 : // Mutex which controls access to all members below.
82 : Mutex mMutex;
83 :
84 : nsTArray<uint8_t> mBuffer;
85 : bool mHasGrown;
86 : };
87 :
88 : } // End namespace mozilla.
89 :
90 : #endif /* MEMORY_BLOCK_CACHE_H_ */
|