当前位置: 首页 > article >正文

windows核心编程,纤程使用---->UNIX服务器应用程序移植到Windows中

windows核心编程,纤程使用

Microsoft公司给Windows添加了一种纤程,以便能够非常容易地将现有的 UNIX服务器应用程序移植到Windows中。UNIX服务器应用程序属于单线程应用程序(由Windows定义),但是它能够为多个客户程序提供服务。换句话说,UNIX应用程序的开发人员已经创建了他们自己的线程结构库,他们能够使用这种线程结构库来仿真纯线程。该线程包能够创建多个堆栈保存某些CPU寄存器,并且在它们之间进行切换,以便为客户机请求提供服务。显然,若要取得最佳的性能,这些 UNIX应用程序必须重新设计,仿真的线程库应该用Windows提供的纯线程来替代。然而,这种重新设计需要花费数月甚至更长的时间才能完成因此许多公司首先将它们现有的 UNIX代码移植到Windows中,这样就能够将某些应用软件推
向Windows市场。当你将UNIX代码移植到Windows中时,一些问题就会因此而产生。尤其是 Windows管理线程的内存栈的方法要比简单地分配内存复杂得多。 Windows内存栈开始时的物理存储器的容量比较小,然后根据需要逐步扩大。这个过程在第 16章“线程的堆栈”中详细介绍。由于结构化异常处理机制的原因,代码的移植就更加复杂了。
为了能够更快和更正确地将它们的代码移植到 Windows中,Microsoft公司在操作系统中添加了纤程。本章将要介绍纤程的概念、负责操作纤程的函数以及如何利用纤程的特性。要记住如果有设计得更好的使用Windows自身线程的应用程序,那么应该避免使用纤程。

文章目录

  • windows核心编程,纤程使用


/*
12_Counter.cpp
纤程使用的 
*/
#include "..\CommonFiles\CmnHdr.h"     /* See Appendix A. */
#include <WindowsX.h>
#include <tchar.h>
#include "Resource.h"
#include <StrSafe.h>
/
//后台处理过程可能的状态
typedef	enum
{
	BPS_STARTOVER,	//重新开始后台处理过程
	BPS_CONTINUE,	//继续后台处理过程
	BPS_DONE		//后台处理结束
}BKGNDPROCSTATE;

typedef	struct
{
	PVOID pFiberUI;		//用户纤程对象(上下文)
	HWND hwnd;			//UI窗口句柄
	BKGNDPROCSTATE bps;//后台处理过程的状态
}FIBERINFO,*PFIBERINFO;

//全局变量
//用用程序运行章台,改变了可以由UI纤程直接访问,后台处理程序可间间访问
FIBERINFO g_FiberInfo;
//纤程局部存储索引FLS槽
DWORD g_dwSlot = 0;
/
VOID WINAPI LogMessage(PVOID pFlsValue);//FlsAlloc中指定的回调函数
void WINAPI FiberFunc(LPVOID lpParamter);
BOOL Dlg_OnInitDialog(HWND hwnd, HWND hwndFocus, LPARAM lParam);
void Dlg_OnCommand(HWND hwnd, int id, HWND hwndCtl, UINT codeNotify);
INT_PTR WINAPI Dlg_Proc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);

/
int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PTSTR pszCmdLine, int)
{
	//后台处理的纤程对象
	PVOID pFiberCounter = NULL;

	//主线程转为主线程
	g_FiberInfo.pFiberUI = ConvertThreadToFiber(NULL);
	//如果FLS插槽正在使用中,则在删除线程,线程退出已经释放FLS所有时调用FLS
	g_dwSlot = FlsAlloc(LogMessage);//FLS索引时调用FlsCallback
	FlsSetValue(g_dwSlot, (PVOID)TEXT("UI Fiber"));

	//创建应用程序UI窗口
	g_FiberInfo.hwnd = CreateDialog(hInstance, MAKEINTRESOURCE(IDD_COUNTER), 
		NULL,Dlg_Proc);

	//更新显示当前正在运行的纤程
	SetDlgItemText(g_FiberInfo.hwnd, IDC_FIBER, TEXT("用户界面纤程"));
	//初始化,当前没有后台处理任务
	g_FiberInfo.bps = BPS_DONE;


	//消息循环
	BOOL fQuit = FALSE;
	while (!fQuit)
	{
		//UI消息此后台处理过程由更高的优先级
		MSG msg;
		if (PeekMessage(&msg,NULL,0,0,PM_REMOVE))
		{
			if (!IsDialogMessage(g_FiberInfo.hwnd,&msg))
			{
				TranslateMessage(&msg);
				DispatchMessage(&msg);
			}
			fQuit = (msg.message == WM_QUIT);

			if (fQuit)
			{
				//释放FLS槽
				FlsFree(g_dwSlot);
				//停止后台处理程序
				if (pFiberCounter != NULL)
				{
					DeleteFiber(pFiberCounter);
					pFiberCounter = NULL;
				}
				//退出纤程模式并返回单线程模式
				ConvertFiberToThread();
				g_FiberInfo.pFiberUI = NULL;
			}
		}
		else //没有UI消息的,检查后台过程的状态
		{
			//switch 后台处理状态
			switch (g_FiberInfo.bps)
			{
			case BPS_DONE:
				//没有后台过程则等待UI事件
				WaitMessage();
				break;
			case BPS_STARTOVER:
				//用户改变了计数值
				//先取消当前的后台处理程序,然后从新开始后台处理
				if (pFiberCounter != NULL)
				{
					DeleteFiber(pFiberCounter);
					pFiberCounter = NULL;
				}
				//将主线程转换为纤程
				if (g_FiberInfo.pFiberUI = NULL)
				{
					g_FiberInfo.pFiberUI = ConvertThreadToFiber(NULL);
				}
				//logMessage
				LogMessage((PVOID)TEXT("转换UI现场为纤程中..."));
				//创建一个细你的重新计算纤程
				pFiberCounter = CreateFiber(0, FiberFunc, &g_FiberInfo);
				//后台处理进程开始
				g_FiberInfo.bps = BPS_CONTINUE;
				//注意这里没有break
			case BPS_CONTINUE:
				//运行后台处理开始
				SwitchToFiber(pFiberCounter);
				//后台处理被暂停(可能因为UI消息或计算完成被自动暂停
				// 显示哪个纤程正在被执行
				SetDlgItemText(g_FiberInfo.hwnd, IDC_FIBER, 
					TEXT("用户界面"));

				if (g_FiberInfo.bps == BPS_DONE)
				{
					//后台处理已完成。请删除光纤,以便下次重新启动处理。
					DeleteFiber(pFiberCounter);
					pFiberCounter = NULL;

					//退出光纤模式,返回简单线程模式
					ConvertFiberToThread();
					g_FiberInfo.pFiberUI = NULL;
				}
				break;
			}// 打开后台处理状态
		}//不存在UI消息
	} // 当窗口仍然存在时

	DestroyWindow(g_FiberInfo.hwnd);
	return 0;
}

INT_PTR WINAPI Dlg_Proc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {

	switch (uMsg) {
		chHANDLE_DLGMSG(hwnd, WM_INITDIALOG, Dlg_OnInitDialog);
		chHANDLE_DLGMSG(hwnd, WM_COMMAND, Dlg_OnCommand);
	}
	return(FALSE);
}

VOID WINAPI LogMessage(PVOID pFlsValue)
{
	TCHAR szMsg[MAX_PATH];

	// Check if we are in a fiber because this function can be called 
	// outside a fiber execution
	if (IsThreadAFiber())
	{
		PVOID pFiberData = GetCurrentFiber();
		PCTSTR pszFlsValue = (PCTSTR)FlsGetValue(g_dwSlot);
		StringCchPrintf(szMsg, _countof(szMsg), TEXT("[0x%x - %s] %s\n"),
			pFiberData,
			(pszFlsValue == NULL) ? TEXT("'Null value'") : (PCTSTR)pszFlsValue,
			(pFlsValue == NULL) ? TEXT("'Null value'") : (PCTSTR)pFlsValue);
	}
	else
	{
		StringCchCopy(szMsg, _countof(szMsg), TEXT("No more a fiber...\n"));
	}

	OutputDebugString(szMsg);

}
 
void WINAPI FiberFunc(PVOID pvParam) {

	PFIBERINFO pFiberInfo = (PFIBERINFO)pvParam;

	FlsSetValue(g_dwSlot, TEXT("Computation"));
	LogMessage(TEXT("entering computation..."));

	// Update the window showing which fiber is executing.
	SetDlgItemText(pFiberInfo->hwnd, IDC_FIBER, TEXT("Recalculation"));

	// Get the current count in the EDIT control.
	int nCount = GetDlgItemInt(pFiberInfo->hwnd, IDC_COUNT, NULL, FALSE);

	// Count from 0 to nCount, updating the STATIC control.
	for (int x = 0; x <= nCount; x++) {

		// UI events have higher priority than counting.
		// If there are any UI events, handle them ASAP.
		if (HIWORD(GetQueueStatus(QS_ALLEVENTS)) != 0) {

			// The UI fiber has something to do; temporarily
			// pause counting and handle the UI events.
			SwitchToFiber(pFiberInfo->pFiberUI);

			// The UI has no more events; continue counting.
			SetDlgItemText(pFiberInfo->hwnd, IDC_FIBER, TEXT("Recalculation"));
		}

		// Update the STATIC control with the most recent count.
		SetDlgItemInt(pFiberInfo->hwnd, IDC_ANSWER, x, FALSE);

		// Sleep for a while to exaggerate the effect; remove 
		// the call to Sleep in production code.
		Sleep(200);
	}

	// Indicate that counting is complete.
	pFiberInfo->bps = BPS_DONE;

	// Reschedule the UI thread. When the UI thread is running
	// and has no events to process, the thread is put to sleep.
	// NOTE: If we just allow the fiber function to return,
	// the thread and the UI fiber die -- we don't want this!
	SwitchToFiber(pFiberInfo->pFiberUI);
}

BOOL Dlg_OnInitDialog(HWND hwnd, HWND hwndFocus, LPARAM lParam) {

	chSETDLGICONS(hwnd, IDI_COUNTER);

	SetDlgItemInt(hwnd, IDC_COUNT, 0, FALSE);
	return(TRUE);
}


///


void Dlg_OnCommand(HWND hwnd, int id, HWND hwndCtl, UINT codeNotify) {

	switch (id) {
	case IDCANCEL:
		PostQuitMessage(0);
		break;

	case IDC_COUNT:
		if (codeNotify == EN_CHANGE) {

			// When the user changes the count, start the 
			// background processing over from the beginning.
			g_FiberInfo.bps = BPS_STARTOVER;
		}
		break;
	}
}


http://www.kler.cn/a/289168.html

相关文章:

  • Linux源码阅读笔记-V4L2框架基础介绍
  • git下载慢下载不了?Git国内国外下载地址镜像,git安装视频教程
  • CommandLineParser 使用
  • STM32单片机WIFI语音识别智能衣柜除湿消毒照明
  • 【日志】392.判断子序列
  • 金价大跌,特朗普胜选或成导火索
  • 在更新python虚拟环境pip版本时,由于更新失败导致pip丢失的修复
  • GD - EmbeddedBuilder - 给已有工程换MCU
  • 【IPV6从入门到起飞】2-1 获取你的IPV6(手机、CPE等)
  • LVS Keepalived nginx haproxy 区别
  • 设计模式-原型适配器桥接外观
  • 基于大数据分析景区消费行为影响因素研究【消费等级预测、携程,去哪网数据抓取】
  • 亿图图示下载安装教程EdrawMax Pro 13版超详细图文教程
  • 前端面试:webSocket如何兼容低浏览器?
  • 安防监控视频平台LntonAIServer视频智能分析平台新增视频质量诊断功能
  • 机器学习数学公式推导之降维
  • Python加载 TorchScript 格式的 ResNet18 模型分类该模型进行预测并输出预测的类别和置信度
  • 【运维监控】prometheus+node exporter+grafana 监控linux机器运行情况(2)
  • 【wsl2】从C盘迁移到G盘
  • redroid搭建云手机学习笔记(一)
  • C++ ─── List的模拟实现
  • django orm的Q和~Q的数据相加并不一定等于总数
  • Golang | Leetcode Golang题解之第380题O(1)时间插入、删除和获取随机元素
  • [SDK]-按钮静态文本与编辑框控件
  • Vue-cli的使用
  • MySQL三大日志详解