/*
 *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "thread_win.h"

#include <assert.h>
#include <process.h>
#include <stdio.h>
#include <windows.h>

#include "set_thread_name_win.h"
#include "trace.h"

#if defined(_WIN32)
// VS 2005: Disable warnings for default initialized arrays.
#pragma warning(disable:4351)
#endif

namespace webrtc {
ThreadWindows::ThreadWindows(ThreadRunFunction func, ThreadObj obj,
                             ThreadPriority prio, const char* threadName)
    : ThreadWrapper(),
      _runFunction(func),
      _obj(obj),
      _alive(false),
      _dead(true),
      _doNotCloseHandle(false),
      _prio(prio),
      _event(NULL),
      _thread(NULL),
      _id(0),
      _name(),
      _setThreadName(false)
{
    _event = EventWrapper::Create();
    _critsectStop = CriticalSectionWrapper::CreateCriticalSection();
    if (threadName != NULL)
    {
        // Set the thread name to appear in the VS debugger.
        _setThreadName = true;
        strncpy(_name, threadName, kThreadMaxNameLength);
    }
}

ThreadWindows::~ThreadWindows()
{
#ifdef _DEBUG
    assert(!_alive);
#endif
    if (_thread)
    {
        CloseHandle(_thread);
    }
    if(_event)
    {
        delete _event;
    }
    if(_critsectStop)
    {
        delete _critsectStop;
    }
}

uint32_t ThreadWrapper::GetThreadId() {
  return GetCurrentThreadId();
}

unsigned int WINAPI ThreadWindows::StartThread(LPVOID lpParameter)
{
    static_cast<ThreadWindows*>(lpParameter)->Run();
    return 0;
}

bool ThreadWindows::Start(unsigned int& threadID)
{
    _doNotCloseHandle = false;

    // Set stack size to 1M
    _thread=(HANDLE)_beginthreadex(NULL, 1024*1024, StartThread, (void*)this, 0,
                                   &threadID);
    if(_thread == NULL)
    {
        return false;
    }
    _id = threadID;
    _event->Wait(INFINITE);

    switch(_prio)
    {
    case kLowPriority:
        SetThreadPriority(_thread, THREAD_PRIORITY_BELOW_NORMAL);
        break;
    case kNormalPriority:
        SetThreadPriority(_thread, THREAD_PRIORITY_NORMAL);
        break;
    case kHighPriority:
        SetThreadPriority(_thread, THREAD_PRIORITY_ABOVE_NORMAL);
        break;
    case kHighestPriority:
        SetThreadPriority(_thread, THREAD_PRIORITY_HIGHEST);
        break;
    case kRealtimePriority:
        SetThreadPriority(_thread, THREAD_PRIORITY_TIME_CRITICAL);
        break;
    };
    return true;
}

bool ThreadWindows::SetAffinity(const int* processorNumbers,
                                const unsigned int amountOfProcessors)
{
    DWORD_PTR processorBitMask = 0;
    for(unsigned int processorIndex = 0;
        processorIndex < amountOfProcessors;
        processorIndex++)
    {
        // Convert from an array with processor numbers to a bitmask
        // Processor numbers start at zero.
        // TODO (hellner): this looks like a bug. Shouldn't the '=' be a '+='?
        // Or even better |=
        processorBitMask = 1 << processorNumbers[processorIndex];
    }
    return SetThreadAffinityMask(_thread,processorBitMask) != 0;
}

void ThreadWindows::SetNotAlive()
{
    _alive = false;
}

bool ThreadWindows::Shutdown()
{
    DWORD exitCode = 0;
    BOOL ret = TRUE;
    if (_thread)
    {
        ret = TerminateThread(_thread, exitCode);
        _alive = false;
        _dead = true;
        _thread = NULL;
    }
    return ret == TRUE;
}

bool ThreadWindows::Stop()
{
    _critsectStop->Enter();
    // Prevents the handle from being closed in ThreadWindows::Run()
    _doNotCloseHandle = true;
    _alive = false;
    bool signaled = false;
    if (_thread && !_dead)
    {
        _critsectStop->Leave();
        // Wait up to 2 seconds for the thread to complete.
        if( WAIT_OBJECT_0 == WaitForSingleObject(_thread, 2000))
        {
            signaled = true;
        }
        _critsectStop->Enter();
    }
    if (_thread)
    {
        CloseHandle(_thread);
        _thread = NULL;
    }
    _critsectStop->Leave();

    if (_dead || signaled)
    {
        return true;
    }
    else
    {
        return false;
    }
}

void ThreadWindows::Run()
{
    _alive = true;
    _dead = false;
    _event->Set();

    // All tracing must be after _event->Set to avoid deadlock in Trace.
    if (_setThreadName)
    {
        WEBRTC_TRACE(kTraceStateInfo, kTraceUtility, _id,
                     "Thread with name:%s started ", _name);
        SetThreadName(-1, _name); // -1, set thread name for the calling thread.
    }else
    {
        WEBRTC_TRACE(kTraceStateInfo, kTraceUtility, _id,
                     "Thread without name started");
    }

    do
    {
        if (_runFunction)
        {
            if (!_runFunction(_obj))
            {
                _alive = false;
            }
        } else {
            _alive = false;
        }
    } while(_alive);

    if (_setThreadName)
    {
        WEBRTC_TRACE(kTraceStateInfo, kTraceUtility, _id,
                     "Thread with name:%s stopped", _name);
    } else {
        WEBRTC_TRACE(kTraceStateInfo, kTraceUtility,_id,
                     "Thread without name stopped");
    }

    _critsectStop->Enter();

    if (_thread && !_doNotCloseHandle)
    {
        HANDLE thread = _thread;
        _thread = NULL;
        CloseHandle(thread);
    }
    _dead = true;

    _critsectStop->Leave();
};
} // namespace webrtc
