- container_locks.zip
- Container_locks
- src
- Testing_simple_concurrent_containers.pdf
- VC9
- container_locks.sln
- container_locks.vcproj
- container_locks.vcproj.val-PC.val.user
- Debug
- Debug64
- Release
- Release64
|
#include "stdafx.h"
#include "perf_counter.h"
#include "rwlocks.h"
#include "slimrwlock.h"
#include "map_tbb_t.h"
#include "map_container_locker_t.h"
#include "map_spinlocks_t.h"
#include "map_critsectable_t.h"
HANDLE g_start_event;
volatile long g_stop_test;
/*
Builder threads change structure of the container
(insert/delete container elements)
*/
const int builder_test_iterations = 4000000;
const int number_of_builders = 1;
/*
Writer threads may read and change elements of the container
*/
const int writer_test_iterations = 4000000;
const int number_of_writers = 16;
/*
Reader threads only read elements of the container
*/
const int reader_test_iterations = 4000000;
const int number_of_readers = 16;
const int number_of_elements = 1000000;
#pragma warning(disable:4324)
class test_container_element
{
public:
void calculate_checksum()
{
for(int i = 0; i < sizeof(m_buffer)/sizeof(m_buffer[0]); i ++)
{
m_buffer[i] = rand();
}
m_checksum = checksum(m_buffer, sizeof(m_buffer));
}
bool validate_checksum()
{
return (m_checksum == checksum(m_buffer, sizeof(m_buffer)));
}
private:
USHORT checksum( LPVOID data, int len )
//
// The function checksum came from http://ava.org.ua/?2&17&get=87&read=87
//
{
ULONG sum = 0;
USHORT * dp = (USHORT *) data;
USHORT sum_s;
int words = len >> 1;
while( words -- ) sum += * dp ++;
if( len & 1 ) sum += *(UCHAR*) dp;
sum = (USHORT) sum + (sum >> 16) & 0xffff;
sum_s = (USHORT) sum + (USHORT)(sum >> 16);
return sum_s != 0xffff ? ~sum_s : sum_s;
}
enum {BUF_SIZE = 64};
int m_buffer[BUF_SIZE];
USHORT m_checksum;
};
#pragma warning(default:4324)
#ifdef TEST_CS_TABLE_CONTAINER
CST_map_t<long, test_container_element,LOCK_TYPE> g_map;
#elif defined TEST_SPINLOCK_CONTAINER
SRWL_map_t<long, test_container_element,LOCK_TYPE> g_map;
#elif defined TEST_POOLLOCK_CONTAINER
Map_t<long, test_container_element, LOCK_TYPE, number_of_writers + number_of_readers> g_map;
#elif defined TEST_TBB_CONCURRENT_CONTAINER
TBB_map_t<long, test_container_element> g_map;
#endif
template <const int test_iteration>
class Test_worker{
public:
HANDLE start(unsigned long rand_seed)
{
m_randSeed = rand_seed;
::ResumeThread(m_handle);
return m_handle;
}
double test_duration(void)
{
return m_perf_counter.get_duration();
}
LONGLONG test_iteration_done(void)
{
return m_perf_counter.get_counter();
}
private:
static DWORD WINAPI worker_proc(LPVOID lpParam)
{
Test_worker& worker = *reinterpret_cast<Test_worker*>(lpParam);
::WaitForSingleObject(g_start_event, INFINITE );
worker.m_perf_counter.start();
int i;
for (i = 0; i < test_iteration; i++)
{
if( false == worker.simulate_work() )
{
::RaiseException( STATUS_NONCONTINUABLE_EXCEPTION, 0, 0, 0);
}
else
{
}
if (TRUE == g_stop_test)
{
break;
}
else
{
}
}
worker.m_perf_counter.end();
::InterlockedExchange(&g_stop_test, TRUE);
worker.m_perf_counter.set_iteration_done(i);
return 0;
}
virtual bool simulate_work(void)=0;
HANDLE m_handle;
Performance_counter_meter m_perf_counter;
unsigned long m_randSeed;
Test_worker & operator=( const Test_worker & ) {}
protected:
// The function rand() came from the MSDN article
// "Multiprocessor Optimizations: Fine-Tuning Concurrent Access to Large Data Collections"
// by Ian Emmons, http://msdn.microsoft.com/en-ca/magazine/cc301503.aspx
unsigned long rand(unsigned long hi)
{
const int k_randMax = 1771875ul,
k_randCoeff = 2416ul,
k_randOffset = 374441ul;
assert(hi < k_randMax);
m_randSeed = (m_randSeed * k_randCoeff + k_randOffset) % k_randMax;
return (hi * m_randSeed) / (k_randMax - 1);
}
Test_worker()
{
m_randSeed = 0;
m_handle = ::CreateThread(NULL,0, worker_proc, (LPVOID)this, CREATE_SUSPENDED, NULL);
}
};
class Container_builder: public Test_worker <builder_test_iterations>
{
public:
/*
One of the builders setup the container g_map
*/
static void setup_test_container(void)
{
for (long key = 0; key < number_of_elements; key++)
{
test_container_element value;
value.calculate_checksum();
g_map.insert(std::pair<long, test_container_element>(key, value));
}
}
Container_builder()
{
m_deleted_element = NOT_DELETED;
}
private:
virtual bool simulate_work(void)
{
if ( m_deleted_element == NOT_DELETED )
{
m_deleted_element = rand(number_of_elements);
g_map.erase(m_deleted_element);
}
else
{
test_container_element value;
value.calculate_checksum();
g_map.insert(std::pair<long, test_container_element>(m_deleted_element, value));
m_deleted_element = NOT_DELETED;
}
return true;
}
enum {NOT_DELETED = -1};
long m_deleted_element;
};
class Writer: public Test_worker <writer_test_iterations>
{
virtual bool simulate_work(void)
{
long element_to_update = rand(number_of_elements);
test_container_element value;
value.calculate_checksum();
g_map.update(element_to_update, value);
return true;
}
};
class Reader: public Test_worker <reader_test_iterations>
{
virtual bool simulate_work(void)
{
long element_to_read = rand(number_of_elements);
test_container_element value;
if(g_map.find(element_to_read, value))
{
return value.validate_checksum();
}
else
{
return true;
}
}
};
int _tmain(int, _TCHAR*)
{
Container_builder::setup_test_container();
g_start_event = ::CreateEvent(NULL,TRUE,FALSE,NULL);
HANDLE threads[number_of_builders + number_of_writers + number_of_readers];
Writer* writer[number_of_writers];
for (int i = 0; i < number_of_writers; i++)
{
writer[i] = new Writer();
threads[i] = writer[i]->start(::rand());
}
Reader* reader[number_of_readers];
for (int i = 0; i < number_of_readers; i++)
{
reader[i] = new Reader();
threads[i + number_of_writers] = reader[i]->start(::rand());
}
Container_builder* builder[number_of_builders];
for (int i = 0; i < number_of_builders; i++)
{
builder[i] = new Container_builder();
threads[i + number_of_writers + number_of_readers ] = builder[i]->start(::rand());
}
::SetEvent(g_start_event);
::WaitForMultipleObjects(sizeof(threads)/sizeof(threads[0]), threads, TRUE, INFINITE);
for (int i = 0; i < number_of_readers; i++)
{
printf("reader iterations done | per operation(ms),%lld,%f\n",
reader[i]->test_iteration_done(),
1000*reader[i]->test_duration()/reader[i]->test_iteration_done());
}
for (int i = 0; i < number_of_writers; i++)
{
printf("writer iterations done | per operation(ms),%lld,%f\n",
writer[i]->test_iteration_done(),
1000*writer[i]->test_duration()/writer[i]->test_iteration_done());
}
for (int i = 0; i < number_of_builders; i++)
{
printf("builder: iterations done | per operation(ms),%lld,%f\n",
builder[i]->test_iteration_done(),
1000*builder[i]->test_duration()/builder[i]->test_iteration_done());
}
return 0;
}
|
By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.
If a file you wish to view isn't highlighted, and is a text file (not binary), please
let us know and we'll add colourisation support for it.
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.