#include "queue2.h"
#include <iostream>
#include <thread>
#include <vector>
#include <atomic>

std::atomic<int> c( 0 );
std::atomic<int> size( 0 );

void push_pop_1t( queue_1t<int> & q)
{
    for ( int i=0; i<100; ++i ) {
        q.push( ++c );
        int val = 0;
        std::shared_ptr<int> top = q.try_pop( );
//        std::cout << *top << std::endl;
    }
}

void push_pop( threadsafe_queue<int> & q)
{
    for ( int i=0; i<100; ++i ) {
        q.push( ++c );
        ++size;
        int val = 0;
        std::shared_ptr<int> top = q.try_pop( );
        if ( top ) {
        --size;
        }
//        std::cout << *top << std::endl;
    }
}

void pop_push( threadsafe_queue<int> & q)
{
    for ( int i=0; i<10000; ++i ) {
        int val = 0;
        std::shared_ptr<int> top = q.try_pop( );
        if ( top ) {
            q.push( ++*top );
        }
    }
}

int main()
{
//    queue_1t<int> q;
//    q.push( 1 );
//    push_pop_1t( q ); // works 

    threadsafe_queue<int> tsq;
    //push_pop( tsq );
    int num_threads = 2;
    std::vector<std::thread> threads;
    for( unsigned i=0; i<num_threads; ++i ) { 
        threads.push_back( std::thread( pop_push, std::ref( tsq ) ) );
    }
    for( unsigned i=0; i<num_threads; ++i ) { 
        threads.push_back( std::thread( push_pop, std::ref( tsq ) ) );
    }
    for( auto & t : threads ) {
        t.join();
    }

    //std::cout << "Stack content: ";
    int final_size = 0;
    while( !tsq.empty() ) {
        std::shared_ptr<int> top = tsq.try_pop();
        ++final_size;
        //std::cout << *top << std::endl;
    }
    if ( final_size != size ) {
        std::cout << "Wrong size " << final_size << std::endl;
    }
}