#include <algorithm>
#include <exception>
#include <cstdlib>
#include <iostream>
#include <vector>
#include <memory>
#include <boost/shared_ptr.hpp>
#include <boost/thread/thread.hpp>
#include <boost/bind.hpp>
#include <boost/timer.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/cstdint.hpp>
using namespace boost;
using namespace std;
struct obj
{
char _c;
long _v;
wstring _str;
char _data[104];
};
typedef std::shared_ptr<obj> std_obj_ptr;
typedef boost::shared_ptr<obj> boost_obj_ptr;
template <typename Pointer>
void thread_method(vector<Pointer> objects)
{
// shuffling
random_shuffle(objects.begin(), objects.end());
// now doing stuff that increases reference count
vector<Pointer> transformed(objects.size());
std::transform(objects.begin(), objects.end(), transformed.begin(), [](Pointer in) -> Pointer
{
// increase ref count
Pointer out = in;
// play around with data don't worry about race conditions
// we don't care about the results
out->_c = in->_c + 'c';
out->_v = in->_v << 1;
return out;
}
);
// now we drop the reference count
transformed.clear();
}
template <typename Pointer, typename Delete>
boost::uint64_t work_with_stuff(size_t count, size_t threads, Delete del)
{
if (!count || !threads)
return 0;
timer t;
vector<Pointer> v(count);
// building all our little objects
generate(v.begin(), v.end(), []{return Pointer(new obj()); });
thread_group run_group;
// let's thread !
for(size_t i = 0; i < threads; ++i)
{
run_group.create_thread(boost::bind(thread_method<Pointer>, v));
}
// wait for everything to end
run_group.join_all();
// do the clean up
for_each(v.begin(), v.end(), del);
// ref count => 0
v.clear();
return static_cast<boost::uint64_t>(t.elapsed() * 1000.0);
}
int wmain(int argc, wchar_t **argv, wchar_t *)
{
try
{
size_t objs[] = { 1000, 2500, 5000, 6000, 7000, 8000, 9000, 10000, 25000, 50000, 75000, 100000 };
vector<size_t> threads(8);
int i = 0;
generate(threads.begin(), threads.end(), [&i] { return ++i; });
for_each(objs, objs + sizeof(objs) / sizeof(size_t),
[&threads](int obj_count)
{
for_each(threads.begin(), threads.end(), [&obj_count](int thread_count)
{
// no need to clean up anything, smart pointers do that for us
boost::uint64_t std_time = work_with_stuff<std_obj_ptr>(obj_count, thread_count, [](std_obj_ptr p) {});
boost::uint64_t boost_time = work_with_stuff<boost_obj_ptr>(obj_count, thread_count, [](boost_obj_ptr p) {});
// we need to manually delete in this case
boost::uint64_t raw_time = work_with_stuff<obj *>(obj_count, thread_count, [](obj *p) { delete p; });
wchar_t separator = '\t';
wcout << obj_count << separator;
wcout << thread_count << separator;
wcout << std_time << separator;
wcout << boost_time << separator;
wcout << raw_time << separator;
wcout << endl;
});
});
return 0;
}
catch(const std::exception & e)
{
cerr << "error: " << e.what() << endl;
return -1;
}
}