+ const size_t bufferSize_;
+ std::unique_ptr<unsigned char[]> buffer_;
+ unsigned char* ptr_;
+};
+
+BufferedRandomDevice::BufferedRandomDevice(size_t bufferSize)
+ : bufferSize_(bufferSize),
+ buffer_(new unsigned char[bufferSize]),
+ ptr_(buffer_.get() + bufferSize) { // refill on first use
+}
+
+void BufferedRandomDevice::getSlow(unsigned char* data, size_t size) {
+ DCHECK_GT(size, remaining());
+ if (size >= bufferSize_) {
+ // Just read directly.
+ readRandomDevice(data, size);
+ return;
+ }
+
+ size_t copied = remaining();
+ memcpy(data, ptr_, copied);
+ data += copied;
+ size -= copied;
+
+ // refill
+ readRandomDevice(buffer_.get(), bufferSize_);
+ ptr_ = buffer_.get();
+
+ memcpy(data, ptr_, size);
+ ptr_ += size;
+}
+
+struct RandomTag {};
+
+} // namespace
+
+void Random::secureRandom(void* data, size_t size) {
+ static SingletonThreadLocal<BufferedRandomDevice, RandomTag>
+ bufferedRandomDevice;
+ bufferedRandomDevice.get().get(data, size);
+}
+
+class ThreadLocalPRNG::LocalInstancePRNG {