/*
 * Copyright 2012 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "SkRefCnt.h"
#include "SkTRefArray.h"
#include "SkThreadUtils.h"
#include "SkTypes.h"
#include "SkWeakRefCnt.h"
#include "Test.h"

class InstCounterClass {
public:
    InstCounterClass() { fCount = gInstCounter++; }
    InstCounterClass(const InstCounterClass& src) {
        fCount = src.fCount;
        gInstCounter += 1;
    }
    virtual ~InstCounterClass() { gInstCounter -= 1; }

    static int gInstCounter;
    int fCount;
};

int InstCounterClass::gInstCounter;

static void test_refarray(skiatest::Reporter* reporter) {
    REPORTER_ASSERT(reporter, 0 == InstCounterClass::gInstCounter);

    const int N = 10;
    SkTRefArray<InstCounterClass>* array = SkTRefArray<InstCounterClass>::Create(N);

    REPORTER_ASSERT(reporter, 1 == array->getRefCnt());
    REPORTER_ASSERT(reporter, N == array->count());

    REPORTER_ASSERT(reporter, N == InstCounterClass::gInstCounter);
    array->unref();
    REPORTER_ASSERT(reporter, 0 == InstCounterClass::gInstCounter);

    // Now test the copy factory

    int i;
    InstCounterClass* src = new InstCounterClass[N];
    REPORTER_ASSERT(reporter, N == InstCounterClass::gInstCounter);
    for (i = 0; i < N; ++i) {
        REPORTER_ASSERT(reporter, i == src[i].fCount);
    }

    array = SkTRefArray<InstCounterClass>::Create(src, N);
    REPORTER_ASSERT(reporter, 1 == array->getRefCnt());
    REPORTER_ASSERT(reporter, N == array->count());

    REPORTER_ASSERT(reporter, 2*N == InstCounterClass::gInstCounter);
    for (i = 0; i < N; ++i) {
        REPORTER_ASSERT(reporter, i == (*array)[i].fCount);
    }

    delete[] src;
    REPORTER_ASSERT(reporter, N == InstCounterClass::gInstCounter);

    for (i = 0; i < N; ++i) {
        REPORTER_ASSERT(reporter, i == (*array)[i].fCount);
    }
    array->unref();
    REPORTER_ASSERT(reporter, 0 == InstCounterClass::gInstCounter);
}

static void bounce_ref(void* data) {
    SkRefCnt* ref = static_cast<SkRefCnt*>(data);
    for (int i = 0; i < 100000; ++i) {
        ref->ref();
        ref->unref();
    }
}

static void test_refCnt(skiatest::Reporter* reporter) {
    SkRefCnt* ref = new SkRefCnt();

    SkThread thing1(bounce_ref, ref);
    SkThread thing2(bounce_ref, ref);

    thing1.setProcessorAffinity(0);
    thing2.setProcessorAffinity(23);

    SkASSERT(thing1.start());
    SkASSERT(thing2.start());

    thing1.join();
    thing2.join();

    REPORTER_ASSERT(reporter, ref->getRefCnt() == 1);
    ref->unref();
}

static void bounce_weak_ref(void* data) {
    SkWeakRefCnt* ref = static_cast<SkWeakRefCnt*>(data);
    for (int i = 0; i < 100000; ++i) {
        if (ref->try_ref()) {
            ref->unref();
        }
    }
}

static void bounce_weak_weak_ref(void* data) {
    SkWeakRefCnt* ref = static_cast<SkWeakRefCnt*>(data);
    for (int i = 0; i < 100000; ++i) {
        ref->weak_ref();
        ref->weak_unref();
    }
}

static void test_weakRefCnt(skiatest::Reporter* reporter) {
    SkWeakRefCnt* ref = new SkWeakRefCnt();

    SkThread thing1(bounce_ref, ref);
    SkThread thing2(bounce_ref, ref);
    SkThread thing3(bounce_weak_ref, ref);
    SkThread thing4(bounce_weak_weak_ref, ref);

    thing1.setProcessorAffinity(0);
    thing2.setProcessorAffinity(23);
    thing3.setProcessorAffinity(2);
    thing4.setProcessorAffinity(17);

    SkASSERT(thing1.start());
    SkASSERT(thing2.start());
    SkASSERT(thing3.start());
    SkASSERT(thing4.start());

    thing1.join();
    thing2.join();
    thing3.join();
    thing4.join();

    REPORTER_ASSERT(reporter, ref->getRefCnt() == 1);
    REPORTER_ASSERT(reporter, ref->getWeakCnt() == 1);
    ref->unref();
}

DEF_TEST(RefCnt, reporter) {
    test_refCnt(reporter);
    test_weakRefCnt(reporter);
    test_refarray(reporter);
}
