Refactor random library

This commit is contained in:
Sebastian Messmer 2015-10-22 17:36:03 +02:00
parent d629e14533
commit ca5edb48db
14 changed files with 150 additions and 81 deletions

View File

@ -3,16 +3,14 @@
#define MESSMER_CPPUTILS_DATA_FIXEDSIZEDATA_H_ #define MESSMER_CPPUTILS_DATA_FIXEDSIZEDATA_H_
#include <cryptopp/cryptopp/hex.h> #include <cryptopp/cryptopp/hex.h>
#include <cryptopp/cryptopp/osrng.h>
#include <string> #include <string>
#include <cstring> #include <cstring>
#include "../assert/assert.h" #include "../assert/assert.h"
#include "../random/RandomPool.h"
namespace cpputils { namespace cpputils {
template<unsigned int SIZE> template<unsigned int SIZE>
class FixedSizeData { class FixedSizeData final {
public: public:
//Non-virtual destructor because we want objects to be small //Non-virtual destructor because we want objects to be small
~FixedSizeData() {} ~FixedSizeData() {}
@ -20,8 +18,6 @@ public:
static constexpr unsigned int BINARY_LENGTH = SIZE; static constexpr unsigned int BINARY_LENGTH = SIZE;
static constexpr unsigned int STRING_LENGTH = 2 * BINARY_LENGTH; // Hex encoding static constexpr unsigned int STRING_LENGTH = 2 * BINARY_LENGTH; // Hex encoding
static FixedSizeData<SIZE> CreatePseudoRandom();
static FixedSizeData<SIZE> CreateOSRandom();
//TODO Test Null() //TODO Test Null()
static FixedSizeData<SIZE> Null(); static FixedSizeData<SIZE> Null();
@ -32,6 +28,7 @@ public:
void ToBinary(void *target) const; void ToBinary(void *target) const;
const unsigned char *data() const; const unsigned char *data() const;
unsigned char *data();
private: private:
FixedSizeData() {} FixedSizeData() {}
@ -47,20 +44,6 @@ template<unsigned int SIZE> bool operator!=(const FixedSizeData<SIZE> &lhs, cons
template<unsigned int SIZE> constexpr unsigned int FixedSizeData<SIZE>::BINARY_LENGTH; template<unsigned int SIZE> constexpr unsigned int FixedSizeData<SIZE>::BINARY_LENGTH;
template<unsigned int SIZE> constexpr unsigned int FixedSizeData<SIZE>::STRING_LENGTH; template<unsigned int SIZE> constexpr unsigned int FixedSizeData<SIZE>::STRING_LENGTH;
template<unsigned int SIZE>
FixedSizeData<SIZE> FixedSizeData<SIZE>::CreatePseudoRandom() {
FixedSizeData<SIZE> result;
RandomPool::get(result._data, BINARY_LENGTH);
return result;
}
template<unsigned int SIZE>
FixedSizeData<SIZE> FixedSizeData<SIZE>::CreateOSRandom() {
FixedSizeData<SIZE> result;
CryptoPP::OS_GenerateRandomBlock(true, result._data, BINARY_LENGTH);
return result;
}
template<unsigned int SIZE> template<unsigned int SIZE>
FixedSizeData<SIZE> FixedSizeData<SIZE>::Null() { FixedSizeData<SIZE> FixedSizeData<SIZE>::Null() {
FixedSizeData<SIZE> result; FixedSizeData<SIZE> result;
@ -97,6 +80,11 @@ const unsigned char *FixedSizeData<SIZE>::data() const {
return _data; return _data;
} }
template<unsigned int SIZE>
unsigned char *FixedSizeData<SIZE>::data() {
return const_cast<unsigned char*>(const_cast<const FixedSizeData<SIZE>*>(this)->data());
}
template<unsigned int SIZE> template<unsigned int SIZE>
void FixedSizeData<SIZE>::ToBinary(void *target) const { void FixedSizeData<SIZE>::ToBinary(void *target) const {
std::memcpy(target, _data, BINARY_LENGTH); std::memcpy(target, _data, BINARY_LENGTH);

View File

@ -2,6 +2,9 @@
#ifndef MESSMER_CPPUTILS_MACROS_H_ #ifndef MESSMER_CPPUTILS_MACROS_H_
#define MESSMER_CPPUTILS_MACROS_H_ #define MESSMER_CPPUTILS_MACROS_H_
//TODO If possible, make classes final and destructors non-virtual or delete destructors
//TODO Use DISALLOW_COPY_AND_ASSIGN where possible
/** /**
* Disallow the copy and assignment constructors of a class * Disallow the copy and assignment constructors of a class
*/ */

View File

@ -0,0 +1 @@
#include "OSRandomGenerator.h"

View File

@ -0,0 +1,24 @@
#pragma once
#ifndef MESSMER_CPPUTILS_RANDOM_OSRANDOMGENERATOR_H
#define MESSMER_CPPUTILS_RANDOM_OSRANDOMGENERATOR_H
#include "RandomGenerator.h"
#include <cryptopp/cryptopp/osrng.h>
namespace cpputils {
class OSRandomGenerator final : public RandomGenerator {
public:
OSRandomGenerator();
protected:
void get(void *target, size_t bytes) override;
};
inline OSRandomGenerator::OSRandomGenerator() {}
inline void OSRandomGenerator::get(void *target, size_t bytes) {
CryptoPP::OS_GenerateRandomBlock(true, (byte*)target, bytes);
}
}
#endif

View File

@ -0,0 +1,6 @@
#include "PseudoRandomPool.h"
namespace cpputils {
constexpr size_t PseudoRandomPool::MIN_BUFFER_SIZE;
constexpr size_t PseudoRandomPool::MAX_BUFFER_SIZE;
}

39
random/PseudoRandomPool.h Normal file
View File

@ -0,0 +1,39 @@
#pragma once
#ifndef MESSMER_CPPUTILS_RANDOM_PSEUDORANDOMPOOL_H
#define MESSMER_CPPUTILS_RANDOM_PSEUDORANDOMPOOL_H
#include <boost/thread.hpp>
#include "RandomGenerator.h"
#include "ThreadsafeRandomDataBuffer.h"
#include "RandomGeneratorThread.h"
#include <mutex>
namespace cpputils {
//TODO Test
class PseudoRandomPool final : public RandomGenerator {
public:
PseudoRandomPool();
protected:
void get(void *target, size_t bytes) override;
private:
static constexpr size_t MIN_BUFFER_SIZE = 1*1024*1024; // 1MB
static constexpr size_t MAX_BUFFER_SIZE = 2*1024*1024; // 2MB
ThreadsafeRandomDataBuffer _buffer;
RandomGeneratorThread _refillThread;
DISALLOW_COPY_AND_ASSIGN(PseudoRandomPool);
};
inline void PseudoRandomPool::get(void *target, size_t bytes) {
_buffer.get(target, bytes);
}
inline PseudoRandomPool::PseudoRandomPool(): _buffer(), _refillThread(&_buffer, MIN_BUFFER_SIZE, MAX_BUFFER_SIZE) {
_refillThread.start();
}
}
#endif

5
random/Random.cpp Normal file
View File

@ -0,0 +1,5 @@
#include "Random.h"
namespace cpputils {
std::mutex Random::_mutex;
}

31
random/Random.h Normal file
View File

@ -0,0 +1,31 @@
#pragma once
#ifndef MESSMER_CPPUTILS_RANDOM_RANDOM_H
#define MESSMER_CPPUTILS_RANDOM_RANDOM_H
#include "PseudoRandomPool.h"
#include "OSRandomGenerator.h"
#include "../data/FixedSizeData.h"
#include "../data/Data.h"
#include <mutex>
namespace cpputils {
class Random {
public:
static PseudoRandomPool &PseudoRandom() {
std::unique_lock <std::mutex> lock(_mutex);
static PseudoRandomPool random;
return random;
}
static OSRandomGenerator &OSRandom() {
std::unique_lock <std::mutex> lock(_mutex);
static OSRandomGenerator random;
return random;
}
private:
static std::mutex _mutex;
};
}
#endif

View File

@ -0,0 +1 @@
#include "RandomGenerator.h"

32
random/RandomGenerator.h Normal file
View File

@ -0,0 +1,32 @@
#ifndef MESSMER_CPPUTILS_RANDOM_RANDOMGENERATOR_H
#define MESSMER_CPPUTILS_RANDOM_RANDOMGENERATOR_H
#include "../data/FixedSizeData.h"
#include "../data/Data.h"
namespace cpputils {
class RandomGenerator {
public:
template<size_t SIZE> FixedSizeData<SIZE> getFixedSize();
Data get(size_t size);
protected:
virtual void get(void *target, size_t bytes) = 0;
private:
static std::mutex _mutex;
};
template<size_t SIZE> inline FixedSizeData<SIZE> RandomGenerator::getFixedSize() {
FixedSizeData<SIZE> result = FixedSizeData<SIZE>::Null();
get(result.data(), SIZE);
return result;
}
inline Data RandomGenerator::get(size_t size) {
Data result(size);
get(result.data(), size);
return result;
}
}
#endif

View File

@ -1,8 +0,0 @@
#include "RandomPool.h"
namespace cpputils {
constexpr size_t RandomPool::MIN_BUFFER_SIZE;
constexpr size_t RandomPool::MAX_BUFFER_SIZE;
std::mutex RandomPool::_mutex;
}

View File

@ -1,44 +0,0 @@
#pragma once
#ifndef MESSMER_CPPUTILS_RANDOM_RANDOMPOOL_H
#define MESSMER_CPPUTILS_RANDOM_RANDOMPOOL_H
#include <boost/thread.hpp>
#include "ThreadsafeRandomDataBuffer.h"
#include "RandomGeneratorThread.h"
#include <mutex>
namespace cpputils {
//TODO Test
class RandomPool final {
public:
static void get(void *target, size_t bytes);
private:
static constexpr size_t MIN_BUFFER_SIZE = 1*1024*1024; // 1MB
static constexpr size_t MAX_BUFFER_SIZE = 2*1024*1024; // 2MB
RandomPool();
static RandomPool &singleton();
static std::mutex _mutex;
ThreadsafeRandomDataBuffer _buffer;
RandomGeneratorThread _refillThread;
DISALLOW_COPY_AND_ASSIGN(RandomPool);
};
inline RandomPool &RandomPool::singleton() {
std::unique_lock<std::mutex> lock(_mutex);
static RandomPool singleton;
return singleton;
}
inline void RandomPool::get(void *target, size_t bytes) {
singleton()._buffer.get(target, bytes);
}
inline RandomPool::RandomPool(): _buffer(), _refillThread(&_buffer, MIN_BUFFER_SIZE, MAX_BUFFER_SIZE) {
_refillThread.start();
}
}
#endif

View File

@ -33,15 +33,6 @@ public:
constexpr unsigned int FixedSizeDataTest::SIZE; constexpr unsigned int FixedSizeDataTest::SIZE;
TEST_F(FixedSizeDataTest, CanGenerateRandomDataWithoutCrashing) {
FixedSizeData<SIZE> result = FixedSizeData<SIZE>::CreatePseudoRandom();
}
TEST_F(FixedSizeDataTest, CreatedRandomDatasHaveCorrectLength) {
FixedSizeData<SIZE> data = FixedSizeData<SIZE>::CreatePseudoRandom();
EXPECT_EQ(FixedSizeData<SIZE>::STRING_LENGTH, data.ToString().size());
}
TEST_F(FixedSizeDataTest, EqualsTrue) { TEST_F(FixedSizeDataTest, EqualsTrue) {
FixedSizeData<SIZE> DATA1_1 = FixedSizeData<SIZE>::FromString(DATA1_AS_STRING); FixedSizeData<SIZE> DATA1_1 = FixedSizeData<SIZE>::FromString(DATA1_AS_STRING);
FixedSizeData<SIZE> DATA1_2 = FixedSizeData<SIZE>::FromString(DATA1_AS_STRING); FixedSizeData<SIZE> DATA1_2 = FixedSizeData<SIZE>::FromString(DATA1_AS_STRING);

View File

@ -1,3 +1,3 @@
#include "../../random/RandomPool.h" #include "../../random/Random.h"
// Test the header can be included without needing additional dependencies // Test the header can be included without needing additional dependencies