{
HANDLE curth = ::GetCurrentThread();
DWORD_PTR oldmask = ::SetThreadAffinityMask(curth, 0);
::QueryPerformanceCounter(&start_);
::SetThreadAffinityMask(curth, oldmask);
}
double HRTimer::StopTimer(void)
{
HANDLE curth = ::GetCurrentThread();
DWORD_PTR oldmask = ::SetThreadAffinityMask(curth, 0);
::QueryPerformanceCounter(&stop_);
::SetThreadAffinityMask(curth, oldmask);
return ((stop_.QuadPart - start_.QuadPart) / frequency_) * 1000;
}
class AutoHRTimer {
public:
AutoHRTimer(HRTimer& hrt, const char* name);
~AutoHRTimer();
private:
HRTimer& hrt_;
const char* name_;
};
AutoHRTimer::AutoHRTimer(HRTimer& hrt, const char* name)
: hrt_(hrt),
name_(name)
{
hrt_.StartTimer();
}
AutoHRTimer::~AutoHRTimer()
{
double diff = hrt_.StopTimer();
fprintf(stdout, "%s cost time %f ms\n", name_, diff);
}
HRTimer g_hrtimer;
void acs_deque_init(acs_deque_t* deq);
int acs_deque_empty(acs_deque_t* deq);
void acs_deque_push(acs_deque_t* deq, acs_node_t* node);
acs_node_t* acs_deque_pop(acs_deque_t* deq);
void acs_deque_init(acs_deque_t* deq)
{
if (deq) {
deq->tail = &deq->head;
deq->head.next = NULL;
}
}
int acs_deque_empty(acs_deque_t* deq)
{
if (!deq)
return 1;
return deq->head.next == NULL;
}
void acs_deque_push(acs_deque_t* deq, acs_node_t* node)
{
acs_node_t* q = NULL;
do {
q = deq->tail;
} while (InterlockedCompareExchangePointer((PVOID*)&q->next, 0, node) != q->next);
InterlockedCompareExchangePointer((PVOID*)&deq->tail, q, node);
}
acs_node_t* acs_deque_pop(acs_deque_t* deq)
{
acs_node_t* q = NULL;
do {
q = deq->head.next;
if (q == NULL)
return NULL;
} while (InterlockedCompareExchangePointer((PVOID*)&deq->head.next, q, q->next) != deq->head.next);
return q;
}
static DWORD AesThreadFunc(void* arg)
{
acs_deque_t* ad = (acs_deque_t*)arg;
for (int i = 0; i < knMaxNodeCount; ++i) {
acs_node_t* an = new acs_node_t;
an->id = "randid_";
an->id.push_back((i % 10) + '0');
an->index = i;
an->next = NULL;
acs_deque_push(ad, an);
} // for
return 0;
}
static void TestAcsDeque()
{
acs_deque_t ad;
acs_node_t* poped_node = NULL;
HANDLE th[knThreadCount];
{
AutoHRTimer ahr(g_hrtimer, "ACS push 50000");
acs_deque_init(&ad);
for (int i = 0; i < knThreadCount; ++i) {
th[i] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)AesThreadFunc, &ad, 0, NULL);
} // for
::WaitForMultipleObjects(knThreadCount, th, TRUE, INFINITE);
}
{
// Test pop.
AutoHRTimer ahr(g_hrtimer, "ACS pop 5000");
for (int i = 0; i < knPopedCount; ++i) {
poped_node = acs_deque_pop(&ad);
delete poped_node;
}
}
{
AutoHRTimer ahr(g_hrtimer, "ACS free 45000");
acs_node_t* cur = ad.head.next;
while (cur != NULL) {
acs_node_t* tmp = cur;
cur = cur->next;
delete tmp;
}
}
}
static DWORD StdThreadFunc(void* arg)
{
StdDeque* deq_list = (StdDeque*)arg;
for (int i = 0; i < knMaxNodeCount; ++i) {
DequeData* dd = new DequeData;
dd->id = "randid_";
dd->id.push_back((i % 10) + '0');
dd->index = i;
EnterCriticalSection(&g_stdcs);
deq_list->push_back(dd);
LeaveCriticalSection(&g_stdcs);
} // for