#include "../comnhdr.h"

//////////////////////////////////////////////////////////////////////////
//                                                                      //
//  >100 times faster case - .NET CLR                                   //
//                                                                      //
//////////////////////////////////////////////////////////////////////////

#define QUEUE_LENGTH        10
#define DATA_LENGTH         20 * 1024
#define NUM                 1000

ref class CNode {
public:
    CNode ^         m_pNext;
    array<int> ^    m_pData;

    CNode() {
        m_pData = gcnew array<int>(DATA_LENGTH);
    }

    static CNode ^  s_pHead;
    static CNode ^  s_pTail;

    static void PushHead(CNode ^ p) {
        p->m_pNext = s_pHead;
        s_pHead = p;
        if (s_pTail == nullptr) {
            s_pTail = p;
        }
    }

    static void PushTail(CNode ^ p) {
        if (s_pTail) {
            s_pTail->m_pNext = p;
        }
        s_pTail = p;
        if (s_pHead == nullptr) {
            s_pHead = p;
        }
    }

    static CNode ^ PopHead() {
        CNode ^ retval;
        retval = s_pHead;
        s_pHead = s_pHead->m_pNext;
        return retval;
    }

    static void init() {
        for (int i = 0; i < (1<<QUEUE_LENGTH); i++) {
            PushTail(gcnew CNode);
        }
    }

    static void main() {
        int nGCCount0 = System::GC::CollectionCount(0);
        int nGCCount1 = System::GC::CollectionCount(1);
        int nGCCount2 = System::GC::CollectionCount(2);
        BenchTicks_t bt;

        bt = BenchTicksGetCurrent();

        for (int i = 0; i < NUM; i++) {
            PushTail(gcnew CNode);
            PopHead();
        }

        bt = BenchTicksGetCurrent() - bt;
        printf("Completed in %s with %u/%u/%u collections.\n",
            BenchTicksToString(bt, false),
            System::GC::CollectionCount(0) - nGCCount0,
            System::GC::CollectionCount(1) - nGCCount1,
            System::GC::CollectionCount(2) - nGCCount2);
    }
};

int main () {
    CNode::init();

    for (int i = 0; i < 20; i++) {
        CNode::main();
    }
    return 0;
}
