#include <iostream>
#include <stdexcept>
#include <vector>
#include <memory>
#include <chrono>
#include <thread>
#include <mutex>
#include <queue>
#include <condition_variable>
#include <atomic>
#include <utility>
#include <cassert>
using namespace std;
using namespace std::chrono;
#define CONCURRENT
#define N_GRAPHICS (1 * 1000 * 1000)
#define N_THREADS 8
struct Graphic;
static vector<size_t> indexes;
static vector<unique_ptr<Graphic>> graphics;
static queue<pair<Graphic*, size_t>> q;
static mutex m;
static atomic<size_t> n_elements;
struct Graphic
{
Graphic()
: status(false)
{
}
bool parse()
{
// waste time
try
{
throw runtime_error("");
}
catch (runtime_error)
{
}
status = true;
//return false;
return true;
}
bool status;
};
static void producer()
{
for (size_t i = 0; i < N_GRAPHICS; i++)
{
auto g = new Graphic();
#ifdef CONCURRENT
graphics.emplace_back(g);
q.emplace(make_pair(g, i));
#else
if (g->parse())
graphics.emplace_back(g);
else
delete g;
#endif
}
n_elements = graphics.size();
}
static void consumer()
{
pair<Graphic*, size_t> item;
while (true)
{
{
std::unique_lock<std::mutex> lk(m);
if (n_elements == 0)
return;
n_elements--;
item = q.front();
q.pop();
}
if (!item.first->parse())
{
assert(graphics[item.second].get() == item.first);
delete item.first;
graphics[item.second] = nullptr;
}
}
}
int main()
{
auto start = system_clock::now();
producer();
#ifdef CONCURRENT
vector<thread> threads;
for (auto i = 0; i < N_THREADS; i++)
threads.emplace_back(consumer);
#endif
for (size_t i = 0; i < graphics.size(); i++)
indexes.push_back(i);
#ifdef CONCURRENT
for (auto& t : threads)
t.join();
#endif
auto duration = duration_cast<milliseconds>(system_clock::now() - start);
cout << "Elapsed: " << duration.count() << endl;
for (size_t i = 0; i < graphics.size(); i++)
{
if (!graphics[i]->status)
{
cerr << "Assertion failed! (" << i << ")" << endl;
break;
}
}
cin.get();
return 0;
}