blob: 6393eb41a822406737f51f8c7407f644657a0d2a [file] [log] [blame]
// Copyright (c) 2010 The WebM 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 <windows.h>
#include <windowsx.h>
#include <process.h>
#include <memory>
#include "debugutil.h"
#include "eventutil.h"
#include "threadutil.h"
namespace WebmMfUtil
{
SimpleThread::SimpleThread():
ptr_user_thread_data_(NULL),
ptr_thread_func_(NULL),
thread_hndl_(0),
thread_id_(0)
{
}
SimpleThread::~SimpleThread()
{
}
bool SimpleThread::Running()
{
HANDLE thread_handle = reinterpret_cast<HANDLE>(thread_hndl_);
if (thread_handle && INVALID_HANDLE_VALUE != thread_handle)
{
HRESULT hr = zero_cowait(thread_handle);
if (SUCCEEDED(hr))
{
return false;
}
}
return true;
}
HRESULT SimpleThread::Run(LPTHREAD_START_ROUTINE ptr_thread_func,
LPVOID ptr_data)
{
if (!ptr_thread_func)
return E_INVALIDARG;
ptr_thread_func_ = ptr_thread_func;
ptr_user_thread_data_ = ptr_data;
HRESULT hr = E_FAIL;
thread_hndl_ = _beginthreadex(NULL, 0, ThreadWrapper_,
reinterpret_cast<LPVOID>(this), 0,
&thread_id_);
if (0 != thread_hndl_ && -1 != thread_hndl_)
hr = S_OK;
return hr;
}
UINT WINAPI SimpleThread::ThreadWrapper_(LPVOID ptr_this)
{
if (!ptr_this)
return EXIT_FAILURE;
HRESULT hr = CoInitializeEx(0, COINIT_APARTMENTTHREADED);
if (FAILED(hr))
{
DBGLOG("CoInitializeEx failed");
return hr;
}
SimpleThread* ptr_sthread = reinterpret_cast<SimpleThread*>(ptr_this);
if (!ptr_sthread || !ptr_sthread->ptr_thread_func_)
return EXIT_FAILURE;
DWORD thread_result =
ptr_sthread->ptr_thread_func_(ptr_sthread->ptr_user_thread_data_);
CoUninitialize();
return thread_result;
}
HRESULT RefCountedThread::Create(RefCountedThread** ptr_instance)
{
*ptr_instance = new RefCountedThread();
if (!*ptr_instance)
return E_OUTOFMEMORY;
(*ptr_instance)->AddRef();
return S_OK;
}
RefCountedThread::RefCountedThread():
ref_count_(0)
{
}
RefCountedThread::~RefCountedThread()
{
}
UINT RefCountedThread::AddRef()
{
return InterlockedIncrement(&ref_count_);
}
UINT RefCountedThread::Release()
{
UINT ref_count = InterlockedDecrement(&ref_count_);
if (ref_count == 0)
{
delete this;
}
return ref_count;
}
StoppableThread::StoppableThread():
ptr_event_(NULL)
{
}
StoppableThread::~StoppableThread()
{
}
HRESULT StoppableThread::Create(StoppableThread **ptr_instance)
{
StoppableThread* ptr_thread = new (std::nothrow) StoppableThread();
if (!ptr_thread)
{
DBGLOG("NULL thread, no memory!");
return E_OUTOFMEMORY;
}
ptr_event_.reset(new (std::nothrow) EventWaiter());
if (!ptr_event_.get())
{
DBGLOG("NULL event, no memory!");
return E_OUTOFMEMORY;
}
HRESULT hr;
CHK(hr, ptr_event_->Create());
if (SUCCEEDED(hr))
{
*ptr_instance = ptr_thread;
}
return hr;
}
bool StoppableThread::StopRequested()
{
if (ptr_event_.get() && Running())
{
if (FAILED(ptr_event_->ZeroWait()))
{
return false;
}
}
return true;
}
} // WebmMfUtil namespace