Skip to content

Instantly share code, notes, and snippets.

@arrieta
Created August 18, 2020 21:04
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save arrieta/d1f303d2a6c003685bd600fcac0c033a to your computer and use it in GitHub Desktop.
Save arrieta/d1f303d2a6c003685bd600fcac0c033a to your computer and use it in GitHub Desktop.
Example Polymorphic Memory Resource (std::pmr) Monotonic Buffer Resource
// Example Polymorphic Memory Resource (std::pmr) Monotonic Buffer Resource.
// J. Arrieta, Nabla Zero Labs
//
// * Pre-allocate two buffers, one with space for 2 chars and one with space for 256 chars.
// * Filled pre-allocated buffers with underscores to peek into them later and see where memory was touched.
// * Create two monotonic_buffer_resources, one for each buffer.
// * Notice that the main pool receives a pointer to the "backup" pool.
// * Create a vector of char that uses the main memory resource.
// * Push back on the vector all chars from 'a' to 'z'.
// * See how the first char was allocated using the first memory resource (pool).
// * Subsequent pushbacks relied on the back-up memory resource.
// * The vector contains the correct data.
// * If `backup` is smaller (try), the vector would have started allocating on the heap.
#include <memory_resource>
#include <memory>
#include <vector>
#include <algorithm>
#include <iostream>
#include <numeric>
int main() {
auto buffer_size = 2;
auto backup_size = 256;
auto buffer = std::make_unique<char[]>(buffer_size);
auto backup = std::make_unique<char[]>(backup_size);
std::fill_n(buffer.get(), buffer_size, '_');
std::fill_n(backup.get(), backup_size, '_');
auto upst = std::pmr::monotonic_buffer_resource(backup.get(), backup_size);
auto pool = std::pmr::monotonic_buffer_resource(buffer.get(), buffer_size, &upst);
std::pmr::vector<char> v(&pool);
for (auto c = 'a'; c <= 'z'; ++c) {
v.push_back(c);
}
std::cout << "main buffer contents:\n";
std::for_each_n(buffer.get(), buffer_size, [idx=0] (auto x) mutable { std::cout << (idx++) << " " << x << "\n";});
std::cout << "backup buffer contents:\n";
std::for_each_n(backup.get(), backup_size, [idx=0] (auto x) mutable { std::cout << (idx++) << " " << x << "\n";});
std::cout << "vector contents:\n";
std::for_each(v.begin(), v.end(), [idx=0] (auto x) mutable { std::cout << (idx++) << " " << x << "\n";});
}
@arrieta
Copy link
Author

arrieta commented Aug 18, 2020

Sample output:

main buffer contents:

0 a

1 _

backup buffer contents:

0 a

1 b

2 _

3 _

4 _

5 �

6 �

7 �

8 

9 

10 

11 

12 

13 

14 

15 

16 a

17 b

18 c

19 d

20 _

21 �

22 �

23 �

24 �

25 �

26 �

27 �

28 

29 

30 

31 

32 a

33 b

34 c

35 d

36 e

37 f

38 g

39 h

40 _

41 _

42 _

43 _

44 _

45 _

46 _

47 _

48 _

49 _

50 _

51 _

52 _

53 �

54 �

55 �

56 �

57 �

58 �

59 �

60 

61 

62 

63 

64 a

65 b

66 c

67 d

68 e

69 f

70 g

71 h

72 i

73 j

74 k

75 l

76 m

77 n

78 o

79 p

80 _

81 _

82 _

83 _

84 _

85 �

86 �

87 �

88 �

89 �

90 �

91 �

92 

93 

94 

95 

96 a

97 b

98 c

99 d

100 e

101 f

102 g

103 h

104 i

105 j

106 k

107 l

108 m

109 n

110 o

111 p

112 q

113 r

114 s

115 t

116 u

117 v

118 w

119 x

120 y

121 z

122 _

123 _

124 _

125 _

126 _

127 _

128 _

129 _

130 _

131 _

132 _

133 _

134 _

135 _

136 _

137 _

138 _

139 _

140 _

141 _

142 _

143 _

144 _

145 _

146 _

147 _

148 _

149 �

150 �

151 �

152 �

153 �

154 �

155 �

156 

157 

158 

159 

160 _

161 _

162 _

163 _

164 _

165 _

166 _

167 _

168 _

169 _

170 _

171 _

172 _

173 _

174 _

175 _

176 _

177 _

178 _

179 _

180 _

181 _

182 _

183 _

184 _

185 _

186 _

187 _

188 _

189 _

190 _

191 _

192 _

193 _

194 _

195 _

196 _

197 _

198 _

199 _

200 _

201 _

202 _

203 _

204 _

205 _

206 _

207 _

208 _

209 _

210 _

211 _

212 _

213 _

214 _

215 _

216 _

217 _

218 _

219 _

220 _

221 _

222 _

223 _

224 _

225 _

226 _

227 _

228 _

229 _

230 _

231 _

232 _

233 _

234 _

235 _

236 _

237 _

238 _

239 _

240 _

241 _

242 _

243 _

244 _

245 _

246 _

247 _

248 _

249 _

250 _

251 _

252 _

253 _

254 _

255 _

vector contents:

0 a

1 b

2 c

3 d

4 e

5 f

6 g

7 h

8 i

9 j

10 k

11 l

12 m

13 n

14 o

15 p

16 q

17 r

18 s

19 t

20 u

21 v

22 w

23 x

24 y

25 z

@arrieta
Copy link
Author

arrieta commented Aug 18, 2020

Idea: create a monotonic_buffer_resource backed by a memory map of (essentially) infinite size (all in virtual memory). As a result, we would have a std::pmr::vector with pointer stability (after calling reserve on the maximum size). Virtual memory ensures that memory will be ready to go when needed, but won't actually page it to RAM until then.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment