Files
UA-.NETStandard/ComIOP/Wrapper/Common/COpcThread.cpp
T
2019-02-14 12:34:33 +02:00

184 lines
4.7 KiB
C++

/* ========================================================================
* Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved.
*
* OPC Foundation MIT License 1.00
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* The complete license agreement can be found here:
* http://opcfoundation.org/License/MIT/1.00/
* ======================================================================*/
#include "StdAfx.h"
#include "COpcThread.h"
//==============================================================================
// Local Functions
static DWORD WINAPI ThreadProc(LPVOID lpParameter)
{
return ((COpcThread*)lpParameter)->Run();
}
//==============================================================================
// COpcThread
// Constructor
COpcThread::COpcThread()
{
m_dwID = NULL;
m_hThread = NULL;
m_hEvent = NULL;
m_pfnControl = NULL;
m_pData = NULL;
m_bWaitingForStop = false;
}
// Destructor
COpcThread::~COpcThread()
{
if (m_hThread != NULL) CloseHandle(m_hThread);
if (m_hEvent != NULL) CloseHandle(m_hEvent);
}
//==============================================================================
// Public Methods
// Start
bool COpcThread::Start(
PfnOpcThreadControl pfnControl,
void* pData,
DWORD dwTimeout,
int iPriority)
{
m_pfnControl = pfnControl;
m_pData = pData;
// no control procedure specified.
if (m_pfnControl == NULL)
{
return false;
}
// thread already running.
if (m_hThread != NULL)
{
return false;
}
// create thread started event.
m_hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (m_hEvent == NULL)
{
return false;
}
// start thread.
m_hThread = CreateThread(
NULL,
NULL,
ThreadProc,
(void*)this,
NULL,
&m_dwID);
if (m_hThread == NULL)
{
return false;
}
// set thread priority.
SetThreadPriority(m_hThread, iPriority);
// wait for thread start.
DWORD dwResult = WaitForSingleObject(m_hEvent, dwTimeout);
if (dwResult != WAIT_OBJECT_0)
{
return false;
}
// reset thread event.
ResetEvent(m_hEvent);
return true;
}
// Stop
void COpcThread::Stop(DWORD dwTimeout)
{
// check if thread is not stopping itself and if thread is running.
if (m_dwID != GetCurrentThreadId() && m_hThread != NULL)
{
m_bWaitingForStop = true;
// post quit message.
PostThreadMessage(m_dwID, WM_QUIT, 0, 0);
// call thread procedure for user defined stop message.
m_pfnControl(NULL, true);
// wait for thread stopped event.
WaitForSingleObject(m_hEvent, dwTimeout);
}
// close handles.
if (m_hThread != NULL) CloseHandle(m_hThread);
if (m_hEvent != NULL) CloseHandle(m_hEvent);
// intialize state.
m_dwID = NULL;
m_hThread = NULL;
m_hEvent = NULL;
m_pfnControl = NULL;
m_pData = NULL;
m_bWaitingForStop = false;
}
// Run
DWORD COpcThread::Run()
{
// initialize message queue.
MSG cMsg; memset(&cMsg, 0, sizeof(cMsg));
PeekMessage(&cMsg, NULL, 0, 0, PM_NOREMOVE);
// signal that the thread started.
SetEvent(m_hEvent);
// call thread procedure.
m_pfnControl(m_pData, false);
// signal that the thread stopped.
CloseHandle(m_hThread);
InterlockedExchange((LONG*)&m_hThread, NULL);
SetEvent(m_hEvent);
return 0;
}
// PostMessage
bool COpcThread::PostMessage(UINT uMsgID, WPARAM wParam, LPARAM lParam)
{
return (PostThreadMessage(m_dwID, uMsgID, wParam, lParam) != 0);
}