参考:
测试代码:
///////////////////////////////////////////////////////////////////////////////
/// SIMPLE LOCK FREE STACK ///
/// Copyright (c) 2014 Michael Gazonda - ///
/// CPOL Licensed ///
/// See CPOL.htm, or ///
/// ///
/// ///
///////////////////////////////////////////////////////////////////////////////
#include
#include
#include
#include
#include
#include
#include
#include "stack.h"
#include "data.h"
// These are the testing parameters, you can change them
#define data_count 10
#define loop_count 1000000
#define thread_count 2
using namespace std;
typedef struct{
double nDataTotal;
float fTotalLast;
int threadId;
int nActCount;
int nIndex;
int nLastLen;
int TotalSize;
int ReadSize;
clock_t tBegin;
clock_t tEnd;
long tDiff;
}t_help_info;
// This is the test function
// It uses those numbers set at the top
// Using new and delete is part of the test - for our new/delete calls to not crash,
// the data inside the stack must be handled properly. When we don't crash, and there is no
// "lost data", we know that everything went properly when playing with the stack.
thread_local t_help_info help_info;
std::mutex g_mtx;
void thread_test(stack *s, std::atomic *max_elapsed, std::atomic *empty_count, size_t index)
{
// Initialization - create the data we'll test with
data data_;
data* d_ = &data_;
data* d[data_count];
for (size_t i = 0; i < data_count; ++i){
d[i] = new data;
d[i]->x_ = index+1;
}
std::chrono::high_resolution_clock::time_point start = std::chrono::high_resolution_clock::now();
// This is the test loop
// Push and pop x number of times and see if everything comes out ok on the other side.
// Also a good working sample of moving data into and out of the stack.
for (size_t loop = 0; loop < loop_count; ++loop)
{
for (size_t i = 0; i < data_count; ++i)
{
if (d[i]){
help_info.TotalSize += d[i]->x_;
s->push(d[i]);
}
}
for (size_t i = 0; i < data_count; ++i){
// if (s->pop((node*&)d[i])){
// help_info.nActCount += d[i]->x_;
// help_info.ReadSize++;
// }
if (s->pop((node*&)d_)){
help_info.nActCount += d_->x_;
help_info.ReadSize++;
}
}
}
for (size_t loop = 0; loop < loop_count; ++loop)
{
if (s->pop((node*&)d_)){
help_info.nActCount += d_->x_;
help_info.ReadSize++;
if (help_info.ReadSize>=data_count * loop_count ) {
break;
}
}
}
std::chrono::high_resolution_clock::time_point finish = std::chrono::high_resolution_clock::now();
std::chrono::milliseconds span = std::chrono::duration_cast(finish - start);
//std::unique_lock lock(g_mtx);
std::cout << index << " - thread completed : " << span.count()
<< " read=" << help_info.ReadSize
<< " push=" << help_info.TotalSize
<< " pop =" << help_info.nActCount << "\r\n";
*max_elapsed = span.count();
// If the test is successful, every location will hold a valid pointer, and no pointers
// will be duplicated. We test for a valid pointer, and by using delete we ensure that we
// didn't have the same data in two places - deleting the same data twice would crash.
// - may not crash on all platforms, so this test isn't meant to have total cross-platform support
for (size_t i = 0; i < data_count; ++i)
{
if (d[i])
delete d[i];
else
(*empty_count)++;
}
}
// This is the place where we get stuff done. Start up the test threads, wait for them, and then
// check the results to display to the user afterwards. No big deal :)
int main(int argc, const char * argv[])
{
std::thread threads[thread_count];
std::atomic max_elapsed{ 0 };
std::atomic empty_count{ 0 };
stack s;
std::cout << R"_(///////////////////////////////////////////////////////////////////////////////
/// SIMPLE LOCK FREE STACK ///
/// Copyright (c) 2014 Michael Gazonda - ///
/// CPOL Licensed ///
/// See CPOL.htm, or ///
/// ///
/// ///
///////////////////////////////////////////////////////////////////////////////)_";
std::cout << "\r\nstarting\r\n";
// Start threads
for (size_t i = 0; i < thread_count; ++i)
threads[i] = std::thread(thread_test, &s, &max_elapsed, &empty_count, i);
// Wait for them to all finish
for (size_t i = 0; i < thread_count; ++i)
threads[i].join();
// Output information
size_t operation_count = data_count * loop_count * thread_count * 2;
if (!empty_count)
std::cout << "no lost data\r\n";
else
std::cout << "___lost data count___: " << empty_count << " of " << data_count * thread_count << "\r\n";
std::cout << "thread count : " << thread_count << "\r\n";
std::cout << "target processor bits: " << PROCESSOR_BITS << "\r\n";
std::cout << "total pushes and pops: " << operation_count << "\r\n";
std::cout << "operations per second: " << operation_count / (max_elapsed.load() > 0 ? max_elapsed.load() : 1) * 1000 << "\r\n";
std::cout << "processing time : " << max_elapsed.load() << "ms\r\n";
std::cout << "press any key to exit\r\n";
getchar();
return 0;
}
单线程没有问题,但多线程时则会出现进栈出栈中的x_累计值不相等,
阅读(1286) | 评论(0) | 转发(0) |