⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 opcdrvthread.cpp

📁 基于Intellution开发包的开发的OPC服务器
💻 CPP
字号:
// OpcDrvThread.cpp
//
//   This file contains functions used to initialize a server
// object for use with the background "helper" thread.
//
//	(c) COPYRIGHT 1996-1998, INTELLUTION INC.
// ALL RIGHTS RESERVED
//
//
//	Functions defined in this module:
//
//			InitServerSlot()
//			DeleteServerSlot()
//			FindServerSlot()
//			ClearServerSlot()
//			GetServerSlotCount()
//			CalcServerBandWidthThread()
//			ChangeDriverThreadPriority()
//
//
//
// Modification Log:
//	Vers	Date		By		Notes
//	----	--------	---		-----
//	1.0		08/26/97	jra		Created
//	1.3		03/10/98	jra		Modified to be wizard generated and driver specific.
//	7.11	11/03/98	jra		Modified ChangeDriverThreadPriority()to to change the
//								priority class because Workspace can't handle having its
//								priority tweaked.
//	7.13	02/29/00	jra		Added DeleteServerSlot() to perform shutdown cleanup and
//								removed call to DeleteCriticalSecion() in ClearServerSlot()
//
//

#define WIN32_LEAN_AND_MEAN

#include "OpcStdAfx.h"
#include "OPCDrvThread.h"
#include "OPCDrv.h"
#include <process.h>

// Global variables
//
static CMap<int, int, COPCDrvServer*, COPCDrvServer*&> g_mapServers;
static int					g_nLocation		= 1;
static CRITICAL_SECTION		g_csServerMap;
static DWORD				g_dwBwThreadId	= 0;
static HANDLE				g_hBwThread		= 0;
static BOOL					g_bKeepRunning	= TRUE;

static UINT __stdcall CalcServerBandWidthThread(void *pParam);
static inline void Lock(void)	{ EnterCriticalSection(&g_csServerMap); }
static inline void UnLock(void)	{ LeaveCriticalSection(&g_csServerMap); }


////////////////////////////////////////////////////////////////
// InitServerSlot()
//
// @desc	Initialization at startup
//
// @parm	none
//
// @retval	void
//
// TODO:	Any additional initialization
//
////////////////////////////////////////////////////////////////
void InitServerSlot(void)
{
	// We initialize the hash table to an arbitrary prime number,
	// init the critical section, etc...
	g_mapServers.InitHashTable(13);
	InitializeCriticalSection(&g_csServerMap);
}


////////////////////////////////////////////////////////////////
// DeleteServerSlot()
//
// @desc	Cleanup at shutdown
//
// @parm	none
//
// @retval	void
//
// TODO:	Any additional cleanup
//
////////////////////////////////////////////////////////////////
void DeleteServerSlot(void)
{
	// Delete the critical section
	DeleteCriticalSection(&g_csServerMap);
}


////////////////////////////////////////////////////////////////
// FindServerSlot()
//
// @desc	Adds the server to the map
//
// @parm	IN	int			  *	| pnSlotNumber	| Returned location in the map
// @parm	IN	COPCDrvServer *	| pServer		| Pointer to the server to add
//
////////////////////////////////////////////////////////////////
BOOL FindServerSlot(int				*pnSlotNumber, 
					COPCDrvServer	*pServer)
{
	*pnSlotNumber = g_nLocation++;

	Lock();
	g_mapServers.SetAt(*pnSlotNumber, pServer);
	UnLock();

	// If this is the first server being added, then start the
	// bandwidth thread.
	if (NULL == g_hBwThread)
	{
		g_dwBwThreadId = 0;
		unsigned int nAddress = 0;
		g_hBwThread = (HANDLE)_beginthreadex(NULL,
											 0,
											 CalcServerBandWidthThread, 
											 NULL, 
											 0, 
											 &nAddress);
	}

	return TRUE;
}


////////////////////////////////////////////////////////////////
// ClearServerSlot()
// 
// @desc	'UnRegister' the server
//
// @parm	IN	int	| nSlotNumber | Location in the map
//
// @retval	void
//
////////////////////////////////////////////////////////////////
void ClearServerSlot(IN	int	nSlotNumber)
{
	int	nNumServers;


	Lock();
	g_mapServers.RemoveKey(nSlotNumber);
	nNumServers = g_mapServers.GetCount();
	UnLock();

	// If the map is now empty, then the last server object has
	// been released, so shutdown the bandwidth thread.
	if (0 == nNumServers)
	{
		g_bKeepRunning = FALSE;
		if (WaitForSingleObject(g_hBwThread, 
								THREAD_SHUTDOWN_TIME) == WAIT_TIMEOUT)
		{
			TerminateThread(g_hBwThread, 0);
		}

		g_dwBwThreadId = 0;
		g_hBwThread = NULL;
	}
}


////////////////////////////////////////////////////////////////
// GetServerSlotCount()
//
// @desc	Returns the number of instanciated server objects
//
// @parm	none
//
// @retval	int
//
////////////////////////////////////////////////////////////////
int	GetServerSlotCount(void)
{
	return g_mapServers.GetCount();
}


////////////////////////////////////////////////////////////////
// CalcServerBandWidthThread()
//
// @desc	This thread calculates the bandwidth for all server objects.
//			The bandwidth is calculated as follows:
//
//			Bandwidth = (# Groups Processed / # Groups Updated) * 100%
//
// @parm	IN void *	| pParam	| Passed in by _beginthreadex()
//
// @retval	UINT
//
////////////////////////////////////////////////////////////////
UINT __stdcall CalcServerBandWidthThread(IN	void	*pParam)
{
	DWORD			dwNumGroupsProcessed	= 0,
					dwTotalPasses			= 0,
					dwPriority				= 13;
	int				nKey					= 0;
	POSITION		posServer				= NULL;
	COPCDrvServer	*pServer				= NULL;


	// Increase the thread priority because this thread will do very little
	if (!ChangeDriverThreadPriority(dwPriority))
	{
		LogEventMessage(TEXT("Unable to change bandwidth thread priority"),
						TEXT("OPCNIO"),
						6);
	}

	// Get the id of this thread
	g_dwBwThreadId = GetCurrentThreadId();

	while(g_bKeepRunning)
	{
		Sleep(500);

		Lock();

		posServer = g_mapServers.GetStartPosition();
		while ((NULL != posServer) && (g_bKeepRunning))
		{
			g_mapServers.GetNextAssoc(posServer, nKey, pServer);

			//
			// We don't bother to lock the server here because this is just
			// a diagnostic estimate of the percent bandwidth that the server
			// is running at.
			//

			// Get temp copies for calculations and make sure they are valid
			if ((0 == (dwTotalPasses = pServer->m_dwTotalPasses)) ||
				(0 == (dwNumGroupsProcessed = pServer->m_dwNumGroupsProcessed)))
			{
				pServer->m_dwBandwidth = 0;
			}
			else
			{
				pServer->m_dwBandwidth = 
					(DWORD)(((float)dwNumGroupsProcessed / (float)dwTotalPasses) * 100);
			}
			pServer->m_dwTotalPasses = pServer->m_dwNumGroupsProcessed = 0;
		}

		UnLock();
	}

	_endthreadex(0);
	return 0;
}


////////////////////////////////////////////////////////////////
// ChangeDriverThreadPriority()
// 
// @desc	This function will adjust the priority of the thread from which
//			it is called. It takes a priority from 1 to 15 and attempts to
//			change the class and priority to come as close as possible to
//			the selected priority.
//
// @parm	IN DWORD	| dwPriority	| New thread priority (1 - 15)
//
// @retval	BOOL	| TRUE  - Priority successfully changed
// @retval	BOOL	| FALSE - Error
//
////////////////////////////////////////////////////////////////
BOOL ChangeDriverThreadPriority(IN	DWORD	dwPriority)
{
	DWORD dwClassLevel,
		  dwPriorityLevel;

	switch (dwPriority)
	{
	case 1:
		dwClassLevel = IDLE_PRIORITY_CLASS;
		dwPriorityLevel = THREAD_PRIORITY_IDLE;
		break;
	case 2:
		dwClassLevel = IDLE_PRIORITY_CLASS;
		dwPriorityLevel = THREAD_PRIORITY_LOWEST;
		break;
	case 3:
		dwClassLevel = IDLE_PRIORITY_CLASS;
		dwPriorityLevel = THREAD_PRIORITY_BELOW_NORMAL;
		break;
	case 4:
		dwClassLevel = IDLE_PRIORITY_CLASS;
		dwPriorityLevel = THREAD_PRIORITY_NORMAL;
		break;
	case 5:
		dwClassLevel = NORMAL_PRIORITY_CLASS;
		dwPriorityLevel = THREAD_PRIORITY_LOWEST;
		break;
	case 6:
		dwClassLevel = NORMAL_PRIORITY_CLASS;
		dwPriorityLevel = THREAD_PRIORITY_BELOW_NORMAL;
		break;
	case 7:
		dwClassLevel = NORMAL_PRIORITY_CLASS;
		dwPriorityLevel = THREAD_PRIORITY_NORMAL;
		break;
	case 8:
		dwClassLevel = NORMAL_PRIORITY_CLASS;
		dwPriorityLevel = THREAD_PRIORITY_ABOVE_NORMAL;
		break;
	case 9:
		dwClassLevel = NORMAL_PRIORITY_CLASS;
		dwPriorityLevel = THREAD_PRIORITY_HIGHEST;
		break;
	case 10:
		dwClassLevel = NORMAL_PRIORITY_CLASS;
		dwPriorityLevel = THREAD_PRIORITY_HIGHEST;
		break;
	case 11:
		dwClassLevel = HIGH_PRIORITY_CLASS;
		dwPriorityLevel = THREAD_PRIORITY_LOWEST;
		break;
	case 12:
		dwClassLevel = HIGH_PRIORITY_CLASS;
		dwPriorityLevel = THREAD_PRIORITY_BELOW_NORMAL;
		break;
	case 13:
		dwClassLevel = HIGH_PRIORITY_CLASS;
		dwPriorityLevel = THREAD_PRIORITY_NORMAL;
		break;
	case 14:
		dwClassLevel = HIGH_PRIORITY_CLASS;
		dwPriorityLevel = THREAD_PRIORITY_ABOVE_NORMAL;
		break;
	case 15:
		dwClassLevel = HIGH_PRIORITY_CLASS;
		dwPriorityLevel = THREAD_PRIORITY_HIGHEST;
		break;
	default:
		return(FALSE);
		break;
	}

	// jra 110398
	// Remove call to SetPriorityClass() because Workspace can't have it's
	// priority changed.
//	if (SetPriorityClass(GetCurrentProcess(), dwClassLevel))
//	{
		return(SetThreadPriority(GetCurrentThread(), dwPriorityLevel));
//	}

	return(FALSE);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -