首页 > 其他分享 >多线程实践篇

多线程实践篇

时间:2022-12-21 14:22:57浏览次数:44  
标签:WINDOWS void 实践 PLATFORM endif MThread 多线程 hThread

这篇文章有参考ue5源码和其他源码。

多线程同步.h文件

/**
	* 关键段 用户模式下同步对象,除非竞争非常激烈,否则不会进入内核模式
	*/
	class SYSTEM_API MCriticalSection
	{
#if WINDOWS_PLATFORM  //平台宏
		CRITICAL_SECTION m_CriticalSection;
#endif	
	public:
		inline MCriticalSection(void)
		{
#ifdef WINDOWS_PLATFORM
			//使用前必须被初始化,如果未初始化CRITICAL_SECTION将不可预料
			InitializeCriticalSection(&m_CriticalSection);
			//设置自旋锁,循环4000次
			SetCriticalSectionSpinCount(&m_CriticalSection, 4000);
#endif
		}
		inline ~MCriticalSection()
		{
#ifdef WINDOWS_PLATFORM
			//会重置结构中的成员变量
			DeleteCriticalSection(&m_CriticalSection);
#endif
		}
		inline void Lock(void)
		{
#ifdef WINDOWS_PLATFORM
			//以原子的方式检查结构中的成员变量,这些变量表示是否有线程在访问资源已经哪个线程在访问资源
			EnterCriticalSection(&m_CriticalSection);
#endif
		}
		inline bool TryLock()
		{
			//不让调用线程等待,返回是否允许访问资源
			return TryEnterCriticalSection(&m_CriticalSection);
		}
		inline void Unlock(void)
		{
#ifdef WINDOWS_PLATFORM
			//检查结构内存的成员变量同时将获准访问共享资源的计数减一,如果计数器大于0则直接返回,等于0 更新成员变量,表示没有任何线程在访问被保护的资源
			LeaveCriticalSection(&m_CriticalSection);
#endif
		}
		class Locker
		{
		public:
			Locker(MCriticalSection& inCriticalSection)
				:in_criticalSection(inCriticalSection)
			{
				in_criticalSection.Lock();
			}
			~Locker()
			{
				in_criticalSection.Unlock();
			}
		private:
			MCriticalSection& in_criticalSection;
		};
	};

多线程.h文件

#pragma once
#include "MSynchronize.h"
namespace Unknown
{
	enum Priority :UINT8
	{
		Low = 20u,
		Normal,
		High,
	};
	enum ThreadState :UINT8
	{
		TS_START,
		TS_SUSPEND,
		TS_STOP,
	};
	class SYSTEM_API MThread
	{
	public:
		MThread();
		virtual ~MThread();

		void SetPriority(Priority p);

		Priority GetPriority() const;

		void SetStackSize(unsigned int uiSize);

		unsigned int GetStackSize() const;

		void Start();

		void Suspend();

		bool IsRunning() const;
		static void Sleep(DWORD dwMillseconds);

		bool IsStopTrigger();
		void Stop();
	public:
		static void SetThreadName(const TCHAR* name, const UINT32 id);
		inline ThreadState GetThreadState()
		{
			return m_ThreadState;
		}
	protected:
		virtual void Run() = 0;
		virtual const TCHAR* GetThreadName();
	private:
		static DWORD THREAD_CALLBACK ThreadProc(void* t);//宏 __stdcall
	private:
		void* m_hThread;
		Priority m_priority;
		unsigned int m_stackSize;
	protected:
		ThreadState m_ThreadState;
		MEvent m_StopEvent;
		UINT32 ui_ThreadID;
	};
}

多线程.cpp

#include "MThread.h"
#include <process.h>
using namespace Unknown;
MThread::MThread():m_hThread(nullptr),m_priority(Normal),m_stackSize(0)
{
	MAC_ASSERT(!IsRunning());
#if WINDOWS_PLATFORM
	//_beginthreadex();
	m_hThread = ::CreateThread(0, m_stackSize, ThreadProc, this, CREATE_SUSPENDED, NULL);
#else
	static_assert(0, "no thread implement");
#endif
	MAC_ASSERT(m_hThread);
	m_ThreadState = TS_SUSPEND;
	SetPriority(m_priority);
	m_StopEvent.Create(true);
	m_StopEvent.Reset();
}

MThread::~MThread()
{
	if (IsRunning())
	{
#if WINDOWS_PLATFORM
		WaitForSingleObjectEx(m_hThread, INFINITE, FALSE);
		// force to exit
		TerminateThread(m_hThread, 0);
#else
		static_assert(0, "no thread implement");
#endif
	}
	if (m_hThread)
	{
#if WINDOWS_PLATFORM
		CloseHandle(m_hThread);
#else
		static_assert(0, "no thread implement");
#endif
	}
	m_hThread = nullptr;
}

void MThread::SetPriority(Priority p)
{
	int nPriority = THREAD_PRIORITY_NORMAL;

	if (p == Low)
		nPriority = THREAD_PRIORITY_BELOW_NORMAL;
	else if (p == Normal)
		nPriority = THREAD_PRIORITY_NORMAL;
	else if (p == High)
		nPriority = THREAD_PRIORITY_ABOVE_NORMAL;
#if WINDOWS_PLATFORM
	::SetThreadPriority(m_hThread, nPriority);
#else
	static_assert(0, "no thread implement");
#endif
}

Priority MThread::GetPriority() const
{
	return m_priority;
}

void MThread::Start()
{
	if (m_ThreadState == TS_SUSPEND)
	{
#if WINDOWS_PLATFORM
		ResumeThread((HANDLE)m_hThread);
#else
		static_assert(0, "no thread implement");
#endif
		m_ThreadState = TS_START;
	}
}

void MThread::Suspend()
{
	if (m_ThreadState == TS_START)
	{
#if WINDOWS_PLATFORM
		SuspendThread((HANDLE)m_hThread);
#else
		static_assert(0, "no thread implement");
#endif
		m_ThreadState = TS_SUSPEND;
	}
}

bool MThread::IsRunning() const
{
	if (NULL != m_hThread)
	{
#if WINDOWS_PLATFORM
		DWORD exitCode = 0;
		if (GetExitCodeThread(m_hThread, &exitCode))
		{
			if (STILL_ACTIVE == exitCode)
			{
				return true;
			}
		}
#else
		static_assert(0, "no thread implement");
#endif
	}

	return false;
}

void MThread::Sleep(DWORD dwMillseconds)
{
#if WINDOWS_PLATFORM
	::Sleep(dwMillseconds);
#else
	static_assert(0, "no thread implement");
#endif
}

bool MThread::IsStopTrigger()
{
	return m_StopEvent.IsTrigger();
}

void MThread::Stop()
{
	if (m_ThreadState == TS_START)
	{
		MAC_ASSERT(this->IsRunning());
		MAC_ASSERT(NULL != m_hThread);

		m_StopEvent.Trigger();
		m_ThreadState = TS_STOP;
#if WINDOWS_PLATFORM
		// 进入等待状态,等待线程终止
		WaitForSingleObject(m_hThread, INFINITE);
		//WaitForSingleObjectEx(m_hThread, INFINITE, false);
		CloseHandle(m_hThread);
#else
		static_assert(0, "no thread implement");
#endif
		m_hThread = NULL;
	}
}

void MThread::SetThreadName(const TCHAR* name,const UINT32 id)
{
#if WINDOWS_PLATFORM
	const UINT32 MS_VC_EXCEPTION = 0x406D1388;
    //更新线程名,使其正确的显示在调试器
	struct THREADNAME_INFO
	{
		DWORD dwType;     // 必须是0x1000
		TCHAR szName;    //线程名
		UINT32 dwThreadID; // 线程id
		DWORD dwFlags;    // 保留以供将来使用,必须为零
	};

	THREADNAME_INFO info;
	info.dwType = 0x1000;
	info.szName = *name;
	info.dwThreadID = id;
	info.dwFlags = 0;
	__try
	{
		RaiseException(MS_VC_EXCEPTION, 0, sizeof(info) / sizeof(ULONG_PTR), (ULONG_PTR*)&info);
	}
	__except (EXCEPTION_EXECUTE_HANDLER)
	{
	}
#else
	static_assert(0, "no thread implement");
#endif
}

const TCHAR* MThread::GetThreadName()
{
	return _T("Thread");
}

DWORD THREAD_CALLBACK MThread::ThreadProc(void* t)
{
	MThread* pThread = (MThread*)(t);
	SetThreadName(pThread->GetThreadName(),::GetCurrentThreadId());
	pThread->Run();
	return 0;
}

标签:WINDOWS,void,实践,PLATFORM,endif,MThread,多线程,hThread
From: https://www.cnblogs.com/zjr0/p/16996063.html

相关文章

  • 多线程同步篇
    用户模式下的线程同步原子访问指的是一个线程在访问某个资源的同时能保证没有其他线程会在统一时刻访问同一资源。传入的变量必须是经过内存对齐的InterlockedExchang......
  • CMake实践(二)
    fPICadd_compile_options(-fPIC)​​大概意思是缺少-fPIC这个编译参数​​​​https://cxyzjd.com/article/winafa/114847300​​-fuse-ld=goldset(CMAKE_SHARED_LINKER_F......
  • 云原生安全系列3:5个 Kubernetes API 网络安全访问最佳实践
    Kubernetes中的API访问控制会经历三个步骤。首先,对请求进行身份验证,然后检查请求的有效授权,然后执行请求准入控制,最后授予访问权限。但在身份验证过程开始之前,确保正确配......
  • 开流运行多线程CompletableFuture
    CompletableFuture提高接口性能//根据排口查询因子信息(异步)CompletableFuture<List<FactorInfo>>listCompletableFuture=CompletableFuture.supplyAsyn......
  • 基于贝叶斯网(Bayes Netword)图模型的应用实践初探
    基于贝叶斯网(BayesNetword)图模型的应用实践初探1.贝叶斯网理论部分笔者在另一篇​​文章​​中对贝叶斯网的理论部分进行了总结,在本文中,我们重点......
  • 公有云降本增效最佳实践
    前言最近看到了几个事情,一个是某保险系统,为了快速上线,全量上云,结果生产正式运行后每月账单高达几十万。相关业务总扛不住这个支出,又劳师动众,让下面的项目经理、开发、运维......
  • 分布式注册服务中心etcd在云原生引擎中的实践
    作者:王雷etcd是什么etcd是云原生架构中重要的基础组件,由CNCF孵化托管。ETCD是用于共享配置和服务发现的分布式,一致性的KV存储系统,是CoreOS公司发起的一个开源项目,授权协......
  • 吃透JAVA的Stream流操作,多年实践总结
    在JAVA中,涉及到对数组、Collection等集合类中的元素进行操作的时候,通常会通过循环的方式进行逐个处理,或者使用Stream的方式进行处理。例如,现在有这么一个需求:从给定句子......
  • Jenkins实践指南-08-Jenkins 凭证管理
    4.Jenkins凭证管理  [作者:Surpassme]随着网络环境的变化,如果在Jenkins中使用明文密码会造成一些安全隐患。为此Jenkins也提供凭证管理功能,本章节来系统学习一下。4......
  • Java多线程批量操作,居然有人不做事务控制?
    前言公司业务中遇到一个需求,需要同时修改最多约5万条数据,而且还不支持批量或异步修改操作。于是只能写个for循环操作,但操作耗时太长,只能一步一步寻找其他解决方案。具体......