LosaDev source snapshot 2019
This commit is contained in:
commit
c198676e97
20588 files changed
+8812878
No files matched your search
@@ -0,0 +1,20 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 11.00
|
||||
# Visual Studio 2010
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testQueue", "testQueue\testQueue.vcxproj", "{3C73F9FB-7352-4742-BE16-02B9152B8F82}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Win32 = Debug|Win32
|
||||
Release|Win32 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{3C73F9FB-7352-4742-BE16-02B9152B8F82}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{3C73F9FB-7352-4742-BE16-02B9152B8F82}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{3C73F9FB-7352-4742-BE16-02B9152B8F82}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{3C73F9FB-7352-4742-BE16-02B9152B8F82}.Release|Win32.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
@@ -0,0 +1,31 @@
|
||||
#pragma once
|
||||
|
||||
struct NodeEntry
|
||||
{
|
||||
NodeEntry() : next(nullptr) {}
|
||||
NodeEntry* volatile next;
|
||||
};
|
||||
|
||||
struct NodeData
|
||||
{
|
||||
NodeData() {}
|
||||
NodeEntry m_nodeEntry;
|
||||
};
|
||||
|
||||
class DummyMPSC
|
||||
{
|
||||
public:
|
||||
DummyMPSC() : data(0)
|
||||
{}
|
||||
|
||||
int data;
|
||||
};
|
||||
|
||||
class DummyWF : public NodeData
|
||||
{
|
||||
public:
|
||||
DummyWF() : data(0)
|
||||
{}
|
||||
|
||||
int data;
|
||||
};
|
||||
@@ -0,0 +1,88 @@
|
||||
|
||||
template <class T>
|
||||
struct MemoryElement_
|
||||
{
|
||||
void* data;
|
||||
MemoryElement_* volatile next;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
class MPSCMempooler
|
||||
{
|
||||
public:
|
||||
MPSCMempooler(void)
|
||||
{
|
||||
|
||||
};
|
||||
virtual ~MPSCMempooler(void)
|
||||
{
|
||||
|
||||
};
|
||||
bool Init(int seed)
|
||||
{
|
||||
InitializeCriticalSection(&m_cs);
|
||||
m_head = m_tail = &m_stub;
|
||||
m_stub.next = 0;
|
||||
for(int i=0; i<seed; ++i)
|
||||
{
|
||||
MemoryElement_<T>* element = new MemoryElement_<T>;
|
||||
ZeroMemory(&element->data,sizeof(T));
|
||||
PushNode(element);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
public:
|
||||
bool Push(T* inputData)
|
||||
{
|
||||
MemoryElement_<T>* element= reinterpret_cast<MemoryElement_<T>*>(inputData);
|
||||
element->next = NULL;
|
||||
MemoryElement_<T>* prev =
|
||||
reinterpret_cast<MemoryElement_<T>*>(InterlockedExchangePointer((void**)(&m_head),element));
|
||||
prev->next = element;
|
||||
return true;
|
||||
}
|
||||
T* Pop()
|
||||
{
|
||||
MiniLock(m_cs);
|
||||
MemoryElement_<T>* tmptail = m_tail;
|
||||
MemoryElement_<T>* next = tmptail->next;
|
||||
if (tmptail == &m_stub)
|
||||
{
|
||||
if (NULL == next)
|
||||
return NULL;
|
||||
m_tail = next;
|
||||
tmptail = next;
|
||||
next = next->next;
|
||||
}
|
||||
if (next)
|
||||
{
|
||||
m_tail = next;
|
||||
return reinterpret_cast<T*>(&tmptail->data);
|
||||
}
|
||||
MemoryElement_<T>* tmphead = m_head;
|
||||
if (tmptail != tmphead)
|
||||
return NULL;
|
||||
PushNode(&m_stub);
|
||||
next = tmptail->next;
|
||||
if (next)
|
||||
{
|
||||
m_tail = next;
|
||||
return reinterpret_cast<T*>(&tmptail->data);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
private:
|
||||
void PushNode(MemoryElement_<T>* element)
|
||||
{
|
||||
element->next = NULL;
|
||||
MemoryElement_<T>* prev =
|
||||
reinterpret_cast<MemoryElement_<T>*>(InterlockedExchangePointer((void**)(&m_head),element));
|
||||
prev->next = element;
|
||||
}
|
||||
protected:
|
||||
MemoryElement_<T>* volatile m_head;
|
||||
MemoryElement_<T>* m_tail;
|
||||
MemoryElement_<T> m_stub;
|
||||
CRITICAL_SECTION m_cs;
|
||||
};
|
||||
|
||||
@@ -0,0 +1,149 @@
|
||||
#pragma once
|
||||
|
||||
|
||||
#define _ASSERTC(expr) \
|
||||
{ \
|
||||
if ( !(expr) ) \
|
||||
{ \
|
||||
int* dummy = 0 ; \
|
||||
*dummy = 0xDEADBEEF ; \
|
||||
} \
|
||||
}
|
||||
|
||||
template <class T>
|
||||
class MPMCQueue
|
||||
{
|
||||
public:
|
||||
|
||||
MPMCQueue() : m_headPos(NULL), m_tailPos(NULL) //, m_Elems(NULL)
|
||||
{
|
||||
m_maxSize = 0;
|
||||
m_currentSize = 0;
|
||||
}
|
||||
void Init(int max) //가능한 2의 제곱으로 해주는게 좋음
|
||||
{
|
||||
try
|
||||
{
|
||||
|
||||
// m_maxSize = MakeSize(max);
|
||||
// m_Elems = new T*[m_maxSize];
|
||||
// memset(m_Elems,0,sizeof(T*)*m_maxSize);
|
||||
// m_maxSizeMask = m_maxSize -1;
|
||||
m_maxSize = 1048576;
|
||||
m_maxSizeMask = 1048576 - 1;
|
||||
}
|
||||
catch(std::exception& e)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
int MakeSize(int size)
|
||||
{
|
||||
int nsqrt = 0;
|
||||
int resultval = size;
|
||||
while(resultval != 1)
|
||||
{
|
||||
resultval = resultval/2;
|
||||
nsqrt++;
|
||||
}
|
||||
int rtval = pow((double)2,nsqrt+1);
|
||||
return rtval;
|
||||
|
||||
}
|
||||
void Push(T* newElem)
|
||||
{
|
||||
|
||||
__int64 insertPos = InterlockedIncrement64(&m_tailPos) - 1 ;
|
||||
_ASSERTC( insertPos - m_headPos < m_maxSize) ; ///< overflow
|
||||
m_Elems[insertPos&(m_maxSizeMask)] = newElem ;
|
||||
}
|
||||
T* Pop()
|
||||
{
|
||||
|
||||
T* popVal = (T*) InterlockedExchangePointer((void**)&m_Elems[m_headPos&(m_maxSizeMask)], nullptr) ;
|
||||
if ( popVal != nullptr )
|
||||
InterlockedIncrement64(&m_headPos) ;
|
||||
return popVal ;
|
||||
}
|
||||
|
||||
__int64 GetSize() const
|
||||
{
|
||||
|
||||
return m_tailPos - m_headPos ;
|
||||
}
|
||||
private:
|
||||
int m_currentSize;
|
||||
int m_maxSize;
|
||||
int m_maxSizeMask;
|
||||
//T** m_Elems ;
|
||||
T* m_Elems[1048576];
|
||||
volatile __int64 m_headPos ;
|
||||
volatile __int64 m_tailPos ;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
class ORIMPMCQueue
|
||||
{
|
||||
public:
|
||||
|
||||
template<int E>
|
||||
struct PowerOfTwo
|
||||
{
|
||||
enum { value = 2 * PowerOfTwo<E-1>::value } ;
|
||||
} ;
|
||||
|
||||
template<>
|
||||
struct PowerOfTwo<0>
|
||||
{
|
||||
enum { value = 1 } ;
|
||||
} ;
|
||||
|
||||
enum
|
||||
{
|
||||
/// 큐의 크기 설정: 반드시 2의 승수로 해야 한다.
|
||||
QUEUE_MAX_SIZE = PowerOfTwo<16>::value,
|
||||
QUEUE_SIZE_MASK = QUEUE_MAX_SIZE - 1
|
||||
} ;
|
||||
|
||||
ORIMPMCQueue() : mHeadPos(0), mTailPos(0)
|
||||
{
|
||||
memset(mElem, 0, sizeof(mElem)) ;
|
||||
}
|
||||
|
||||
void Push(T* newElem)
|
||||
{
|
||||
__int64 insertPos = InterlockedIncrement64(&mTailPos) - 1 ;
|
||||
_ASSERTC(insertPos - mHeadPos < QUEUE_MAX_SIZE)
|
||||
if(insertPos - mHeadPos < QUEUE_MAX_SIZE)///< overflow
|
||||
{
|
||||
printf("QQQQQQQQQQQQQ\n");
|
||||
}
|
||||
|
||||
mElem[insertPos&QUEUE_SIZE_MASK] = newElem ;
|
||||
}
|
||||
|
||||
T* Pop()
|
||||
{
|
||||
T* popVal = (T*) InterlockedExchangePointer((void**)&mElem[mHeadPos&QUEUE_SIZE_MASK], nullptr) ;
|
||||
|
||||
if ( popVal != nullptr )
|
||||
InterlockedIncrement64(&mHeadPos) ;
|
||||
|
||||
return popVal ;
|
||||
}
|
||||
|
||||
__int64 GetSize() const
|
||||
{
|
||||
return mTailPos - mHeadPos ;
|
||||
}
|
||||
|
||||
|
||||
|
||||
private:
|
||||
|
||||
T* mElem[QUEUE_MAX_SIZE] ;
|
||||
volatile __int64 mHeadPos ;
|
||||
volatile __int64 mTailPos ;
|
||||
|
||||
} ;
|
||||
@@ -0,0 +1,88 @@
|
||||
|
||||
template <class T>
|
||||
struct MemoryElement_
|
||||
{
|
||||
void* data;
|
||||
MemoryElement_* volatile next;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
class MPSCMempooler
|
||||
{
|
||||
public:
|
||||
MPSCMempooler(void)
|
||||
{
|
||||
|
||||
};
|
||||
virtual ~MPSCMempooler(void)
|
||||
{
|
||||
|
||||
};
|
||||
bool Init(int seed)
|
||||
{
|
||||
InitializeCriticalSection(&m_cs);
|
||||
m_head = m_tail = &m_stub;
|
||||
m_stub.next = 0;
|
||||
for(int i=0; i<seed; ++i)
|
||||
{
|
||||
MemoryElement_<T>* element = new MemoryElement_<T>;
|
||||
ZeroMemory(&element->data,sizeof(T));
|
||||
PushNode(element);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
public:
|
||||
bool Push(T* inputData)
|
||||
{
|
||||
MemoryElement_<T>* element= reinterpret_cast<MemoryElement_<T>*>(inputData);
|
||||
element->next = NULL;
|
||||
MemoryElement_<T>* prev =
|
||||
reinterpret_cast<MemoryElement_<T>*>(InterlockedExchangePointer((void**)(&m_head),element));
|
||||
prev->next = element;
|
||||
return true;
|
||||
}
|
||||
T* Pop()
|
||||
{
|
||||
MiniLock(m_cs);
|
||||
MemoryElement_<T>* tmptail = m_tail;
|
||||
MemoryElement_<T>* next = tmptail->next;
|
||||
if (tmptail == &m_stub)
|
||||
{
|
||||
if (NULL == next)
|
||||
return NULL;
|
||||
m_tail = next;
|
||||
tmptail = next;
|
||||
next = next->next;
|
||||
}
|
||||
if (next)
|
||||
{
|
||||
m_tail = next;
|
||||
return reinterpret_cast<T*>(&tmptail->data);
|
||||
}
|
||||
MemoryElement_<T>* tmphead = m_head;
|
||||
if (tmptail != tmphead)
|
||||
return NULL;
|
||||
PushNode(&m_stub);
|
||||
next = tmptail->next;
|
||||
if (next)
|
||||
{
|
||||
m_tail = next;
|
||||
return reinterpret_cast<T*>(&tmptail->data);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
private:
|
||||
void PushNode(MemoryElement_<T>* element)
|
||||
{
|
||||
element->next = NULL;
|
||||
MemoryElement_<T>* prev =
|
||||
reinterpret_cast<MemoryElement_<T>*>(InterlockedExchangePointer((void**)(&m_head),element));
|
||||
prev->next = element;
|
||||
}
|
||||
protected:
|
||||
MemoryElement_<T>* volatile m_head;
|
||||
MemoryElement_<T>* m_tail;
|
||||
MemoryElement_<T> m_stub;
|
||||
CRITICAL_SECTION m_cs;
|
||||
};
|
||||
|
||||
@@ -0,0 +1,159 @@
|
||||
#pragma once
|
||||
|
||||
#include <deque>
|
||||
#include <list>
|
||||
#include "cCriticalSection.h"
|
||||
|
||||
|
||||
template <class Type>
|
||||
class MPMC_MemPooler
|
||||
{
|
||||
public:
|
||||
MPMC_MemPooler(int numofBlock=0, int maximumBlock=0, BOOL threadSafe=TRUE) :
|
||||
m_allocCount(32),
|
||||
m_numofBlock(0),
|
||||
m_maximumBlock(maximumBlock),
|
||||
m_threadSafe(threadSafe)
|
||||
{
|
||||
m_blockSize = sizeof(Type);
|
||||
|
||||
Create(numofBlock);
|
||||
}
|
||||
~MPMC_MemPooler()
|
||||
{
|
||||
Destroy();
|
||||
}
|
||||
|
||||
public:
|
||||
void CreatePool(const int numofBlock, const int maximumBlock=0, BOOL threadSafe=TRUE)
|
||||
{
|
||||
m_numofBlock = 0;
|
||||
m_maximumBlock = maximumBlock;
|
||||
m_threadSafe = threadSafe;
|
||||
|
||||
Create(numofBlock);
|
||||
}
|
||||
void DestroyPool()
|
||||
{
|
||||
Destroy();
|
||||
}
|
||||
|
||||
public:
|
||||
Type* Pop()
|
||||
{
|
||||
return Get();
|
||||
}
|
||||
|
||||
Type* Remove()
|
||||
{
|
||||
if(m_memPooler.empty())
|
||||
return (NULL);
|
||||
|
||||
return Get();
|
||||
}
|
||||
|
||||
void Push(Type* block)
|
||||
{
|
||||
|
||||
if(block == NULL)
|
||||
return;
|
||||
mpmc_queue::node_t * node = CONTAINING_RECORD(block,mpmc_queue::node_t,data);
|
||||
m_memPooler.enqueue(node);
|
||||
|
||||
}
|
||||
|
||||
int GetCount() { return m_memPooler.size(); }
|
||||
int GetTotalCount() { return m_numofBlock; }
|
||||
|
||||
protected:
|
||||
void Create(const int numofBlock)
|
||||
{
|
||||
if(numofBlock <= 0) return;
|
||||
|
||||
BYTE *memBlock = new BYTE[m_blockSize * numofBlock];
|
||||
if(memBlock)
|
||||
{
|
||||
Type *block;
|
||||
int nSegment = 0;
|
||||
|
||||
for(int i = 0 ; i < numofBlock ; i++)
|
||||
{
|
||||
block = reinterpret_cast<Type*>(reinterpret_cast<DWORD>(memBlock) + nSegment);
|
||||
new (block) Type;
|
||||
nSegment += m_blockSize;
|
||||
mpmc_queue::node_t* node = new mpmc_queue::node_t;
|
||||
node->data = block;
|
||||
m_memPooler.enqueue(node);
|
||||
}
|
||||
m_numofBlock += numofBlock;
|
||||
|
||||
m_memBlocks.push_back(memBlock);
|
||||
}
|
||||
}
|
||||
|
||||
void Destroy()
|
||||
{
|
||||
Lock();
|
||||
for(std::list<BYTE*>::iterator it = m_memBlocks.begin() ; it != m_memBlocks.end() ; ++it)
|
||||
{
|
||||
BYTE* memBlock = *it;
|
||||
if(memBlock)
|
||||
{
|
||||
delete []memBlock;
|
||||
}
|
||||
}
|
||||
m_memBlocks.clear();
|
||||
Unlock();
|
||||
}
|
||||
|
||||
Type* Get()
|
||||
{
|
||||
Type* block = NULL;
|
||||
|
||||
if(!m_memPooler.empty())
|
||||
{
|
||||
mpmc_queue::node_t* node = NULL;
|
||||
node = m_memPooler.dequeue();
|
||||
block = node->data;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
if(m_numofBlock < m_maximumBlock)
|
||||
{
|
||||
int allocCount = m_maximumBlock - m_numofBlock;
|
||||
(allocCount > m_allocCount) ? Create(m_allocCount) : Create(allocCount);
|
||||
mpmc_queue::node_t* node = NULL;
|
||||
node = m_memPooler.dequeue();
|
||||
block = node->data;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return (block);
|
||||
}
|
||||
|
||||
void Lock()
|
||||
{
|
||||
if(m_threadSafe) m_cs.Lock();
|
||||
}
|
||||
|
||||
void Unlock()
|
||||
{
|
||||
if(m_threadSafe) m_cs.Unlock();
|
||||
}
|
||||
|
||||
protected:
|
||||
int m_allocCount;
|
||||
int m_numofBlock;
|
||||
int m_maximumBlock;
|
||||
int m_blockSize;
|
||||
BOOL m_threadSafe;
|
||||
//std::deque<Type*> m_memPooler;
|
||||
mpmc_queue m_memPooler;
|
||||
std::list<BYTE*> m_memBlocks;
|
||||
|
||||
// For thread-safe.
|
||||
cCriticalSection m_cs;
|
||||
};
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
#include "stdafx.h"
|
||||
#include "MPSCQueue.h"
|
||||
|
||||
|
||||
|
||||
WFQueue::WFQueue(void)
|
||||
{
|
||||
Init();
|
||||
}
|
||||
|
||||
WFQueue::~WFQueue(void)
|
||||
{
|
||||
}
|
||||
|
||||
bool WFQueue::Init()
|
||||
{
|
||||
m_head = m_tail = &m_stub;
|
||||
m_stub.next = NULL;
|
||||
m_count = 0;
|
||||
|
||||
m_offset = reinterpret_cast<__int64>( &((reinterpret_cast<NodeData*>(0))->m_nodeEntry) ) ;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WFQueue::Enqueue( NodeData* node )
|
||||
{
|
||||
NodeEntry* prev = reinterpret_cast<NodeEntry*>(InterlockedExchangePointer((void*)(&m_head), (void*)(&node->m_nodeEntry)));
|
||||
prev->next = &(node->m_nodeEntry);
|
||||
InterlockedIncrement(&m_count);
|
||||
return true;
|
||||
}
|
||||
|
||||
void WFQueue::PushNode( NodeEntry* element )
|
||||
{
|
||||
element->next = NULL;
|
||||
NodeEntry* prev = reinterpret_cast<NodeEntry*>(InterlockedExchangePointer((void*)(&m_head), element));
|
||||
prev->next = element;
|
||||
}
|
||||
|
||||
NodeEntry* WFQueue::Dequeue()
|
||||
{
|
||||
NodeEntry* tail = m_tail;
|
||||
NodeEntry* next = tail->next;
|
||||
if (tail == &m_stub)
|
||||
{
|
||||
if (NULL == next)
|
||||
return NULL;
|
||||
m_tail = next;
|
||||
tail = next;
|
||||
next = next->next;
|
||||
}
|
||||
if (next)
|
||||
{
|
||||
m_tail = next;
|
||||
InterlockedDecrement(&m_count);
|
||||
NodeEntry* node = reinterpret_cast<NodeEntry*>(reinterpret_cast<__int64>(tail) - m_offset);
|
||||
return (node);
|
||||
}
|
||||
|
||||
NodeEntry* head = m_head;
|
||||
if (tail != head)
|
||||
return NULL;
|
||||
|
||||
PushNode(&m_stub);
|
||||
|
||||
next = tail->next;
|
||||
if (next)
|
||||
{
|
||||
m_tail = next;
|
||||
InterlockedDecrement(&m_count);
|
||||
NodeEntry* node = reinterpret_cast<NodeEntry*>(reinterpret_cast<__int64>(tail) - m_offset);
|
||||
return (node);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
#pragma once
|
||||
|
||||
#include "DATA.h"
|
||||
|
||||
class WFQueue
|
||||
{
|
||||
public:
|
||||
WFQueue(void);
|
||||
virtual ~WFQueue(void);
|
||||
|
||||
bool Init();
|
||||
|
||||
public:
|
||||
bool Enqueue( NodeData *node );
|
||||
NodeEntry* Dequeue();
|
||||
|
||||
int GetSize() { return m_count;}
|
||||
|
||||
protected:
|
||||
void PushNode(NodeEntry* element);
|
||||
|
||||
private:
|
||||
NodeEntry* volatile m_head;
|
||||
NodeEntry* m_tail;
|
||||
NodeEntry m_stub;
|
||||
long m_count;
|
||||
__int64 m_offset;
|
||||
};
|
||||
|
||||
@@ -0,0 +1,160 @@
|
||||
#pragma once
|
||||
|
||||
#include <deque>
|
||||
#include <list>
|
||||
#include "cCriticalSection.h"
|
||||
|
||||
|
||||
template <class Type>
|
||||
class MemPooler
|
||||
{
|
||||
public:
|
||||
MemPooler(int numofBlock=0, int maximumBlock=0, BOOL threadSafe=TRUE) :
|
||||
m_allocCount(32),
|
||||
m_numofBlock(0),
|
||||
m_maximumBlock(maximumBlock),
|
||||
m_threadSafe(threadSafe)
|
||||
{
|
||||
m_blockSize = sizeof(Type);
|
||||
|
||||
Create(numofBlock);
|
||||
}
|
||||
~MemPooler()
|
||||
{
|
||||
Destroy();
|
||||
}
|
||||
|
||||
public:
|
||||
void CreatePool(const int numofBlock, const int maximumBlock=0, BOOL threadSafe=TRUE)
|
||||
{
|
||||
m_numofBlock = 0;
|
||||
m_maximumBlock = maximumBlock;
|
||||
m_threadSafe = threadSafe;
|
||||
|
||||
Create(numofBlock);
|
||||
}
|
||||
void DestroyPool()
|
||||
{
|
||||
Destroy();
|
||||
}
|
||||
|
||||
public:
|
||||
Type* Pop()
|
||||
{
|
||||
return Get();
|
||||
}
|
||||
|
||||
Type* Remove()
|
||||
{
|
||||
if(m_memPooler.empty())
|
||||
return (NULL);
|
||||
|
||||
return Get();
|
||||
}
|
||||
|
||||
void Push(Type* block)
|
||||
{
|
||||
Lock();
|
||||
m_memPooler.push_back(block);
|
||||
Unlock();
|
||||
}
|
||||
|
||||
void Push_Front(Type* block)
|
||||
{
|
||||
Lock();
|
||||
m_memPooler.push_front(block);
|
||||
Unlock();
|
||||
}
|
||||
|
||||
int GetCount() { return m_memPooler.size(); }
|
||||
int GetTotalCount() { return m_numofBlock; }
|
||||
|
||||
protected:
|
||||
void Create(const int numofBlock)
|
||||
{
|
||||
if(numofBlock <= 0) return;
|
||||
|
||||
BYTE *memBlock = new BYTE[m_blockSize * numofBlock];
|
||||
if(memBlock)
|
||||
{
|
||||
Type *block;
|
||||
int nSegment = 0;
|
||||
|
||||
for(int i = 0 ; i < numofBlock ; i++)
|
||||
{
|
||||
block = reinterpret_cast<Type*>(reinterpret_cast<DWORD>(memBlock) + nSegment);
|
||||
new (block) Type;
|
||||
|
||||
nSegment += m_blockSize;
|
||||
m_memPooler.push_back(block);
|
||||
}
|
||||
m_numofBlock += numofBlock;
|
||||
|
||||
m_memBlocks.push_back(memBlock);
|
||||
}
|
||||
}
|
||||
|
||||
void Destroy()
|
||||
{
|
||||
Lock();
|
||||
for(std::list<BYTE*>::iterator it = m_memBlocks.begin() ; it != m_memBlocks.end() ; ++it)
|
||||
{
|
||||
BYTE* memBlock = *it;
|
||||
if(memBlock)
|
||||
{
|
||||
delete []memBlock;
|
||||
}
|
||||
}
|
||||
m_memBlocks.clear();
|
||||
Unlock();
|
||||
}
|
||||
|
||||
Type* Get()
|
||||
{
|
||||
Type* block = NULL;
|
||||
Lock();
|
||||
if(!m_memPooler.empty())
|
||||
{
|
||||
block = m_memPooler.front();
|
||||
if(block)
|
||||
m_memPooler.pop_front();
|
||||
}
|
||||
else
|
||||
{
|
||||
if(m_numofBlock < m_maximumBlock)
|
||||
{
|
||||
int allocCount = m_maximumBlock - m_numofBlock;
|
||||
(allocCount > m_allocCount) ? Create(m_allocCount) : Create(allocCount);
|
||||
|
||||
block = m_memPooler.front();
|
||||
if(block)
|
||||
m_memPooler.pop_front();
|
||||
}
|
||||
}
|
||||
Unlock();
|
||||
return (block);
|
||||
}
|
||||
|
||||
void Lock()
|
||||
{
|
||||
if(m_threadSafe) m_cs.Lock();
|
||||
}
|
||||
|
||||
void Unlock()
|
||||
{
|
||||
if(m_threadSafe) m_cs.Unlock();
|
||||
}
|
||||
|
||||
protected:
|
||||
int m_allocCount;
|
||||
int m_numofBlock;
|
||||
int m_maximumBlock;
|
||||
int m_blockSize;
|
||||
BOOL m_threadSafe;
|
||||
std::deque<Type*> m_memPooler;
|
||||
std::list<BYTE*> m_memBlocks;
|
||||
|
||||
// For thread-safe.
|
||||
cCriticalSection m_cs;
|
||||
};
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
========================================================================
|
||||
콘솔 응용 프로그램 : testQueue 프로젝트 개요
|
||||
========================================================================
|
||||
|
||||
응용 프로그램 마법사에서 이 testQueue 응용 프로그램을 만들었습니다.
|
||||
|
||||
testQueue 응용 프로그램을 구성하는 각 파일에 대한
|
||||
요약 설명이 포함되어 있습니다.
|
||||
|
||||
|
||||
testQueue.vcxproj
|
||||
응용 프로그램 마법사를 사용하여 생성한 VC++ 프로젝트의 기본 프로젝트 파일입니다.
|
||||
파일을 생성한 Visual C++ 버전에 대한 정보와 응용 프로그램 마법사를 사용하여 선택한 플랫폼,
|
||||
구성 및 프로젝트 기능에 대한 정보가 포함되어 있습니다.
|
||||
|
||||
testQueue.vcxproj.filters
|
||||
응용 프로그램 마법사를 사용하여 생성된 VC++ 프로젝트의 필터 파일입니다.
|
||||
이 파일에는 프로젝트의 파일과 필터 간의 연결 정보가 들어 있습니다.
|
||||
이러한 연결은 특정 노드에서 유사한 확장명으로 그룹화된 파일을 표시하기 위해 IDE에서
|
||||
사용됩니다. 예를 들어 ".cpp" 파일은 "소스 파일" 필터와 연결되어 있습니다.
|
||||
|
||||
testQueue.cpp
|
||||
기본 응용 프로그램 소스 파일입니다.
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
기타 표준 파일:
|
||||
|
||||
StdAfx.h, StdAfx.cpp
|
||||
이 파일은 미리 컴파일된 헤더(PCH) 파일 testQueue.pch와
|
||||
미리 컴파일된 형식(PCT) 파일 StdAfx.obj를 빌드하는 데 사용됩니다.
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
기타 참고:
|
||||
|
||||
응용 프로그램 마법사에서 사용하는 "TODO:" 주석은 사용자가 추가하거나 사용자 지정해야 하는
|
||||
소스 코드 부분을 나타냅니다.
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
@@ -0,0 +1,96 @@
|
||||
#include "stdafx.h"
|
||||
#include "TMPSCQueue.h"
|
||||
|
||||
|
||||
|
||||
TMPSCQueue::TMPSCQueue(void)
|
||||
{
|
||||
m_timeout = 0;
|
||||
}
|
||||
|
||||
TMPSCQueue::~TMPSCQueue(void)
|
||||
{
|
||||
}
|
||||
|
||||
bool TMPSCQueue::Init( int seed, int timeout )
|
||||
{
|
||||
m_head = m_tail = &m_stub;
|
||||
m_stub.next = NULL;
|
||||
m_pool.CreatePool(seed/2,seed);
|
||||
m_count = 0;
|
||||
m_timeout = timeout;
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
bool TMPSCQueue::Enqueue( DWORD inputData )
|
||||
{
|
||||
TQueueElement_* element= m_pool.Pop();
|
||||
if(element == NULL)
|
||||
return false;
|
||||
element->next = NULL;
|
||||
element->data = inputData;
|
||||
TQueueElement_* prev =
|
||||
reinterpret_cast<TQueueElement_*>(InterlockedExchangePointer((void**)(&m_head),element));
|
||||
prev->next = element;
|
||||
InterlockedIncrement(&m_count);
|
||||
return true;
|
||||
}
|
||||
|
||||
void TMPSCQueue::PushNode( TQueueElement_* element )
|
||||
{
|
||||
element->next = NULL;
|
||||
TQueueElement_* prev =
|
||||
reinterpret_cast<TQueueElement_*>(InterlockedExchangePointer((void**)(&m_head),element));
|
||||
prev->next = element;
|
||||
}
|
||||
|
||||
LPDWORD TMPSCQueue::Dequeue()
|
||||
{
|
||||
TQueueElement_* tmptail = m_tail;
|
||||
TQueueElement_* next = tmptail->next;
|
||||
if (tmptail == &m_stub)
|
||||
{
|
||||
if (NULL == next)
|
||||
return NULL;
|
||||
m_tail = next;
|
||||
tmptail = next;
|
||||
next = next->next;
|
||||
}
|
||||
if (next)
|
||||
{
|
||||
m_tail = next;
|
||||
InterlockedDecrement(&m_count);
|
||||
DWORD rtval = tmptail->data;
|
||||
m_pool.Push(tmptail);
|
||||
return reinterpret_cast<LPDWORD>(rtval);
|
||||
}
|
||||
TQueueElement_* tmphead = m_head;
|
||||
if (tmptail != tmphead)
|
||||
return NULL;
|
||||
PushNode(&m_stub);
|
||||
next = tmptail->next;
|
||||
if (next)
|
||||
{
|
||||
m_tail = next;
|
||||
InterlockedDecrement(&m_count);
|
||||
LPDWORD rtval = reinterpret_cast<LPDWORD>(tmptail->data);
|
||||
m_pool.Push(tmptail);
|
||||
return reinterpret_cast<LPDWORD>(rtval);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
LPDWORD TMPSCQueue::WaitDequeue()
|
||||
{
|
||||
LPDWORD data;
|
||||
while ((data = Dequeue()) == NULL)
|
||||
Sleep (m_timeout); // wait for nonbusy result
|
||||
return data;
|
||||
}
|
||||
|
||||
void TMPSCQueue::ReleaseMemoryPool()
|
||||
{
|
||||
m_pool.DestroyPool();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
#pragma once
|
||||
|
||||
#include "MemPooler.h"
|
||||
|
||||
struct TQueueElement_
|
||||
{
|
||||
DWORD data;
|
||||
TQueueElement_* volatile next;
|
||||
};
|
||||
|
||||
class TMPSCQueue
|
||||
{
|
||||
public:
|
||||
TMPSCQueue(void);
|
||||
virtual ~TMPSCQueue(void);
|
||||
bool Init(int seed,int timeout = 0);
|
||||
void ReleaseMemoryPool();
|
||||
public:
|
||||
bool Enqueue(DWORD inputData);
|
||||
LPDWORD Dequeue();
|
||||
LPDWORD WaitDequeue();
|
||||
int GetSize() { return m_count;}
|
||||
|
||||
protected:
|
||||
void PushNode(TQueueElement_* element);
|
||||
|
||||
private:
|
||||
TQueueElement_* volatile m_head;
|
||||
TQueueElement_* m_tail;
|
||||
TQueueElement_ m_stub;
|
||||
MemPooler<TQueueElement_> m_pool;
|
||||
long m_count;
|
||||
int m_timeout;
|
||||
|
||||
};
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
#include "StdAfx.h"
|
||||
#include "TestCase.h"
|
||||
|
||||
|
||||
TestCase::TestCase(void)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
TestCase::~TestCase(void)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
#pragma once
|
||||
|
||||
#include "DATA.h"
|
||||
|
||||
class TestCase
|
||||
{
|
||||
public:
|
||||
TestCase(void);
|
||||
virtual ~TestCase(void);
|
||||
|
||||
virtual void Run() = 0;
|
||||
|
||||
template <class T>
|
||||
int unique_check(std::pair<T,bool> &result)
|
||||
{
|
||||
int rtval = 0;;
|
||||
if(result.second == true)
|
||||
rtval = 0;
|
||||
else
|
||||
rtval = -1;
|
||||
return rtval;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -0,0 +1,107 @@
|
||||
#include "StdAfx.h"
|
||||
#include "TestIOCPQueue.h"
|
||||
#include <set>
|
||||
#include <iostream>
|
||||
|
||||
TestIOCPQueue::TestIOCPQueue(void)
|
||||
{
|
||||
Startup(1);
|
||||
}
|
||||
|
||||
|
||||
TestIOCPQueue::~TestIOCPQueue(void)
|
||||
{
|
||||
m_nodes.DestroyPool();
|
||||
}
|
||||
|
||||
void TestIOCPQueue::Start()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void TestIOCPQueue::Run()
|
||||
{
|
||||
int tmpval;
|
||||
|
||||
// flush(stdin);
|
||||
printf("\nQueCount : ");
|
||||
std::cin >> tmpval;
|
||||
m_nodes.CreatePool(tmpval/2,tmpval);
|
||||
|
||||
int quecount = tmpval;
|
||||
|
||||
printf("Thread Count : ");
|
||||
scanf("%d",&tmpval);
|
||||
std::vector<boost::thread*> m_threads;
|
||||
for(int i=0; i<tmpval; ++i)
|
||||
{
|
||||
m_threads.push_back(new boost::thread(&TestIOCPQueue::Input,this,(quecount/tmpval)*i,quecount/tmpval));
|
||||
}
|
||||
|
||||
//for(int i=0; i<m_threads.size(); ++i)
|
||||
// m_threads[i]->join();
|
||||
|
||||
boost::thread popthread(&TestIOCPQueue::Pop,this,quecount);
|
||||
popthread.join();
|
||||
Cleanup();
|
||||
|
||||
}
|
||||
|
||||
|
||||
double TestIOCPQueue::Input( int i, int maxcount )
|
||||
{
|
||||
DWORD tmp =0;
|
||||
boost::timer el;
|
||||
int index = 0;
|
||||
int tmpval = i;
|
||||
for(index; index<maxcount; ++index)
|
||||
{
|
||||
i++;
|
||||
NodeData* node = reinterpret_cast<NodeData*>(m_nodes.Pop());
|
||||
node->data = reinterpret_cast<void*>(i);
|
||||
|
||||
Enqueue((DWORD)node,tmp);
|
||||
|
||||
}
|
||||
printf("InputThread(%d) %0.4f\n",tmpval,el.elapsed());
|
||||
return 0;
|
||||
|
||||
|
||||
}
|
||||
|
||||
void TestIOCPQueue::Pop(int quecount)
|
||||
{
|
||||
std::set<int> testvalues;
|
||||
|
||||
NodeData* popval = NULL;
|
||||
int popcount = 0;
|
||||
boost::timer el;
|
||||
while(1)
|
||||
{
|
||||
|
||||
popval = reinterpret_cast<NodeData*>(Dequeue());
|
||||
if(popval == NULL)
|
||||
break;
|
||||
// printf("%d\n",popval);
|
||||
if(unique_check(testvalues.insert((int)popval->data)) == -1)
|
||||
{
|
||||
printf("Áߺ¹µ¥ÀÌÅÍ \n");
|
||||
break;
|
||||
}
|
||||
if(testvalues.size() > 5000000)
|
||||
{
|
||||
// printf("D:%d",popcount);
|
||||
testvalues.clear();
|
||||
}
|
||||
popcount++;
|
||||
m_nodes.Push((NodeData*)popval);
|
||||
if(popcount >= quecount)
|
||||
{
|
||||
printf("¿Ï·á\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
printf("Finished popCount :[%d] time: [%0.4f]\n",popcount,el.elapsed());
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
#pragma once
|
||||
|
||||
#include "TestCase.h"
|
||||
|
||||
struct NodeData
|
||||
{
|
||||
void* data;
|
||||
NodeData* volatile next;
|
||||
};
|
||||
class TestIOCPQueue : public TestCase, cIocpQueue
|
||||
{
|
||||
public:
|
||||
TestIOCPQueue(void);
|
||||
virtual ~TestIOCPQueue(void);
|
||||
virtual void Start();
|
||||
virtual void Run();
|
||||
|
||||
public:
|
||||
double Input(int i, int maxcount);
|
||||
void Pop(int quecount);
|
||||
private:
|
||||
MemPooler<NodeData> m_nodes;
|
||||
|
||||
};
|
||||
|
||||
@@ -0,0 +1,112 @@
|
||||
#include "StdAfx.h"
|
||||
#include "TestMPMCMemoryPool.h"
|
||||
#include <boost/timer.hpp>
|
||||
#define MAXCOUNT 1000000
|
||||
|
||||
TestMPMCMemoryPool::TestMPMCMemoryPool(void)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
TestMPMCMemoryPool::~TestMPMCMemoryPool(void)
|
||||
{
|
||||
}
|
||||
|
||||
void TestMPMCMemoryPool::Run()
|
||||
{
|
||||
m_memPooler.CreatePool(MAXCOUNT/2,MAXCOUNT);
|
||||
test_* tt = new test_;
|
||||
m_memPooler.CreatePush(tt);
|
||||
m_orimemPooler.CreatePool(MAXCOUNT/2,MAXCOUNT);
|
||||
boost::thread newmemt(&TestMPMCMemoryPool::TestFunc,this,0,0);
|
||||
boost::thread orimemt(&TestMPMCMemoryPool::oriTestFunc,this,0,0);
|
||||
newmemt.join();
|
||||
orimemt.join();
|
||||
|
||||
|
||||
}
|
||||
|
||||
void TestMPMCMemoryPool::TestFunc( int i, int maxcount )
|
||||
{
|
||||
boost::timer el;
|
||||
std::vector<test_*> tests;
|
||||
for(int i=0; i<MAXCOUNT; ++i)
|
||||
{
|
||||
test_* ptest = m_memPooler.Pop();
|
||||
ptest->i = i;
|
||||
tests.push_back(ptest);
|
||||
}
|
||||
for(int i=0; i<tests.size(); ++i)
|
||||
{
|
||||
m_memPooler.Push(tests[i]);
|
||||
}
|
||||
printf("New Mem Finsith[%d]:%0.3f\n",tests.size(),el.elapsed());
|
||||
std::vector<boost::thread*> threads;
|
||||
for(int i=0; i<8; ++i)
|
||||
{
|
||||
threads.push_back(new boost::thread(&TestMPMCMemoryPool::PopFunc,this,i));
|
||||
}
|
||||
for(int i=0; i<threads.size(); ++i)
|
||||
{
|
||||
threads[i]->join();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
void TestMPMCMemoryPool::oriTestFunc( int i, int maxcount )
|
||||
{
|
||||
|
||||
boost::timer el;
|
||||
std::vector<test_*> tests;
|
||||
for(int i=0; i<MAXCOUNT; ++i)
|
||||
{
|
||||
test_* ptest = m_orimemPooler.Pop();
|
||||
ptest->i = i;
|
||||
tests.push_back(ptest);
|
||||
}
|
||||
for(int i=0; i<tests.size(); ++i)
|
||||
{
|
||||
m_orimemPooler.Push(tests[i]);
|
||||
}
|
||||
printf("\nOriMem Finsith[%d]:%0.3f\n",tests.size(),el.elapsed());
|
||||
std::vector<boost::thread*> threads;
|
||||
for(int i=0; i<8; ++i)
|
||||
{
|
||||
threads.push_back(new boost::thread(&TestMPMCMemoryPool::oriPopFunc,this,i));
|
||||
}
|
||||
for(int i=0; i<threads.size(); ++i)
|
||||
{
|
||||
threads[i]->join();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
#define POPCOUNT 500000
|
||||
|
||||
void TestMPMCMemoryPool::PopFunc( int i )
|
||||
{
|
||||
boost::timer el;
|
||||
for(int j = 0; j<POPCOUNT;++j)
|
||||
{
|
||||
test_* ptest = m_memPooler.Pop();
|
||||
if(j% 300000 == 1)
|
||||
printf("n:%d ",ptest->i);
|
||||
m_memPooler.Push(ptest);
|
||||
}
|
||||
printf("\n[%d]Popfunc Finsh:%0.3f (free:%d)\n",i,el.elapsed(),m_memPooler.GetCount());
|
||||
}
|
||||
|
||||
void TestMPMCMemoryPool::oriPopFunc( int i )
|
||||
{
|
||||
boost::timer el;
|
||||
for(int j = 0; j<POPCOUNT;++j)
|
||||
{
|
||||
test_* ptest = m_orimemPooler.Pop();
|
||||
// printf("O:%d ",ptest->i);
|
||||
if(j% 300000 == 1)
|
||||
printf("o:%d ",ptest->i);
|
||||
m_orimemPooler.Push(ptest);
|
||||
}
|
||||
printf("\n[%d]OriPopfunc Finsh:%0.3f (free:%d)\n",i,el.elapsed(),m_orimemPooler.GetCount());
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
#pragma once
|
||||
|
||||
#include "TestCase.h"
|
||||
#include "mpmc_seh_mempool.h"
|
||||
#include <set>
|
||||
#include "MemPooler.h"
|
||||
|
||||
struct test_
|
||||
{
|
||||
char str[256];
|
||||
int i;
|
||||
};
|
||||
|
||||
class TestMPMCMemoryPool : public TestCase
|
||||
{
|
||||
public:
|
||||
TestMPMCMemoryPool(void);
|
||||
virtual ~TestMPMCMemoryPool(void);
|
||||
|
||||
virtual void Run();
|
||||
virtual void TestFunc(int i, int maxcount);
|
||||
virtual void oriTestFunc(int i, int maxcount);
|
||||
virtual void PopFunc(int i);
|
||||
virtual void oriPopFunc(int i);
|
||||
|
||||
MPMC_MemPooler<test_> m_memPooler;
|
||||
MemPooler<test_> m_orimemPooler;
|
||||
};
|
||||
|
||||
@@ -0,0 +1,155 @@
|
||||
#include "StdAfx.h"
|
||||
#include "TestMPMCQueue.h"
|
||||
#include <iostream>
|
||||
#include <set>
|
||||
|
||||
TestMPMCQueue::TestMPMCQueue(void)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
TestMPMCQueue::~TestMPMCQueue(void)
|
||||
{
|
||||
}
|
||||
|
||||
void TestMPMCQueue::Start()
|
||||
{
|
||||
|
||||
}
|
||||
#define MAXXX 3
|
||||
void TestMPMCQueue::Run()
|
||||
{
|
||||
#if 0
|
||||
m_pool.CreatePool(MAXXX/2,MAXXX);
|
||||
std::vector<int*> ints;
|
||||
for(int i=0; i<MAXXX; ++i)
|
||||
{
|
||||
ints.push_back(m_pool.Pop());
|
||||
}
|
||||
for(int i=0; i<ints.size(); ++i)
|
||||
{
|
||||
*ints[i] = i;
|
||||
}
|
||||
for(int i=0; i<ints.size(); ++i)
|
||||
{
|
||||
m_pool.Push(reinterpret_cast<int*>(ints[i]));
|
||||
}
|
||||
ints.clear();
|
||||
for(int i=0; i<MAXXX; ++i)
|
||||
{
|
||||
int* a = m_pool.Pop();
|
||||
printf("P:%d\n",*a);
|
||||
ints.push_back(a);
|
||||
}
|
||||
for(int i=0; i<ints.size(); ++i)
|
||||
{
|
||||
m_pool.Push(reinterpret_cast<int*>(ints[i]));
|
||||
}
|
||||
ints.clear();
|
||||
for(int i=0; i<MAXXX; ++i)
|
||||
{
|
||||
int* a = m_pool.Pop();
|
||||
printf("P:%d\n",*a);
|
||||
ints.push_back(a);
|
||||
}
|
||||
for(int i=0; i<ints.size(); ++i)
|
||||
{
|
||||
m_pool.Push(reinterpret_cast<int*>(ints[i]));
|
||||
}
|
||||
#endif
|
||||
#if 1
|
||||
int tmpval;
|
||||
printf("\nQueCount : ");
|
||||
std::cin >> tmpval;
|
||||
int quecount = tmpval;
|
||||
|
||||
printf("Thread Count : ");
|
||||
scanf_s("%d",&tmpval);
|
||||
std::vector<boost::thread*> m_threads;
|
||||
for(int i=0; i<tmpval; ++i)
|
||||
{
|
||||
m_threads.push_back(new boost::thread(&TestMPMCQueue::Input,this,(quecount/tmpval)*i,quecount/tmpval));
|
||||
}
|
||||
|
||||
for(int i=0; i<m_threads.size(); ++i)
|
||||
m_threads[i]->join();
|
||||
printf("\n");
|
||||
int popcount = 2;
|
||||
std::vector<boost::thread*> m_popthreads;
|
||||
std::vector<std::vector<int>* > values;
|
||||
for(int i=0; i<popcount; ++i)
|
||||
{
|
||||
std::vector<int>* tmpset = new std::vector<int>;
|
||||
values.push_back(tmpset);
|
||||
}
|
||||
for(int i =0; i<popcount; ++i)
|
||||
{
|
||||
m_popthreads.push_back(new boost::thread(&TestMPMCQueue::Pop,this,i,(quecount/popcount),quecount,values[i]));
|
||||
}
|
||||
for(int i=0; i<popcount; ++i)
|
||||
m_popthreads[i]->join();
|
||||
printf("\n");
|
||||
std::set<int> mainset;
|
||||
for(int i=0; i< values.size(); ++i)
|
||||
{
|
||||
for(int j=0; j<values[i]->size(); ++j)
|
||||
{
|
||||
if(unique_check(mainset.insert(values[i]->at(j))) == -1)
|
||||
printf("Áߺ¹µ¥ÀÌÅÍ\n");
|
||||
}
|
||||
}
|
||||
printf("Final size = %d\n",mainset.size());
|
||||
for(int i=0; i<values.size(); ++i)
|
||||
{
|
||||
values[i]->clear();
|
||||
|
||||
}
|
||||
#endif
|
||||
//m_popthreads.join();
|
||||
//m_queue.ReleaseMemoryPool();
|
||||
|
||||
}
|
||||
|
||||
double TestMPMCQueue::Input( int i, int maxcount )
|
||||
{
|
||||
|
||||
boost::timer el;
|
||||
int index = 0;
|
||||
for(index; index<maxcount; ++index)
|
||||
{
|
||||
mpmc_queue::node_t* tt = new mpmc_queue::node_t;
|
||||
// tt->data = new int(i+index);
|
||||
m_queue.enqueue(tt);
|
||||
}
|
||||
printf("i:%d max:%d time:%0.3f\n",i,maxcount,el.elapsed());
|
||||
return 0;
|
||||
}
|
||||
|
||||
void TestMPMCQueue::Pop( int i,int maxcount,int quecount, std::vector<int>* setval)
|
||||
{
|
||||
|
||||
int index =0;
|
||||
//while(1)
|
||||
boost::timer el;
|
||||
for(index; index<maxcount; ++index)
|
||||
{
|
||||
mpmc_queue::node_t* valt = m_queue.dequeue();
|
||||
// int* val = (int*)valt->data;
|
||||
// if(val == NULL)
|
||||
{
|
||||
// printf("NULL Size : %d\n",m_queue.GetSize());
|
||||
// printf("ºü´Ù:%d\n",val);
|
||||
|
||||
break;
|
||||
}
|
||||
// setval->push_back(*val);
|
||||
|
||||
|
||||
|
||||
//printf("P[%d]:%d ",i,*val);
|
||||
//delete val;
|
||||
|
||||
}
|
||||
printf("Elast::%0.3f\n",el.elapsed());
|
||||
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
#pragma once
|
||||
|
||||
#include "TestCase.h"
|
||||
#include "MPMCQueue.h"
|
||||
#include "mpmc_queue.h"
|
||||
#include "mpmc_seh_mempool.h"
|
||||
#include <set>
|
||||
|
||||
class TestMPMCQueue : public TestCase
|
||||
{
|
||||
public:
|
||||
TestMPMCQueue(void);
|
||||
virtual ~TestMPMCQueue(void);
|
||||
virtual void Start();
|
||||
virtual void Run();
|
||||
|
||||
public:
|
||||
double Input(int i, int maxcount);
|
||||
void Pop(int i,int maxcount,int quecount, std::vector<int>* sets);
|
||||
|
||||
protected:
|
||||
//MPMCQueue<int> m_queue;
|
||||
//ORIMPMCQueue<int> m_queue;
|
||||
mpmc_queue m_queue;
|
||||
//MPMC_MemPooler<int> m_pool;
|
||||
MemPooler<int> m_pool;
|
||||
|
||||
|
||||
};
|
||||
|
||||
@@ -0,0 +1,123 @@
|
||||
#include "StdAfx.h"
|
||||
#include "TestMPSCQueue.h"
|
||||
#include <set>
|
||||
#include <iostream>
|
||||
|
||||
extern INT G_TESTCOUNT;
|
||||
extern LONG G_NUMBER;
|
||||
extern BOOL G_TERMINATE;
|
||||
|
||||
TestMPSCQueue::TestMPSCQueue(int count) : m_count(count)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
TestMPSCQueue::~TestMPSCQueue(void)
|
||||
{
|
||||
}
|
||||
|
||||
void TestMPSCQueue::Run()
|
||||
{
|
||||
G_NUMBER = 0;
|
||||
G_TERMINATE = FALSE;
|
||||
|
||||
m_queue.Init(G_TESTCOUNT, 1);
|
||||
|
||||
std::vector<boost::thread*> m_threads;
|
||||
for(int i=0; i< m_count; i++)
|
||||
{
|
||||
m_threads.push_back(new boost::thread(&TestMPSCQueue::Input,this));
|
||||
}
|
||||
|
||||
//for(int i=0; i<m_threads.size(); ++i)
|
||||
// m_threads[i]->join();
|
||||
|
||||
|
||||
boost::thread popthread(&TestMPSCQueue::Pop,this);
|
||||
popthread.join();
|
||||
m_queue.ReleaseMemoryPool();
|
||||
|
||||
}
|
||||
|
||||
double TestMPSCQueue::Input()
|
||||
{
|
||||
int count = 0;
|
||||
while(!G_TERMINATE)
|
||||
{
|
||||
DummyMPSC* node = new DummyMPSC;
|
||||
if(!node)
|
||||
{
|
||||
int a;
|
||||
a = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
++count;
|
||||
|
||||
LONG value = InterlockedIncrement(&G_NUMBER);
|
||||
node->data = value;
|
||||
|
||||
if(m_queue.Enqueue((DWORD)node) == false)
|
||||
{
|
||||
//printf("Memory Pool Zero\n");
|
||||
break;
|
||||
}
|
||||
|
||||
if(value >= G_TESTCOUNT)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void TestMPSCQueue::Pop()
|
||||
{
|
||||
int popcount = 0;
|
||||
boost::timer el;
|
||||
|
||||
DummyMPSC* popval = NULL;
|
||||
|
||||
while(1)
|
||||
{
|
||||
popval = reinterpret_cast<DummyMPSC*>(m_queue.Dequeue());
|
||||
if(popval == NULL)
|
||||
{
|
||||
SwitchToThread();
|
||||
continue;
|
||||
}
|
||||
if(popcount == 0)
|
||||
{
|
||||
el.restart();
|
||||
}
|
||||
|
||||
delete popval;
|
||||
|
||||
popcount++;
|
||||
if(popcount >= G_TESTCOUNT)
|
||||
{
|
||||
G_TERMINATE = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
printf("Finished popCount :[%d] time: [%0.4f], remain : %lu\n",popcount, el.elapsed(), m_queue.GetSize());
|
||||
|
||||
while(TRUE)
|
||||
{
|
||||
popval = reinterpret_cast<DummyMPSC*>(m_queue.Dequeue());
|
||||
if(popval == NULL) break;
|
||||
|
||||
delete popval;
|
||||
}
|
||||
|
||||
if(m_queue.GetSize() != 0)
|
||||
{
|
||||
printf("remove not complete : %lu\n", m_queue.GetSize());
|
||||
}
|
||||
}
|
||||
|
||||
void TestMPSCQueue::Start()
|
||||
{
|
||||
boost::thread thread(&TestMPSCQueue::Run,this);
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
#pragma once
|
||||
|
||||
#include "TestCase.h"
|
||||
#include "TMPSCQueue.h"
|
||||
|
||||
class TestMPSCQueue : public TestCase
|
||||
{
|
||||
public:
|
||||
TestMPSCQueue(int count);
|
||||
virtual ~TestMPSCQueue(void);
|
||||
virtual void Start();
|
||||
virtual void Run();
|
||||
|
||||
public:
|
||||
double Input();
|
||||
void Pop();
|
||||
|
||||
protected:
|
||||
TMPSCQueue m_queue;
|
||||
int m_count;
|
||||
};
|
||||
|
||||
@@ -0,0 +1,125 @@
|
||||
#include "StdAfx.h"
|
||||
#include "TestWFQueue.h"
|
||||
#include <set>
|
||||
#include <iostream>
|
||||
|
||||
extern INT G_TESTCOUNT;
|
||||
extern LONG G_NUMBER;
|
||||
extern BOOL G_TERMINATE;
|
||||
|
||||
TestWFQueue::TestWFQueue(int count) : m_count(count)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
TestWFQueue::~TestWFQueue(void)
|
||||
{
|
||||
}
|
||||
|
||||
void TestWFQueue::Run()
|
||||
{
|
||||
G_NUMBER = 0;
|
||||
G_TERMINATE = FALSE;
|
||||
|
||||
std::vector<boost::thread*> m_threads;
|
||||
for(int i=0; i< m_count; i++)
|
||||
{
|
||||
m_threads.push_back(new boost::thread(&TestWFQueue::Input,this));
|
||||
}
|
||||
|
||||
//for(int i=0; i<m_threads.size(); ++i)
|
||||
// m_threads[i]->join();
|
||||
|
||||
boost::thread popthread(&TestWFQueue::Pop,this);
|
||||
popthread.join();
|
||||
}
|
||||
|
||||
double TestWFQueue::Input()
|
||||
{
|
||||
int count = 0;
|
||||
while(!G_TERMINATE)
|
||||
{
|
||||
DummyWF* node = new DummyWF;
|
||||
if(!node)
|
||||
{
|
||||
int a;
|
||||
a = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
++count;
|
||||
|
||||
LONG value = InterlockedIncrement(&G_NUMBER);
|
||||
node->data = value;
|
||||
|
||||
if(m_queue.Enqueue(node) == false)
|
||||
{
|
||||
printf("Memory Pool Zero\n");
|
||||
break;
|
||||
}
|
||||
|
||||
if(value >= G_TESTCOUNT)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void TestWFQueue::Pop()
|
||||
{
|
||||
std::set<int> values;
|
||||
|
||||
int popcount = 0;
|
||||
boost::timer el;
|
||||
|
||||
DummyWF* popval = NULL;
|
||||
while(TRUE)
|
||||
{
|
||||
popval = reinterpret_cast<DummyWF*>(m_queue.Dequeue());
|
||||
if(popval == NULL)
|
||||
{
|
||||
SwitchToThread();
|
||||
continue;
|
||||
}
|
||||
if(popcount == 0)
|
||||
{
|
||||
el.restart();
|
||||
}
|
||||
|
||||
//if(unique_check(values.insert(popval->data)) == -1)
|
||||
//{
|
||||
// printf("Áߺ¹µ¥ÀÌÅÍ \n");
|
||||
// break;
|
||||
//}
|
||||
|
||||
delete popval;
|
||||
|
||||
popcount++;
|
||||
if(popcount >= G_TESTCOUNT)
|
||||
{
|
||||
G_TERMINATE = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
printf("Finished popCount :[%d] time: [%0.4f], remain : %lu\n",popcount, el.elapsed(), m_queue.GetSize());
|
||||
|
||||
while(TRUE)
|
||||
{
|
||||
popval = reinterpret_cast<DummyWF*>(m_queue.Dequeue());
|
||||
if(popval == NULL) break;
|
||||
|
||||
delete popval;
|
||||
}
|
||||
|
||||
if(m_queue.GetSize() != 0)
|
||||
{
|
||||
printf("remove not complete : %lu\n", m_queue.GetSize());
|
||||
}
|
||||
}
|
||||
|
||||
void TestWFQueue::Start()
|
||||
{
|
||||
boost::thread thread(&TestWFQueue::Run,this);
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
#pragma once
|
||||
|
||||
#include "TestCase.h"
|
||||
#include "MPSCQueue.h"
|
||||
|
||||
class TestWFQueue : public TestCase
|
||||
{
|
||||
public:
|
||||
TestWFQueue(int count);
|
||||
virtual ~TestWFQueue(void);
|
||||
virtual void Start();
|
||||
virtual void Run();
|
||||
|
||||
public:
|
||||
double Input();
|
||||
void Pop();
|
||||
|
||||
protected:
|
||||
WFQueue m_queue;
|
||||
int m_count;
|
||||
|
||||
};
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
#pragma once
|
||||
|
||||
class cCriticalSection
|
||||
{
|
||||
public:
|
||||
cCriticalSection()
|
||||
{
|
||||
InitializeCriticalSection( &m_criticalSection );
|
||||
}
|
||||
|
||||
~cCriticalSection() { DeleteCriticalSection( &m_criticalSection ); }
|
||||
|
||||
public:
|
||||
void Lock() { EnterCriticalSection( &m_criticalSection ); }
|
||||
void Unlock() { LeaveCriticalSection( &m_criticalSection ); }
|
||||
|
||||
private:
|
||||
CRITICAL_SECTION m_criticalSection;
|
||||
};
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef _LS_BASIC_TYPES_
|
||||
#define _LS_BASIC_TYPES_
|
||||
typedef unsigned int uint;
|
||||
typedef unsigned char uchar;
|
||||
typedef unsigned short ushort;
|
||||
typedef unsigned long ulong;
|
||||
typedef unsigned long uint32;
|
||||
typedef unsigned short uint16;
|
||||
typedef unsigned char uint8;
|
||||
typedef unsigned __int64 uint64;
|
||||
typedef char int8;
|
||||
typedef short int16;
|
||||
typedef long int32;
|
||||
typedef __int64 int64;
|
||||
|
||||
typedef uint64 uniq;
|
||||
typedef uint32 unit;
|
||||
#endif
|
||||
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
/* Multi-producer/multi-consumer queue
|
||||
* 2009, Dmitriy V'yukov
|
||||
* Distributed under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation,
|
||||
* either version 3 of the License, or (at your option) any later version.
|
||||
* See: http://www.gnu.org/licenses
|
||||
*/
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "mpmc_queue.h"
|
||||
|
||||
|
||||
@@ -0,0 +1,149 @@
|
||||
/* Multi-producer/multi-consumer queue
|
||||
* 2009, Dmitriy V'yukov
|
||||
* Distributed under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation,
|
||||
* either version 3 of the License, or (at your option) any later version.
|
||||
* See: http://www.gnu.org/licenses
|
||||
*/
|
||||
#include <assert.h>
|
||||
#pragma once
|
||||
|
||||
|
||||
|
||||
class mpmc_queue
|
||||
{
|
||||
public:
|
||||
struct node_t
|
||||
{
|
||||
|
||||
node_t* volatile next_;
|
||||
|
||||
};
|
||||
|
||||
mpmc_queue()
|
||||
{
|
||||
head_.ptr_ = 0;
|
||||
head_.cnt_ = 0;
|
||||
tail_ = &head_.ptr_;
|
||||
m_size = 0;
|
||||
}
|
||||
|
||||
~mpmc_queue()
|
||||
{
|
||||
assert(head_.ptr_ == 0);
|
||||
assert(tail_ == &head_.ptr_);
|
||||
}
|
||||
|
||||
long size()
|
||||
{
|
||||
return m_size;
|
||||
}
|
||||
bool empty()
|
||||
{
|
||||
if(m_size == 0)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
void enqueue(node_t* node)
|
||||
{
|
||||
|
||||
assert(node);
|
||||
node->next_ = 0;
|
||||
node_t** prev = (node_t**)
|
||||
_InterlockedExchange((long*)&tail_, (long)node);
|
||||
assert(prev);
|
||||
// <--- the window of inconsistency is HERE (***)
|
||||
prev[0] = node;
|
||||
InterlockedIncrement(&m_size);
|
||||
}
|
||||
|
||||
node_t* dequeue()
|
||||
{
|
||||
unsigned retry_count = 0;
|
||||
InterlockedDecrement(&m_size);
|
||||
retry:
|
||||
__try
|
||||
{
|
||||
head_t h;
|
||||
h.ptr_= head_.ptr_;
|
||||
h.cnt_ = head_.cnt_;
|
||||
for (;;)
|
||||
{
|
||||
node_t* n = h.ptr_;
|
||||
if (n == 0)
|
||||
return 0;
|
||||
if (n->next_)
|
||||
{
|
||||
head_t xchg = {n->next_, h.cnt_ + 1};
|
||||
__int64 prev_raw =
|
||||
_InterlockedCompareExchange64
|
||||
(&head_.whole_, xchg.whole_, h.whole_);
|
||||
head_t prev = *(head_t*)&prev_raw;
|
||||
if (*(__int64*)&prev == *(__int64*)&h)
|
||||
return n;
|
||||
h.ptr_ = prev.ptr_;
|
||||
h.cnt_ = prev.cnt_;
|
||||
}
|
||||
else
|
||||
{
|
||||
node_t* t = (node_t*)tail_;
|
||||
if (n != t)
|
||||
{
|
||||
// spinning here may only be caused
|
||||
// by producer preempted in (***)
|
||||
SwitchToThread();
|
||||
h.ptr_= head_.ptr_;
|
||||
h.cnt_ = head_.cnt_;
|
||||
continue;
|
||||
}
|
||||
head_t xchg = {0, h.cnt_ + 1};
|
||||
head_t prev;
|
||||
prev.whole_ = _InterlockedCompareExchange64
|
||||
(&head_.whole_, xchg.whole_, h.whole_);
|
||||
if (prev.whole_ == h.whole_)
|
||||
{
|
||||
node_t* prev_tail = (node_t*)
|
||||
_InterlockedCompareExchange
|
||||
((long*)&tail_, (long)&head_.ptr_, (long)n);
|
||||
if (prev_tail == n)
|
||||
return n;
|
||||
// spinning here may only be caused
|
||||
// by producer preempted in (***)
|
||||
while (n->next_ == 0)
|
||||
SwitchToThread();
|
||||
head_.ptr_ = n->next_;
|
||||
return n;
|
||||
}
|
||||
h.ptr_ = prev.ptr_;
|
||||
h.cnt_ = prev.cnt_;
|
||||
}
|
||||
}
|
||||
}
|
||||
__except ((GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION
|
||||
&& ++retry_count < 64*1024) ?
|
||||
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
|
||||
{
|
||||
goto retry;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
union head_t
|
||||
{
|
||||
struct
|
||||
{
|
||||
node_t* ptr_;
|
||||
unsigned cnt_;
|
||||
};
|
||||
__int64 whole_;
|
||||
};
|
||||
|
||||
head_t volatile head_;
|
||||
char pad_ [64];
|
||||
node_t* volatile* volatile tail_;
|
||||
|
||||
mpmc_queue(mpmc_queue const&);
|
||||
mpmc_queue& operator = (mpmc_queue const&);
|
||||
long m_size;
|
||||
};
|
||||
|
||||
@@ -0,0 +1,130 @@
|
||||
#pragma once
|
||||
|
||||
#include <deque>
|
||||
#include <list>
|
||||
#include "mpmc_queue.h"
|
||||
|
||||
template <class Type>
|
||||
class MPMC_MemPooler
|
||||
{
|
||||
struct PoolElement
|
||||
{
|
||||
Type data;
|
||||
mpmc_queue::node_t node;
|
||||
};
|
||||
public:
|
||||
MPMC_MemPooler(int numofBlock=0, int maximumBlock=0 ) :
|
||||
m_allocCount(32),
|
||||
m_numofBlock(numofBlock),
|
||||
m_maximumBlock(maximumBlock)
|
||||
{
|
||||
Create(numofBlock);
|
||||
}
|
||||
~MPMC_MemPooler()
|
||||
{
|
||||
Destroy();
|
||||
}
|
||||
|
||||
public:
|
||||
void CreatePool(const int numofBlock, const int maximumBlock=0 )
|
||||
{
|
||||
m_numofBlock = 0;
|
||||
m_maximumBlock = maximumBlock;
|
||||
Create(numofBlock);
|
||||
}
|
||||
void DestroyPool()
|
||||
{
|
||||
Destroy();
|
||||
}
|
||||
|
||||
public:
|
||||
Type* Pop()
|
||||
{
|
||||
return Get();
|
||||
}
|
||||
Type* Remove()
|
||||
{
|
||||
if(m_memPooler.empty())
|
||||
return (NULL);
|
||||
return Get();
|
||||
}
|
||||
void CreatePush(Type* block)
|
||||
{
|
||||
if(m_numofBlock < m_maximumBlock)
|
||||
{
|
||||
PoolElement* memBlock = new PoolElement;
|
||||
if(memBlock)
|
||||
{
|
||||
memcpy(&memBlock->data,block,sizeof(Type));
|
||||
m_memPooler.enqueue(&memBlock->node);
|
||||
}
|
||||
m_numofBlock++;
|
||||
}
|
||||
delete block;
|
||||
}
|
||||
void Push(Type* block)
|
||||
{
|
||||
if(block == NULL)
|
||||
return;
|
||||
PoolElement* tmpdata = reinterpret_cast<PoolElement*>(block);
|
||||
m_memPooler.enqueue(&tmpdata->node);
|
||||
}
|
||||
|
||||
int GetCount() { return m_memPooler.size(); }
|
||||
int GetTotalCount() { return m_numofBlock; }
|
||||
|
||||
protected:
|
||||
void Create(const int numofBlock)
|
||||
{
|
||||
if(numofBlock <= 0) return;
|
||||
for(int i = 0 ; i < numofBlock ; i++)
|
||||
{
|
||||
PoolElement *memBlock = new PoolElement;
|
||||
if(memBlock)
|
||||
m_memPooler.enqueue(&memBlock->node);
|
||||
}
|
||||
m_numofBlock += numofBlock;
|
||||
}
|
||||
void Destroy()
|
||||
{
|
||||
mpmc_queue::node_t* pnode = m_memPooler.dequeue();
|
||||
PoolElement* tmpdata = CONTAINING_RECORD(pnode,PoolElement,node);
|
||||
while(tmpdata)
|
||||
{
|
||||
delete tmpdata;
|
||||
mpmc_queue::node_t* pnode = m_memPooler.dequeue();
|
||||
if(pnode == NULL)
|
||||
break;
|
||||
tmpdata = CONTAINING_RECORD(pnode,PoolElement,node);
|
||||
}
|
||||
}
|
||||
Type* Get()
|
||||
{
|
||||
Type* block = NULL;
|
||||
if(!m_memPooler.empty())
|
||||
{
|
||||
mpmc_queue::node_t* pnode = m_memPooler.dequeue();
|
||||
PoolElement* tmpdata = CONTAINING_RECORD(pnode,PoolElement,node);
|
||||
block = reinterpret_cast<Type*>(tmpdata);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
if(m_numofBlock < m_maximumBlock)
|
||||
{
|
||||
int allocCount = m_maximumBlock - m_numofBlock;
|
||||
(allocCount > m_allocCount) ? Create(m_allocCount) : Create(allocCount);
|
||||
mpmc_queue::node_t* pnode = m_memPooler.dequeue();
|
||||
PoolElement* tmpdata = CONTAINING_RECORD(pnode,PoolElement,node);
|
||||
block = reinterpret_cast<Type*>(tmpdata);
|
||||
}
|
||||
}
|
||||
return (block);
|
||||
}
|
||||
protected:
|
||||
int m_allocCount;
|
||||
int m_numofBlock;
|
||||
int m_maximumBlock;
|
||||
mpmc_queue m_memPooler;
|
||||
};
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
// stdafx.cpp : 표준 포함 파일만 들어 있는 소스 파일입니다.
|
||||
// testQueue.pch는 미리 컴파일된 헤더가 됩니다.
|
||||
// stdafx.obj에는 미리 컴파일된 형식 정보가 포함됩니다.
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
// TODO: 필요한 추가 헤더는
|
||||
// 이 파일이 아닌 STDAFX.H에서 참조합니다.
|
||||
@@ -0,0 +1,18 @@
|
||||
// stdafx.h : 자주 사용하지만 자주 변경되지는 않는
|
||||
// 표준 시스템 포함 파일 및 프로젝트 관련 포함 파일이
|
||||
// 들어 있는 포함 파일입니다.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "targetver.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <tchar.h>
|
||||
#include <Windows.h>
|
||||
|
||||
// TODO: 프로그램에 필요한 추가 헤더는 여기에서 참조합니다.
|
||||
#include <boost/timer.hpp>
|
||||
#include <boost/thread.hpp>
|
||||
#include "TMPSCQueue.h"
|
||||
#include "common.h"
|
||||
@@ -0,0 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
// SDKDDKVer.h를 포함하면 최고 수준의 가용성을 가진 Windows 플랫폼이 정의됩니다.
|
||||
|
||||
// 이전 Windows 플랫폼에 대해 응용 프로그램을 빌드하려는 경우에는 SDKDDKVer.h를 포함하기 전에
|
||||
// WinSDKVer.h를 포함하고 _WIN32_WINNT 매크로를 지원하려는 플랫폼으로 설정하십시오.
|
||||
|
||||
#include <SDKDDKVer.h>
|
||||
@@ -0,0 +1,106 @@
|
||||
// testQueue.cpp : 콘솔 응용 프로그램에 대한 진입점을 정의합니다.
|
||||
//
|
||||
|
||||
#include "stdafx.h"
|
||||
#include <iostream>
|
||||
#include <set>
|
||||
#include <conio.h>
|
||||
#include "TestMPSCQueue.h"
|
||||
//#include "TestIOCPQueue.h"
|
||||
#include "TestMPMCQueue.h"
|
||||
#include "TestWFQueue.h"
|
||||
#include "TestMPMCMemoryPool.h"
|
||||
|
||||
|
||||
INT G_TESTCOUNT = 1000000;
|
||||
LONG G_NUMBER = 0;
|
||||
BOOL G_TERMINATE = FALSE;
|
||||
|
||||
int _tmain(int argc, _TCHAR* argv[])
|
||||
{
|
||||
|
||||
while(1)
|
||||
{
|
||||
printf("\t\t ===========================================\t\t\n");
|
||||
printf("\t\t >> [0] Run MPSC QueueTest\n");
|
||||
printf("\t\t >> [1] Run IOCP QueueTest\n");
|
||||
printf("\t\t >> [2] Run MPMC QueueTest\n");
|
||||
printf("\t\t >> [3] Run MPMC MemoryPoolTest\n");
|
||||
printf("\t\t >> [4] Run WF QueueTest\n");
|
||||
printf("\t\t >> [q] Quit TestQueue Program\n");
|
||||
printf("\t\t >> ========================================\t\t\n\n");
|
||||
|
||||
printf("\t\t >> Input : ");
|
||||
|
||||
char c;
|
||||
std::cin >> c;
|
||||
|
||||
switch(c)
|
||||
{
|
||||
case 'Q':
|
||||
case 'q':
|
||||
{
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case '0':
|
||||
{
|
||||
int count;
|
||||
|
||||
printf("Thread Count : ");
|
||||
scanf_s("%d", &count);
|
||||
|
||||
for(int i = 0 ; i < 20 ; i++)
|
||||
{
|
||||
TestMPSCQueue* m = new TestMPSCQueue(count);
|
||||
m->Run();
|
||||
delete m;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case '1':
|
||||
{
|
||||
//TestIOCPQueue* m = new TestIOCPQueue;
|
||||
//m->Run();
|
||||
//delete m;
|
||||
|
||||
}
|
||||
break;
|
||||
case '2':
|
||||
{
|
||||
TestMPMCQueue* m = new TestMPMCQueue;
|
||||
m->Run();
|
||||
delete m;
|
||||
|
||||
}
|
||||
break;
|
||||
case '3':
|
||||
{
|
||||
TestMPMCMemoryPool* m = new TestMPMCMemoryPool;
|
||||
m->Run();
|
||||
delete m;
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
case '4':
|
||||
{
|
||||
int count;
|
||||
|
||||
printf("Thread Count : ");
|
||||
scanf_s("%d", &count);
|
||||
|
||||
for(int i = 0 ; i < 20 ; i++)
|
||||
{
|
||||
TestWFQueue* m = new TestWFQueue(count);
|
||||
m->Run();
|
||||
delete m;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,118 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{3C73F9FB-7352-4742-BE16-02B9152B8F82}</ProjectGuid>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<RootNamespace>testQueue</RootNamespace>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>C:\Program Files (x86)\boost\boost_1_47\</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalLibraryDirectories>C:\Program Files %28x86%29\boost\boost_1_47\lib</AdditionalLibraryDirectories>
|
||||
<AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<StackReserveSize>100000000</StackReserveSize>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>../../../src/iocpSocketDLL;C:\Program Files (x86)\boost\boost_1_47\</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<AdditionalLibraryDirectories>../../../lib;C:\Program Files %28x86%29\boost\boost_1_47\lib</AdditionalLibraryDirectories>
|
||||
<AdditionalDependencies>iocpsocketdll.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<None Include="ReadMe.txt" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="DATA.h" />
|
||||
<ClInclude Include="MPMCMemPool.h" />
|
||||
<ClInclude Include="MPMCQueue.h" />
|
||||
<ClInclude Include="mpmc_queue.h" />
|
||||
<ClInclude Include="mpmc_seh_mempool.h" />
|
||||
<ClInclude Include="MPSCQueue.h" />
|
||||
<ClInclude Include="TestMPMCMemoryPool.h" />
|
||||
<ClInclude Include="TestMPMCQueue.h" />
|
||||
<ClInclude Include="TestWFQueue.h" />
|
||||
<ClInclude Include="TMPSCQueue.h" />
|
||||
<ClInclude Include="stdafx.h" />
|
||||
<ClInclude Include="targetver.h" />
|
||||
<ClInclude Include="TestCase.h" />
|
||||
<ClInclude Include="TestMPSCQueue.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="mpmc_queue.cpp" />
|
||||
<ClCompile Include="MPSCQueue.cpp" />
|
||||
<ClCompile Include="TestMPMCMemoryPool.cpp" />
|
||||
<ClCompile Include="TestMPMCQueue.cpp" />
|
||||
<ClCompile Include="TestWFQueue.cpp" />
|
||||
<ClCompile Include="TMPSCQueue.cpp" />
|
||||
<ClCompile Include="stdafx.cpp">
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
<ClCompile Include="TestCase.cpp" />
|
||||
<ClCompile Include="TestMPSCQueue.cpp" />
|
||||
<ClCompile Include="testQueue.cpp" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,105 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="소스 파일">
|
||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="헤더 파일">
|
||||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||
<Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="리소스 파일">
|
||||
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
||||
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="TestCase">
|
||||
<UniqueIdentifier>{4f0bb767-8c95-41a7-96c4-44641f4eb77c}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Queue">
|
||||
<UniqueIdentifier>{f3e81d52-bfe9-4643-a59a-04fcbee67702}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="ReadMe.txt" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="stdafx.h">
|
||||
<Filter>헤더 파일</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="targetver.h">
|
||||
<Filter>헤더 파일</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="TestMPSCQueue.h">
|
||||
<Filter>TestCase</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="TestCase.h">
|
||||
<Filter>TestCase</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="MPMCQueue.h">
|
||||
<Filter>헤더 파일</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="TestMPMCQueue.h">
|
||||
<Filter>TestCase</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="mpmc_queue.h">
|
||||
<Filter>헤더 파일</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="MPMCMemPool.h">
|
||||
<Filter>헤더 파일</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="MPMCMemPool.h">
|
||||
<Filter>헤더 파일</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="mpmc_seh_mempool.h">
|
||||
<Filter>헤더 파일</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="TestMPMCMemoryPool.h">
|
||||
<Filter>TestCase</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="MPSCQueue.h">
|
||||
<Filter>Queue</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="TMPSCQueue.h">
|
||||
<Filter>Queue</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="TestWFQueue.h">
|
||||
<Filter>TestCase</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="DATA.h">
|
||||
<Filter>TestCase</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="stdafx.cpp">
|
||||
<Filter>소스 파일</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="testQueue.cpp">
|
||||
<Filter>소스 파일</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="TestCase.cpp">
|
||||
<Filter>TestCase</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="TestMPSCQueue.cpp">
|
||||
<Filter>TestCase</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="TestMPMCQueue.cpp">
|
||||
<Filter>TestCase</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="mpmc_queue.cpp">
|
||||
<Filter>소스 파일</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="TestMPMCMemoryPool.cpp">
|
||||
<Filter>TestCase</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="MPSCQueue.cpp">
|
||||
<Filter>Queue</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="TMPSCQueue.cpp">
|
||||
<Filter>Queue</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="TestWFQueue.cpp">
|
||||
<Filter>TestCase</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
Reference in new issue
Block a user