Tue, 06 Jan 2015 21:39:09 +0100
Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #ifndef nsSegmentedBuffer_h__
7 #define nsSegmentedBuffer_h__
9 #include "nsIMemory.h"
11 class nsSegmentedBuffer
12 {
13 public:
14 nsSegmentedBuffer()
15 : mSegmentSize(0), mMaxSize(0),
16 mSegmentArray(nullptr),
17 mSegmentArrayCount(0),
18 mFirstSegmentIndex(0), mLastSegmentIndex(0) {}
20 ~nsSegmentedBuffer() {
21 Empty();
22 }
25 nsresult Init(uint32_t segmentSize, uint32_t maxSize);
27 char* AppendNewSegment(); // pushes at end
29 // returns true if no more segments remain:
30 bool DeleteFirstSegment(); // pops from beginning
32 // returns true if no more segments remain:
33 bool DeleteLastSegment(); // pops from beginning
35 // Call Realloc() on last segment. This is used to reduce memory
36 // consumption when data is not an exact multiple of segment size.
37 bool ReallocLastSegment(size_t newSize);
39 void Empty(); // frees all segments
41 inline uint32_t GetSegmentCount() {
42 if (mFirstSegmentIndex <= mLastSegmentIndex)
43 return mLastSegmentIndex - mFirstSegmentIndex;
44 else
45 return mSegmentArrayCount + mLastSegmentIndex - mFirstSegmentIndex;
46 }
48 inline uint32_t GetSegmentSize() { return mSegmentSize; }
49 inline uint32_t GetMaxSize() { return mMaxSize; }
50 inline uint32_t GetSize() { return GetSegmentCount() * mSegmentSize; }
52 inline char* GetSegment(uint32_t indx) {
53 NS_ASSERTION(indx < GetSegmentCount(), "index out of bounds");
54 int32_t i = ModSegArraySize(mFirstSegmentIndex + (int32_t)indx);
55 return mSegmentArray[i];
56 }
58 protected:
59 inline int32_t ModSegArraySize(int32_t n) {
60 uint32_t result = n & (mSegmentArrayCount - 1);
61 NS_ASSERTION(result == n % mSegmentArrayCount,
62 "non-power-of-2 mSegmentArrayCount");
63 return result;
64 }
66 inline bool IsFull() {
67 return ModSegArraySize(mLastSegmentIndex + 1) == mFirstSegmentIndex;
68 }
70 protected:
71 uint32_t mSegmentSize;
72 uint32_t mMaxSize;
73 char** mSegmentArray;
74 uint32_t mSegmentArrayCount;
75 int32_t mFirstSegmentIndex;
76 int32_t mLastSegmentIndex;
77 };
79 // NS_SEGMENTARRAY_INITIAL_SIZE: This number needs to start out as a
80 // power of 2 given how it gets used. We double the segment array
81 // when we overflow it, and use that fact that it's a power of 2
82 // to compute a fast modulus operation in IsFull.
83 //
84 // 32 segment array entries can accommodate 128k of data if segments
85 // are 4k in size. That seems like a reasonable amount that will avoid
86 // needing to grow the segment array.
87 #define NS_SEGMENTARRAY_INITIAL_COUNT 32
89 #endif // nsSegmentedBuffer_h__