펼쳐두기..
#include <windows.h>
namespace Lock
{
class mutex
{
mutex(const mutex &);
void operator=(const mutex &);
public:
mutex()
{ ::InitializeCriticalSection(&mtx); }
~mutex()
{ ::DeleteCriticalSection(&mtx); }
void lock()
{ ::EnterCriticalSection(&mtx); }
void unlock()
{ ::LeaveCriticalSection(&mtx); }
private:
::CRITICAL_SECTION mtx;
};
class null_mutex
{
null_mutex(const null_mutex &);
void operator=(const null_mutex &);
public:
null_mutex() { }
static void lock() { }
static void unlock() { }
};
template <typename Mutex>
class guard
{
guard(const guard &);
void operator=(const guard &);
public:
explicit guard(Mutex & nmtx)
:mtx(nmtx) { mtx.lock(); }
~guard() { mtx.unlock(); }
private:
Mutex & mtx;
};
typedef mutex default_mutex;
};
펼쳐두기..
#include "boost/static_assert.hpp"
#include "boost/noncopyable.hpp"
#include "Lock.hpp"
namespace Pool
{
template <typename T, typename Mutex = Lock::default_mutex, std::size_t Size = 128>
class Chunk : public boost::noncopyable
{
BOOST_STATIC_CONSTANT(std::size_t, MAX_ALLOCATE_COUNT = 256);
BOOST_STATIC_CONSTANT(std::size_t, BLOCK_SIZE = sizeof(T));
BOOST_STATIC_CONSTANT(std::size_t, ALLOCATE_COUNT = Size);
BOOST_STATIC_ASSERT( Size <= MAX_ALLOCATE_COUNT );
public:
Chunk(void) : availableBlocks_((unsigned char)ALLOCATE_COUNT), firstAvailableBlock_(0)
{
initialize();
}
public:
void initialize()
{
unsigned char* data = data_;
for( unsigned char i = 0; i < availableBlocks_; data += BLOCK_SIZE )
*data = ++i;
}
void* allocate()
{
Lock::guard<Mutex> guard( mutex );
if( availableBlocks_ == 0 ) return NULL;
unsigned char* result = data_ + ( firstAvailableBlock_ * BLOCK_SIZE );
firstAvailableBlock_ = *result;
--availableBlocks_;
return result;
}
void deallocate(void* pointer)
{
assert( data_ <= pointer );
assert( pointer <= data_ + (BLOCK_SIZE * ( ALLOCATE_COUNT - 1 ) ) );
unsigned char* toRelease = static_cast<unsigned char*>( pointer );
assert( (toRelease - data_) % BLOCK_SIZE == 0 );
Lock::guard<Mutex> guard( mutex );
*toRelease = firstAvailableBlock_;
firstAvailableBlock_ = static_cast<unsigned char>( ( toRelease - data_ ) / BLOCK_SIZE );
++availableBlocks_;
}
public:
bool empty()
{
return availableBlocks_ == 0;
}
std::size_t availableSize()
{
return availableBlocks_;
}
bool isAllocate(const void* pointer)
{
return data_ <= pointer && pointer <= data_ + (BLOCK_SIZE * ( ALLOCATE_COUNT - 1 ) );
}
public:
template <typename M, unsigned int S>
bool operator < (const Chunk<T, M, S>& other)
{
return data_ + (BLOCK_SIZE * ( ALLOCATE_COUNT - 1 )) < other.data_;
}
bool operator < (const void* pointer)
{
return data_ + (BLOCK_SIZE * ( ALLOCATE_COUNT - 1 )) < pointer;
}
template <typename M, unsigned int S>
friend bool operator < (const void* pointer, const Chunk<T, M, S>& self)
{
return pointer < self.data_;
}
private:
unsigned char data_[ BLOCK_SIZE * ALLOCATE_COUNT ];
unsigned char availableBlocks_;
unsigned char firstAvailableBlock_;
Mutex mutex_;
};
};
펼쳐두기..
#include <windows.h>
#include "gtest/gtest.h"
#include <vector>
#include "../MemoryPool/Chunk.hpp"
#ifdef _DEBUG
#pragma comment(lib, "gtestd.lib")
#pragma comment(lib, "gtest_maind.lib")
#else
#pragma comment(lib, "gtest.lib")
#pragma comment(lib, "gtest_main.lib")
#endif
class BaseFixture : public testing::Test
{
protected:
virtual void SetUp()
{
startTime_ = ::GetTickCount();
}
virtual void TearDown()
{
HANDLE stdOut = ::GetStdHandle( STD_OUTPUT_HANDLE );
::SetConsoleTextAttribute( stdOut, FOREGROUND_GREEN | FOREGROUND_INTENSITY );
std::cout << "[ RUN TIME ] ";
::SetConsoleTextAttribute( stdOut, FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_GREEN );
std::cout << GetTestName() << " : " << ::GetTickCount() - startTime_ << "ms" << std::endl;
// ::CloseHandle( stdOut );
}
std::string GetTestName()
{
const testing::TestInfo* testInfo = testing::UnitTest::GetInstance()->current_test_info();
std::string testName( testInfo->test_case_name() );
testName.reserve( testName.size() * 3 );
testName.append( "." );
testName.append( testInfo->name() );
return testName;
}
private:
unsigned long startTime_;
};
using namespace Lock;
using namespace Pool;
typedef std::vector<void*> PointerArray;
TEST_F( ChunkTest, Create )
{
Chunk<int> chunk;
EXPECT_EQ( false, chunk.empty() );
EXPECT_EQ( 128, chunk.availableSize() );
}
TEST_F( ChunkTest, Allocate )
{
Chunk<int> chunk;
void* pointer = chunk.allocate();
EXPECT_EQ( false, pointer == NULL );
EXPECT_EQ( true, chunk.isAllocate( pointer ) );
EXPECT_EQ( false, chunk < pointer );
EXPECT_EQ( false, pointer < chunk );
}
TEST_F( ChunkTest, Deallocate )
{
Chunk<int> chunk;
for( int i = 0; i < 100; ++i )
{
void* pointer = chunk.allocate();
EXPECT_EQ( false, pointer == NULL );
EXPECT_EQ( true, chunk.isAllocate( pointer ) );
EXPECT_EQ( false, chunk < pointer );
EXPECT_EQ( false, pointer < chunk );
chunk.deallocate( pointer );
}
EXPECT_EQ( 128, chunk.availableSize() );
PointerArray array;
array.reserve( 128 );
for( int i = 0; i < 128; ++i )
{
void* pointer = chunk.allocate();
EXPECT_EQ( false, pointer == NULL );
EXPECT_EQ( true, chunk.isAllocate( pointer ) );
EXPECT_EQ( false, chunk < pointer );
EXPECT_EQ( false, pointer < chunk );
array.push_back( pointer );
}
EXPECT_EQ( true, chunk.empty() );
EXPECT_EQ( 0, chunk.availableSize() );
PointerArray::iterator pos, end = array.end();
for( pos = array.begin(); pos != end; ++pos )
{
chunk.deallocate( *pos );
}
EXPECT_EQ( 128, chunk.availableSize() );
}
int _tmain(int argc, _TCHAR* argv[])
{
testing::InitGoogleTest( &argc, argv );
return RUN_ALL_TESTS();
}
댓글 없음:
댓글 쓰기