#include "../comnhdr.h"

//////////////////////////////////////////////////////////////////////////
//                                                                      //
//  >100 times faster case - HnxGC                                      //
//                                                                      //
//////////////////////////////////////////////////////////////////////////

// #define TEST_CIRCULAR_REF

#include "hnxGC.h"

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

class CNode {
public:
    HNXGC_ENABLE(CNode)
    gcptr<CNode>    m_pNext;
    int             m_aData[DATA_LENGTH];
#if defined(TEST_CIRCULAR_REF)
    gcptr<CNode>    m_pSelf;
    CNode() {
        m_pSelf = native_cast(this);
    }
#endif

    static gcptr<CNode>     s_pHead;
    static gcptr<CNode>     s_pTail;

    static void PushHead(gcptr<CNode>::in p) {
        p->m_pNext = s_pHead;
        s_pHead = p;
        if (s_pTail == nullptr) {
            s_pTail = p;
        }
    }

    static void PushTail(gcptr<CNode>::in p) {
        if (s_pTail) {
            s_pTail->m_pNext = p;
        }
        s_pTail = p;
        if (s_pHead == nullptr) {
            s_pHead = p;
        }
    }

    static gcptr<CNode>::ret PopHead() {
        gcptr<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 nGCCount = hnxgc.GetNumOfGC();
        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 collections.\n",
            BenchTicksToString(bt, false),
            hnxgc.GetNumOfGC() - nGCCount);
    }
};

gcptr<CNode>        CNode::s_pHead;
gcptr<CNode>        CNode::s_pTail;

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

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