/*
 * Copyright (C) 2010, 2015 Apple Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 * THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "config.h"
#include "WebCoreThreadRun.h"

#if PLATFORM(IOS_FAMILY)

#include "WebCoreThreadInternal.h"
#include <mutex>
#include <wtf/Condition.h>
#include <wtf/Lock.h>
#include <wtf/Vector.h>

namespace {

class WebThreadBlockState {
public:
    WebThreadBlockState()
        : m_completed(false)
    {
    }

    void waitForCompletion()
    {
        std::unique_lock<Lock> lock(m_stateMutex);

        m_completionConditionVariable.wait(lock, [this] { return m_completed; });
    }

    void setCompleted()
    {
        auto locker = holdLock(m_stateMutex);

        ASSERT(!m_completed);
        m_completed = true;
        m_completionConditionVariable.notifyOne();
    }

private:
    Lock m_stateMutex;
    Condition m_completionConditionVariable;
    bool m_completed;
};

class WebThreadBlock {
public:
    WebThreadBlock(void (^block)(void), WebThreadBlockState* state)
        : m_block(Block_copy(block))
        , m_state(state)
    {
    }

    WebThreadBlock(const WebThreadBlock& other)
        : m_block(Block_copy(other.m_block))
        , m_state(other.m_state)
    {
    }

    WebThreadBlock& operator=(const WebThreadBlock& other)
    {
        void (^oldBlock)() = m_block;
        m_block = Block_copy(other.m_block);
        Block_release(oldBlock);
        m_state = other.m_state;
        return *this;
    }

    ~WebThreadBlock()
    {
        Block_release(m_block);
    }

    void operator()() const
    {
        m_block();
        if (m_state)
            m_state->setCompleted();
    }

private:
    void (^m_block)(void);
    WebThreadBlockState* m_state;
};

}

extern "C" {

typedef WTF::Vector<WebThreadBlock> WebThreadRunQueue;

static Lock runQueueMutex;
static CFRunLoopSourceRef runSource;
static WebThreadRunQueue* runQueue;

static void HandleRunSource(void *info)
{
    UNUSED_PARAM(info);
    ASSERT(WebThreadIsCurrent());
    ASSERT(runSource);
    ASSERT(runQueue);

    WebThreadRunQueue queueCopy;
    {
        auto locker = holdLock(runQueueMutex);
        queueCopy = *runQueue;
        runQueue->clear();
    }

    for (const auto& block : queueCopy)
        block();
}

static void _WebThreadRun(void (^block)(void), bool synchronous)
{
    if (WebThreadIsCurrent() || !WebThreadIsEnabled()) {
        block();
        return;
    }

    ASSERT(runSource);
    ASSERT(runQueue);

    WebThreadBlockState* state = 0;
    if (synchronous)
        state = new WebThreadBlockState;

    {
        auto locker = holdLock(runQueueMutex);
        runQueue->append(WebThreadBlock(block, state));
    }

    CFRunLoopSourceSignal(runSource);
    CFRunLoopWakeUp(WebThreadRunLoop());

    if (synchronous) {
        state->waitForCompletion();
        delete state;
    }
}

void WebThreadRun(void (^block)(void))
{
    _WebThreadRun(block, false);
}

void WebThreadInitRunQueue()
{
    ASSERT(!runQueue);
    ASSERT(!runSource);

    static dispatch_once_t pred;
    dispatch_once(&pred, ^{
        runQueue = new WebThreadRunQueue;

        CFRunLoopSourceContext runSourceContext = {0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, HandleRunSource};
        runSource = CFRunLoopSourceCreate(NULL, -1, &runSourceContext);
        CFRunLoopAddSource(WebThreadRunLoop(), runSource, kCFRunLoopDefaultMode);
    });
}

}

#endif // PLATFORM(IOS_FAMILY)
