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

#include "include/core/SkExecutor.h"
#include "include/private/SkMutex.h"
#include "include/private/SkSemaphore.h"
#include "include/private/SkSpinlock.h"
#include "include/private/SkTArray.h"
#include "src/core/SkMakeUnique.h"
#include <deque>
#include <thread>

#if defined(STARBOARD)
#include "starboard/thread.h"
#endif

namespace {

#if defined(STARBOARD)
// Starboardize std::thread as thread creation is undefined for stub builds.
class SkThread {
public:
    SkThread(SbThreadEntryPoint entry_point, void* context) {
        SbThreadCreate(0,                    // default stack_size.
                       kSbThreadNoPriority,  // default priority.
                       kSbThreadNoAffinity,  // default affinity.
                       true,                 // joinable.
                       "SkThread", entry_point, this);
    }

    bool join() { return SbThreadJoin((SbThread)this, NULL); }
};
#else
typedef std::thread SkThread;
#endif

}  // namespace

#if defined(STARBOARD)
#include "starboard/system.h"
static int num_cores() {
  return SbSystemGetNumberOfProcessors();
}
#else  // defined(STARBOARD)
#if defined(SK_BUILD_FOR_WIN)
    #include "src/core/SkLeanWindows.h"
    static int num_cores() {
        SYSTEM_INFO sysinfo;
        GetNativeSystemInfo(&sysinfo);
        return (int)sysinfo.dwNumberOfProcessors;
    }
#else
    #include <unistd.h>
    static int num_cores() {
        return (int)sysconf(_SC_NPROCESSORS_ONLN);
    }
#endif
#endif  // defined(STARBOARD)

SkExecutor::~SkExecutor() {}

// The default default SkExecutor is an SkTrivialExecutor, which just runs the work right away.
class SkTrivialExecutor final : public SkExecutor {
    void add(std::function<void(void)> work) override {
        work();
    }
};

static SkExecutor* gDefaultExecutor = nullptr;

void SetDefaultTrivialExecutor() {
    static SkTrivialExecutor *gTrivial = new SkTrivialExecutor();
    gDefaultExecutor = gTrivial;
}
SkExecutor& SkExecutor::GetDefault() {
    if (!gDefaultExecutor) {
        SetDefaultTrivialExecutor();
    }
    return *gDefaultExecutor;
}
void SkExecutor::SetDefault(SkExecutor* executor) {
    if (executor) {
        gDefaultExecutor = executor;
    } else {
        SetDefaultTrivialExecutor();
    }
}

// We'll always push_back() new work, but pop from the front of deques or the back of SkTArray.
static inline std::function<void(void)> pop(std::deque<std::function<void(void)>>* list) {
    std::function<void(void)> fn = std::move(list->front());
    list->pop_front();
    return fn;
}
static inline std::function<void(void)> pop(SkTArray<std::function<void(void)>>* list) {
    std::function<void(void)> fn = std::move(list->back());
    list->pop_back();
    return fn;
}

// An SkThreadPool is an executor that runs work on a fixed pool of OS threads.
template <typename WorkList>
class SkThreadPool final : public SkExecutor {
public:
    explicit SkThreadPool(int threads) {
        for (int i = 0; i < threads; i++) {
            fThreads.emplace_back(&Loop, this);
        }
    }

    ~SkThreadPool() override {
        // Signal each thread that it's time to shut down.
        for (int i = 0; i < fThreads.count(); i++) {
            this->add(nullptr);
        }
        // Wait for each thread to shut down.
        for (int i = 0; i < fThreads.count(); i++) {
            fThreads[i].join();
        }
    }

    virtual void add(std::function<void(void)> work) override {
        // Add some work to our pile of work to do.
        {
            SkAutoMutexExclusive lock(fWorkLock);
            fWork.emplace_back(std::move(work));
        }
        // Tell the Loop() threads to pick it up.
        fWorkAvailable.signal(1);
    }

    virtual void borrow() override {
        // If there is work waiting, do it.
        if (fWorkAvailable.try_wait()) {
            SkAssertResult(this->do_work());
        }
    }

private:
    // This method should be called only when fWorkAvailable indicates there's work to do.
    bool do_work() {
        std::function<void(void)> work;
        {
            SkAutoMutexExclusive lock(fWorkLock);
            SkASSERT(!fWork.empty());        // TODO: if (fWork.empty()) { return true; } ?
            work = pop(&fWork);
        }

        if (!work) {
            return false;  // This is Loop()'s signal to shut down.
        }

        work();
        return true;
    }

    static void* Loop(void* ctx) {
        auto pool = (SkThreadPool*)ctx;
        do {
            pool->fWorkAvailable.wait();
        } while (pool->do_work());
        return NULL;
    }

    // Both SkMutex and SkSpinlock can work here.
    using Lock = SkMutex;

    SkTArray<SkThread>    fThreads;
    WorkList              fWork;
    Lock                  fWorkLock;
    SkSemaphore           fWorkAvailable;
};

std::unique_ptr<SkExecutor> SkExecutor::MakeFIFOThreadPool(int threads) {
    using WorkList = std::deque<std::function<void(void)>>;
    return skstd::make_unique<SkThreadPool<WorkList>>(threads > 0 ? threads : num_cores());
}
std::unique_ptr<SkExecutor> SkExecutor::MakeLIFOThreadPool(int threads) {
    using WorkList = SkTArray<std::function<void(void)>>;
    return skstd::make_unique<SkThreadPool<WorkList>>(threads > 0 ? threads : num_cores());
}
