<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>中文 &#187; sniperhuangwei</title>
	<atom:link href="http://software.intel.com/zh-cn/blogs/author/sniperhuangwei/feed/" rel="self" type="application/rss+xml" />
	<link>http://software.intel.com/zh-cn/blogs</link>
	<description></description>
	<lastBuildDate>Sat, 26 May 2012 06:34:24 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.1.3</generator>
		<item>
		<title>利用用户级线程提高多线程应用的性能</title>
		<link>http://software.intel.com/zh-cn/blogs/2010/08/18/400005148/</link>
		<comments>http://software.intel.com/zh-cn/blogs/2010/08/18/400005148/#comments</comments>
		<pubDate>Wed, 18 Aug 2010 06:35:31 +0000</pubDate>
		<dc:creator>sniperhuangwei</dc:creator>
				<category><![CDATA[博客征文专栏]]></category>
		<category><![CDATA[并行计算]]></category>

		<guid isPermaLink="false">http://software.intel.com/zh-cn/blogs/2010/08/18/400005148/</guid>
		<description><![CDATA[随着处理器往多核的发展，多线程被越来越多的应用到软件的开发中。但是如果没有正确的使用多线程，反而可能会导致软件性能的下降。 多线程程序中一个影响程序性能的因素就是同步。对于windows系统来说，最快的同步方案就是 critical_section,critical_section基本上可以被认为是一个用户态的同步机制(特别是设定了spincount,只有在自旋超过了spincount次之后任然不能获得锁，才会切入核心态并把当前线程阻塞).但即使是这样，如果在临界区中的代码如果处理时间比较长，任然会导致处理器浪费在自旋上。如果我们可以让线程在无法获得锁的时候就切换线程（当然是在用户态，切换核心态线程的代价很大，除了进入核心态的开销，还有因为线程切换而导致缓存失效带来的代价）那么就可以把浪费在自旋上的cpu时间用来做有用的工作了。 下面介绍一种利用用户态线程的多线程解决方案，首先，创建跟cpu数量一致的线程，每个线程上将会运行一个用户级线程调度器。 所有的业务处理都交给用户级线程处理，每当用户级线程无法获得锁时，就将自己阻塞并回到调度器中，由调度器选择另一个用户级线程来运行。当一个用户级线程释放锁的时候，会唤醒一个阻塞在这个锁上的用户级线程。当然，因为用户级线程是没有时间片控制的，如果在里面处理耗时的代码，将会导致在同一调度器上运行的其它用户级线程无法运行。 下面是代码: 首先是一个lockfree队列，队列是线程安全的，并且无需任何锁 lockfree_queue.h view plaincopy to clipboardprint? #ifndef _LOCKFREE_QUEUE_H #define _LOCKFREE_QUEUE_H template struct _node { T val; _node *_next; }; template class LockFreeQueue { public: LockFreeQueue():_head(0){} //在队列头插入一个节点 void push(_node *newnode) { while(1) { _node *lhead = _head;//本地保存 newnode-&#62;_next = lhead; //成功就退出，失败就重做 if(InterlockedCompareExchangePointer((volatile PVOID *)&#38;_head,newnode,lhead) == lhead) break; } } //从队列头弹出一个节点 [...]]]></description>
			<content:encoded><![CDATA[<p>随着处理器往多核的发展，多线程被越来越多的应用到软件的开发中。但是如果没有正确的使用多线程，反而可能会导致软件性能的下降。</p>
<p>多线程程序中一个影响程序性能的因素就是同步。对于windows系统来说，最快的同步方案就是 critical_section,critical_section基本上可以被认为是一个用户态的同步机制(特别是设定了spincount,只有在自旋超过了spincount次之后任然不能获得锁，才会切入核心态并把当前线程阻塞).但即使是这样，如果在临界区中的代码如果处理时间比较长，任然会导致处理器浪费在自旋上。如果我们可以让线程在无法获得锁的时候就切换线程（当然是在用户态，切换核心态线程的代价很大，除了进入核心态的开销，还有因为线程切换而导致缓存失效带来的代价）那么就可以把浪费在自旋上的cpu时间用来做有用的工作了。</p>
<p>下面介绍一种利用用户态线程的多线程解决方案，首先，创建跟cpu数量一致的线程，每个线程上将会运行一个用户级线程调度器。</p>
<p>所有的业务处理都交给用户级线程处理，每当用户级线程无法获得锁时，就将自己阻塞并回到调度器中，由调度器选择另一个用户级线程来运行。当一个用户级线程释放锁的时候，会唤醒一个阻塞在这个锁上的用户级线程。当然，因为用户级线程是没有时间片控制的，如果在里面处理耗时的代码，将会导致在同一调度器上运行的其它用户级线程无法运行。</p>
<p>下面是代码:</p>
<p>首先是一个lockfree队列，队列是线程安全的，并且无需任何锁</p>
<p>lockfree_queue.h</p>
<p>view plaincopy to clipboardprint?<br />
#ifndef _LOCKFREE_QUEUE_H<br />
#define _LOCKFREE_QUEUE_H<br />
template<br />
struct _node<br />
{<br />
T val;<br />
_node *_next;<br />
};<br />
template<br />
class LockFreeQueue<br />
{<br />
public:<br />
LockFreeQueue():_head(0){}<br />
//在队列头插入一个节点<br />
void push(_node *newnode)<br />
{<br />
while(1)<br />
{<br />
_node *lhead = _head;//本地保存<br />
newnode-&gt;_next = lhead;<br />
//成功就退出，失败就重做<br />
if(InterlockedCompareExchangePointer((volatile PVOID *)&amp;_head,newnode,lhead) == lhead)<br />
break;<br />
}<br />
}</p>
<p>//从队列头弹出一个节点<br />
_node* pop()<br />
{<br />
while(1)<br />
{<br />
_node *lhead = _head;//本地保存<br />
if(!lhead)<br />
return NULL;<br />
_node *ret = _head;<br />
if(InterlockedCompareExchangePointer((volatile PVOID *)&amp;_head,_head-&gt;_next,lhead) == lhead)<br />
{<br />
ret-&gt;_next = NULL;<br />
return ret;<br />
}<br />
}<br />
}<br />
private:<br />
_node *_head;<br />
};<br />
#endif<br />
#ifndef _LOCKFREE_QUEUE_H<br />
#define _LOCKFREE_QUEUE_H<br />
template<br />
struct _node<br />
{<br />
T val;<br />
_node *_next;<br />
};<br />
template<br />
class LockFreeQueue<br />
{<br />
public:<br />
LockFreeQueue():_head(0){}<br />
//在队列头插入一个节点<br />
void push(_node *newnode)<br />
{<br />
while(1)<br />
{<br />
_node *lhead = _head;//本地保存<br />
newnode-&gt;_next = lhead;<br />
//成功就退出，失败就重做<br />
if(InterlockedCompareExchangePointer((volatile PVOID *)&amp;_head,newnode,lhead) == lhead)<br />
break;<br />
}<br />
}</p>
<p>//从队列头弹出一个节点<br />
_node* pop()<br />
{<br />
while(1)<br />
{<br />
_node *lhead = _head;//本地保存<br />
if(!lhead)<br />
return NULL;<br />
_node *ret = _head;<br />
if(InterlockedCompareExchangePointer((volatile PVOID *)&amp;_head,_head-&gt;_next,lhead) == lhead)<br />
{<br />
ret-&gt;_next = NULL;<br />
return ret;<br />
}<br />
}<br />
}<br />
private:<br />
_node *_head;<br />
};<br />
#endif</p>
<p>用户级线程</p>
<p>uthread.h</p>
<p>view plaincopy to clipboardprint?<br />
#ifndef _UTHREAD_H<br />
#define _UTHREAD_H<br />
#include<br />
#include "lockfree_queue.h"<br />
//#include "luaWrapper.h"<br />
enum<br />
{<br />
NONE,<br />
WAIT4EVENT = 1, //等待某事件的来临<br />
DEAD, //纤程已死亡<br />
ACTIVED, //可运行的<br />
UNACTIVED, //不可被添加到调度队列中<br />
YIELD,<br />
SLEEP,<br />
};<br />
enum<br />
{<br />
BS_MOV = 0,<br />
BS_ATK,<br />
BS_OTHER,<br />
BS_WAIT4LOCK,<br />
BS_END,<br />
};<br />
//阻塞结构<br />
class BlockStruct<br />
{<br />
public:<br />
BlockStruct(uChar type=BS_OTHER):bs_type(type){}<br />
//返回true纤程将从block中返回<br />
virtual bool WakeUp() = 0;<br />
uChar bs_type;<br />
};<br />
typedef int uthread_t;<br />
class uthread;<br />
class runnable<br />
{<br />
public:<br />
virtual void main_routine() = 0;<br />
};<br />
class uthread;<br />
struct st_timeout<br />
{<br />
st_timeout(uthread *ut):ut(ut),_timeout(0),index(0){}<br />
bool operator &lt; (st_timeout &amp;r)<br />
{<br />
return _timeout &lt; r._timeout;<br />
}<br />
uLong _timeout;<br />
uthread *ut;<br />
int index;//在超时队列中的下标<br />
private:<br />
st_timeout &amp; operator = (const st_timeout &amp;other);<br />
st_timeout(const st_timeout &amp;other);<br />
};<br />
class Scheduler;<br />
class uthread;<br />
struct ulstruct<br />
{<br />
void *lock_addr;<br />
uthread *ut;<br />
};<br />
//纤程<br />
class uthread<br />
{<br />
public:<br />
uthread(Scheduler *sc):m_runnable(0),m_bs(0),uthread_id(-1),m_status(NONE),_st_timeout(this),p_uthreadContext(0),m_next(0),wakeuptick(0),m_scheduler(sc)<br />
{<br />
m_unlockevent = (_node*)_aligned_malloc(sizeof(*m_unlockevent),4);<br />
m_locknode = (_node*)_aligned_malloc(sizeof(*m_locknode),4);<br />
m_locknode-&gt;val = this;<br />
m_unlockevent-&gt;val.ut = this;<br />
}<br />
static void WINAPI fiber_routine(LPVOID pvParam);</p>
<p>Scheduler *GetScheduler()<br />
{<br />
return m_scheduler;<br />
}<br />
//有事件到达，尝试唤醒block的纤程<br />
void Signal();</p>
<p>void SetStatus(unsigned char st)<br />
{<br />
m_status = st;<br />
}<br />
unsigned char GetStatus()<br />
{<br />
return m_status;<br />
}<br />
PVOID GetUContext()<br />
{<br />
return p_uthreadContext;<br />
}<br />
void SetUContext(PVOID uct)<br />
{<br />
p_uthreadContext = uct;<br />
}<br />
void SetBs(BlockStruct *bs)<br />
{<br />
m_bs = bs;<br />
}<br />
BlockStruct *GetBs()<br />
{<br />
return m_bs;<br />
}<br />
void SetRunnable(runnable *ra)<br />
{<br />
m_runnable = ra;<br />
}<br />
runnable *GetRunnable()<br />
{<br />
return m_runnable;<br />
}</p>
<p>st_timeout &amp;GetTimeoutSt()<br />
{<br />
return _st_timeout;<br />
}</p>
<p>uthread_t GetUid()<br />
{<br />
return uthread_id;<br />
}<br />
void SetUid(uthread_t uid)<br />
{<br />
uthread_id = uid;<br />
}<br />
uthread *Next()<br />
{<br />
return m_next;<br />
}<br />
void SetNext(uthread *ut)<br />
{<br />
m_next = ut;<br />
}<br />
uLong wakeuptick;</p>
<p>_node* GetUnlockEvent()<br />
{<br />
return m_unlockevent;<br />
}<br />
_node* GetLockNode()<br />
{<br />
return m_locknode;<br />
}</p>
<p>private:<br />
unsigned char m_status;</p>
<p>uthread_t uthread_id;</p>
<p>PVOID p_uthreadContext;<br />
BlockStruct *m_bs;<br />
runnable *m_runnable;<br />
uthread *m_next;<br />
st_timeout _st_timeout;<br />
_node* m_unlockevent;<br />
_node* m_locknode;<br />
Scheduler *m_scheduler;<br />
};<br />
#endif<br />
#ifndef _UTHREAD_H<br />
#define _UTHREAD_H<br />
#include<br />
#include "lockfree_queue.h"<br />
//#include "luaWrapper.h"<br />
enum<br />
{<br />
NONE,<br />
WAIT4EVENT = 1, //等待某事件的来临<br />
DEAD, //纤程已死亡<br />
ACTIVED, //可运行的<br />
UNACTIVED, //不可被添加到调度队列中<br />
YIELD,<br />
SLEEP,<br />
};<br />
enum<br />
{<br />
BS_MOV = 0,<br />
BS_ATK,<br />
BS_OTHER,<br />
BS_WAIT4LOCK,<br />
BS_END,<br />
};<br />
//阻塞结构<br />
class BlockStruct<br />
{<br />
public:<br />
BlockStruct(uChar type=BS_OTHER):bs_type(type){}<br />
//返回true纤程将从block中返回<br />
virtual bool WakeUp() = 0;<br />
uChar bs_type;<br />
};<br />
typedef int uthread_t;<br />
class uthread;<br />
class runnable<br />
{<br />
public:<br />
virtual void main_routine() = 0;<br />
};<br />
class uthread;<br />
struct st_timeout<br />
{<br />
st_timeout(uthread *ut):ut(ut),_timeout(0),index(0){}<br />
bool operator &lt; (st_timeout &amp;r)<br />
{<br />
return _timeout &lt; r._timeout;<br />
}<br />
uLong _timeout;<br />
uthread *ut;<br />
int index;//在超时队列中的下标<br />
private:<br />
st_timeout &amp; operator = (const st_timeout &amp;other);<br />
st_timeout(const st_timeout &amp;other);<br />
};<br />
class Scheduler;<br />
class uthread;<br />
struct ulstruct<br />
{<br />
void *lock_addr;<br />
uthread *ut;<br />
};<br />
//纤程<br />
class uthread<br />
{<br />
public:<br />
uthread(Scheduler *sc):m_runnable(0),m_bs(0),uthread_id(-1),m_status(NONE),_st_timeout(this),p_uthreadContext(0),m_next(0),wakeuptick(0),m_scheduler(sc)<br />
{<br />
m_unlockevent = (_node*)_aligned_malloc(sizeof(*m_unlockevent),4);<br />
m_locknode = (_node*)_aligned_malloc(sizeof(*m_locknode),4);<br />
m_locknode-&gt;val = this;<br />
m_unlockevent-&gt;val.ut = this;<br />
}<br />
static void WINAPI fiber_routine(LPVOID pvParam);</p>
<p>Scheduler *GetScheduler()<br />
{<br />
return m_scheduler;<br />
}<br />
//有事件到达，尝试唤醒block的纤程<br />
void Signal();</p>
<p>void SetStatus(unsigned char st)<br />
{<br />
m_status = st;<br />
}<br />
unsigned char GetStatus()<br />
{<br />
return m_status;<br />
}<br />
PVOID GetUContext()<br />
{<br />
return p_uthreadContext;<br />
}<br />
void SetUContext(PVOID uct)<br />
{<br />
p_uthreadContext = uct;<br />
}<br />
void SetBs(BlockStruct *bs)<br />
{<br />
m_bs = bs;<br />
}<br />
BlockStruct *GetBs()<br />
{<br />
return m_bs;<br />
}<br />
void SetRunnable(runnable *ra)<br />
{<br />
m_runnable = ra;<br />
}<br />
runnable *GetRunnable()<br />
{<br />
return m_runnable;<br />
}</p>
<p>st_timeout &amp;GetTimeoutSt()<br />
{<br />
return _st_timeout;<br />
}</p>
<p>uthread_t GetUid()<br />
{<br />
return uthread_id;<br />
}<br />
void SetUid(uthread_t uid)<br />
{<br />
uthread_id = uid;<br />
}<br />
uthread *Next()<br />
{<br />
return m_next;<br />
}<br />
void SetNext(uthread *ut)<br />
{<br />
m_next = ut;<br />
}<br />
uLong wakeuptick;</p>
<p>_node* GetUnlockEvent()<br />
{<br />
return m_unlockevent;<br />
}<br />
_node* GetLockNode()<br />
{<br />
return m_locknode;<br />
}</p>
<p>private:<br />
unsigned char m_status;</p>
<p>uthread_t uthread_id;</p>
<p>PVOID p_uthreadContext;<br />
BlockStruct *m_bs;<br />
runnable *m_runnable;<br />
uthread *m_next;<br />
st_timeout _st_timeout;<br />
_node* m_unlockevent;<br />
_node* m_locknode;<br />
Scheduler *m_scheduler;<br />
};<br />
#endif</p>
<p>uthread.cpp</p>
<p>view plaincopy to clipboardprint?<br />
#include "stdafx.h"<br />
#include "uthread.h"<br />
#include "fiberApi.h"<br />
#include<br />
#include<br />
#include "ulock.h"<br />
void WINAPI uthread::fiber_routine(LPVOID pvParam)<br />
{<br />
uthread *_uthread = (uthread*)pvParam;<br />
while(1)<br />
{<br />
assert(_uthread-&gt;m_runnable);<br />
std::cout &lt;&lt; "Ai Start,threadid :" &lt;uthread_id &lt;m_runnable-&gt;main_routine();<br />
std::cout &lt;&lt; "Ai Stop" &lt;m_runnable = 0;<br />
//从可运行队列中删除<br />
//Scheduler::m_uthreads[Scheduler::m_curuid]-&gt;m_status = UNACTIVED;<br />
//SetCurrentUthreadState(UNACTIVED);</p>
<p>//Scheduler::ReleaseUthread(Scheduler::m_curuid);</p>
<p>ReleaseCurrentUthread();<br />
//Scheduler::_Yield(UNACTIVED);<br />
_Yield(UNACTIVED);<br />
}</p>
<p>//Scheduler::m_uthreads[Scheduler::m_curuid]-&gt;m_status = DEAD;<br />
//SetCurrentUthreadState(DEAD);<br />
/*这里不能直接退出纤程运行函数，否则会导致运行线程的退出，<br />
* 正确的做法是把运行权交回给scheduler，由scheduler来删除<br />
* 这个纤程<br />
*/<br />
//Scheduler::_Yield(DEAD);<br />
_Yield(DEAD);<br />
}<br />
//等待的事件到达了，将纤程重新插入到可运行队列中<br />
void uthread::Signal()<br />
{<br />
if(m_bs-&gt;WakeUp())<br />
{<br />
//printf("满足唤醒条件 %d \n",this-&gt;GetUid());<br />
//等待的条件满足了，把fiber置为可运行态并添加到运行队列中<br />
//Scheduler::Add2Active(this);<br />
Add2Active(this);<br />
m_bs = 0;<br />
wakeuptick = 0;<br />
}<br />
}<br />
#include "stdafx.h"<br />
#include "uthread.h"<br />
#include "fiberApi.h"<br />
#include<br />
#include<br />
#include "ulock.h"<br />
void WINAPI uthread::fiber_routine(LPVOID pvParam)<br />
{<br />
uthread *_uthread = (uthread*)pvParam;<br />
while(1)<br />
{<br />
assert(_uthread-&gt;m_runnable);<br />
std::cout &lt;&lt; "Ai Start,threadid :" &lt;uthread_id &lt;m_runnable-&gt;main_routine();<br />
std::cout &lt;&lt; "Ai Stop" &lt;m_runnable = 0;<br />
//从可运行队列中删除<br />
//Scheduler::m_uthreads[Scheduler::m_curuid]-&gt;m_status = UNACTIVED;<br />
//SetCurrentUthreadState(UNACTIVED);</p>
<p>//Scheduler::ReleaseUthread(Scheduler::m_curuid);</p>
<p>ReleaseCurrentUthread();<br />
//Scheduler::_Yield(UNACTIVED);<br />
_Yield(UNACTIVED);<br />
}</p>
<p>//Scheduler::m_uthreads[Scheduler::m_curuid]-&gt;m_status = DEAD;<br />
//SetCurrentUthreadState(DEAD);<br />
/*这里不能直接退出纤程运行函数，否则会导致运行线程的退出，<br />
* 正确的做法是把运行权交回给scheduler，由scheduler来删除<br />
* 这个纤程<br />
*/<br />
//Scheduler::_Yield(DEAD);<br />
_Yield(DEAD);<br />
}<br />
//等待的事件到达了，将纤程重新插入到可运行队列中<br />
void uthread::Signal()<br />
{<br />
if(m_bs-&gt;WakeUp())<br />
{<br />
//printf("满足唤醒条件 %d \n",this-&gt;GetUid());<br />
//等待的条件满足了，把fiber置为可运行态并添加到运行队列中<br />
//Scheduler::Add2Active(this);<br />
Add2Active(this);<br />
m_bs = 0;<br />
wakeuptick = 0;<br />
}<br />
}</p>
<p>然后是用户态的锁</p>
<p>uLock.h</p>
<p>view plaincopy to clipboardprint?<br />
#ifndef _ULOCK_H<br />
#define _ULOCK_H<br />
#pragma pack(push)<br />
#pragma pack(4)<br />
#include "fiberApi.h"<br />
#include "lockfree_queue.h"<br />
class Scheduler;<br />
//纤程间使用的用户级锁<br />
struct umutex<br />
{<br />
friend class Scheduler;<br />
public:<br />
umutex():flag(0){}<br />
void Lock()<br />
{<br />
if(InterlockedCompareExchange(&amp;flag,1,0) == 1)<br />
{</p>
<p>uthread *currentUThread = GetCurrentUThread();<br />
_node *tmp = currentUThread-&gt;GetLockNode();<br />
m_blockthread.push(tmp);<br />
//加锁失败，阻塞当前纤程<br />
Wait4Lock();<br />
}<br />
}<br />
void UnLock()<br />
{<br />
if(InterlockedCompareExchange(&amp;flag,0,1) == 0)<br />
{<br />
//没有lock<br />
return;<br />
}<br />
//已经解锁，唤醒阻塞在这个锁上的纤程<br />
_node *tmp = m_blockthread.pop();<br />
if(tmp)<br />
{<br />
NotifyUnLock(this,tmp-&gt;val);<br />
}<br />
}<br />
private:<br />
bool _Lock(uthread *ut)<br />
{<br />
bool ret = InterlockedCompareExchange(&amp;flag,1,0) == 0;<br />
if(!ret)<br />
{<br />
//uthread *currentUThread = GetCurrentUThread();<br />
_node *tmp = ut-&gt;GetLockNode();<br />
m_blockthread.push(tmp);<br />
}<br />
return ret;<br />
}<br />
private:<br />
volatile long flag;//如果被持有则置1,否则置0<br />
LockFreeQueue m_blockthread;//阻塞在这个锁上的纤程<br />
};<br />
#pragma pack(pop)<br />
#endif<br />
#ifndef _ULOCK_H<br />
#define _ULOCK_H<br />
#pragma pack(push)<br />
#pragma pack(4)<br />
#include "fiberApi.h"<br />
#include "lockfree_queue.h"<br />
class Scheduler;<br />
//纤程间使用的用户级锁<br />
struct umutex<br />
{<br />
friend class Scheduler;<br />
public:<br />
umutex():flag(0){}<br />
void Lock()<br />
{<br />
if(InterlockedCompareExchange(&amp;flag,1,0) == 1)<br />
{</p>
<p>uthread *currentUThread = GetCurrentUThread();<br />
_node *tmp = currentUThread-&gt;GetLockNode();<br />
m_blockthread.push(tmp);<br />
//加锁失败，阻塞当前纤程<br />
Wait4Lock();<br />
}<br />
}<br />
void UnLock()<br />
{<br />
if(InterlockedCompareExchange(&amp;flag,0,1) == 0)<br />
{<br />
//没有lock<br />
return;<br />
}<br />
//已经解锁，唤醒阻塞在这个锁上的纤程<br />
_node *tmp = m_blockthread.pop();<br />
if(tmp)<br />
{<br />
NotifyUnLock(this,tmp-&gt;val);<br />
}<br />
}<br />
private:<br />
bool _Lock(uthread *ut)<br />
{<br />
bool ret = InterlockedCompareExchange(&amp;flag,1,0) == 0;<br />
if(!ret)<br />
{<br />
//uthread *currentUThread = GetCurrentUThread();<br />
_node *tmp = ut-&gt;GetLockNode();<br />
m_blockthread.push(tmp);<br />
}<br />
return ret;<br />
}<br />
private:<br />
volatile long flag;//如果被持有则置1,否则置0<br />
LockFreeQueue m_blockthread;//阻塞在这个锁上的纤程<br />
};<br />
#pragma pack(pop)<br />
#endif</p>
<p>调度器</p>
<p>scheduler.h</p>
<p>view plaincopy to clipboardprint?<br />
#ifndef _SCHEDULER_H<br />
#define _SCHEDULER_H<br />
#include<br />
#include "uthread.h"<br />
#include<br />
#include<br />
#include<br />
#include "minHeap.h"<br />
#include "lockfree_queue.h"<br />
#define MAX_FIBER 32<br />
class Scheduler<br />
{<br />
friend class uthread;<br />
friend void _Yield(uChar);<br />
friend void ReleaseUthread(int);<br />
friend void ReleaseCurrentUthread();<br />
friend void SetCurrentUthreadState(uChar);<br />
friend void Add2Active(uthread*);<br />
friend uthread *GetCurrentUThread();<br />
friend uthread_t GetCurrentUThreadId();<br />
public:<br />
Scheduler():m_active_head(0),m_active_tail(0),m_count(0),m_curuid(-1),pending_index(0)<br />
{}<br />
//初始化纤程库<br />
void Init();<br />
void Destroy();<br />
//将一个纤程加入到调度列表中以运行runnable<br />
uthread_t FiberStartRun(runnable *param);<br />
//选择一个纤程以进行调度<br />
void Schedule();<br />
void SwitchTo(uthread_t uid)<br />
{<br />
SwitchToFiber(m_uthreads[uid]-&gt;GetUContext());<br />
}<br />
void SwitchToBlock(uthread_t uid)<br />
{<br />
if(m_uthreads[uid]-&gt;GetBs())<br />
SwitchTo(uid);<br />
}<br />
void _Yield(uChar status = YIELD)<br />
{<br />
m_uthreads[m_curuid]-&gt;SetStatus(status);<br />
SwitchToFiber(m_pUthreadContext);<br />
}<br />
//将一个纤程添加到可运行队列中<br />
void Add2Active(uthread *ut);<br />
//阻塞纤程,直到wc得到满足<br />
void Block(BlockStruct *bs,uLong ms);<br />
uthread_t GetFreeUthread()<br />
{<br />
if(!m_uthreadpool.empty())<br />
{<br />
uthread_t ret = m_uthreadpool.front();<br />
m_uthreadpool.pop_front();<br />
return ret;<br />
}<br />
return -1;<br />
}<br />
void ReleaseUthread(uthread_t uid)<br />
{<br />
if(uid SetStatus(UNACTIVED);<br />
m_uthreadpool.push_back(uid);<br />
}<br />
}<br />
//尝试唤醒uid<br />
void TryWakeup(uthread_t uid)<br />
{<br />
if(m_uthreads[uid]-&gt;GetBs())<br />
m_uthreads[uid]-&gt;Signal();<br />
}<br />
//强制唤醒纤程<br />
void ForceWakeup(uthread_t uid)<br />
{<br />
if(m_uthreads[uid]-&gt;GetStatus() != ACTIVED)<br />
{<br />
//printf("强制唤醒\n");<br />
Add2Active(m_uthreads[uid]);<br />
}<br />
}<br />
//强制唤醒阻塞在type条件上的纤程<br />
void ForceWakeup(uthread_t uid,uChar type)<br />
{<br />
if(m_uthreads[uid]-&gt;GetStatus() != ACTIVED &amp;&amp;<br />
m_uthreads[uid]-&gt;GetBs()-&gt;bs_type == type)<br />
{<br />
//printf("强制唤醒\n");<br />
Add2Active(m_uthreads[uid]);<br />
}<br />
}<br />
//清空activelist,和pendingadd<br />
void ClearActiveList();<br />
void ClearTimeOut()<br />
{<br />
m_timeoutlist.Clear();<br />
}<br />
void Sleep(uLong ms);<br />
void NotifyUnlock(_node *nn)<br />
{<br />
m_unlockevent.push(nn);<br />
}<br />
void Wait4Lock();<br />
private:<br />
uthread *m_active_head;<br />
uthread *m_active_tail;<br />
//也可以不使用m_pendingAdd，根据测试结果决定<br />
uthread_t m_pendingAdd[MAX_FIBER];<br />
unsigned int pending_index;<br />
minheap m_timeoutlist;<br />
PVOID m_pUthreadContext;//调度器所在纤程的上下文</p>
<p>uthread *m_uthreads[MAX_FIBER];<br />
LockFreeQueue m_unlockevent;<br />
int m_count;<br />
int m_curuid; //当前正在运行的纤程的uid,==-1表示在scheduler中运行<br />
std::list m_uthreadpool;//fiber池<br />
//std::map&lt;void*,std::list &gt; m_wait4lock;<br />
//std::list m_wait4lock;<br />
static const int reservesize = 65536;<br />
static const int commitsize = 8192;<br />
};<br />
#endif<br />
#ifndef _SCHEDULER_H<br />
#define _SCHEDULER_H<br />
#include<br />
#include "uthread.h"<br />
#include<br />
#include<br />
#include<br />
#include "minHeap.h"<br />
#include "lockfree_queue.h"<br />
#define MAX_FIBER 32<br />
class Scheduler<br />
{<br />
friend class uthread;<br />
friend void _Yield(uChar);<br />
friend void ReleaseUthread(int);<br />
friend void ReleaseCurrentUthread();<br />
friend void SetCurrentUthreadState(uChar);<br />
friend void Add2Active(uthread*);<br />
friend uthread *GetCurrentUThread();<br />
friend uthread_t GetCurrentUThreadId();<br />
public:<br />
Scheduler():m_active_head(0),m_active_tail(0),m_count(0),m_curuid(-1),pending_index(0)<br />
{}<br />
//初始化纤程库<br />
void Init();<br />
void Destroy();<br />
//将一个纤程加入到调度列表中以运行runnable<br />
uthread_t FiberStartRun(runnable *param);<br />
//选择一个纤程以进行调度<br />
void Schedule();<br />
void SwitchTo(uthread_t uid)<br />
{<br />
SwitchToFiber(m_uthreads[uid]-&gt;GetUContext());<br />
}<br />
void SwitchToBlock(uthread_t uid)<br />
{<br />
if(m_uthreads[uid]-&gt;GetBs())<br />
SwitchTo(uid);<br />
}<br />
void _Yield(uChar status = YIELD)<br />
{<br />
m_uthreads[m_curuid]-&gt;SetStatus(status);<br />
SwitchToFiber(m_pUthreadContext);<br />
}<br />
//将一个纤程添加到可运行队列中<br />
void Add2Active(uthread *ut);<br />
//阻塞纤程,直到wc得到满足<br />
void Block(BlockStruct *bs,uLong ms);<br />
uthread_t GetFreeUthread()<br />
{<br />
if(!m_uthreadpool.empty())<br />
{<br />
uthread_t ret = m_uthreadpool.front();<br />
m_uthreadpool.pop_front();<br />
return ret;<br />
}<br />
return -1;<br />
}<br />
void ReleaseUthread(uthread_t uid)<br />
{<br />
if(uid SetStatus(UNACTIVED);<br />
m_uthreadpool.push_back(uid);<br />
}<br />
}<br />
//尝试唤醒uid<br />
void TryWakeup(uthread_t uid)<br />
{<br />
if(m_uthreads[uid]-&gt;GetBs())<br />
m_uthreads[uid]-&gt;Signal();<br />
}<br />
//强制唤醒纤程<br />
void ForceWakeup(uthread_t uid)<br />
{<br />
if(m_uthreads[uid]-&gt;GetStatus() != ACTIVED)<br />
{<br />
//printf("强制唤醒\n");<br />
Add2Active(m_uthreads[uid]);<br />
}<br />
}<br />
//强制唤醒阻塞在type条件上的纤程<br />
void ForceWakeup(uthread_t uid,uChar type)<br />
{<br />
if(m_uthreads[uid]-&gt;GetStatus() != ACTIVED &amp;&amp;<br />
m_uthreads[uid]-&gt;GetBs()-&gt;bs_type == type)<br />
{<br />
//printf("强制唤醒\n");<br />
Add2Active(m_uthreads[uid]);<br />
}<br />
}<br />
//清空activelist,和pendingadd<br />
void ClearActiveList();<br />
void ClearTimeOut()<br />
{<br />
m_timeoutlist.Clear();<br />
}<br />
void Sleep(uLong ms);<br />
void NotifyUnlock(_node *nn)<br />
{<br />
m_unlockevent.push(nn);<br />
}<br />
void Wait4Lock();<br />
private:<br />
uthread *m_active_head;<br />
uthread *m_active_tail;<br />
//也可以不使用m_pendingAdd，根据测试结果决定<br />
uthread_t m_pendingAdd[MAX_FIBER];<br />
unsigned int pending_index;<br />
minheap m_timeoutlist;<br />
PVOID m_pUthreadContext;//调度器所在纤程的上下文</p>
<p>uthread *m_uthreads[MAX_FIBER];<br />
LockFreeQueue m_unlockevent;<br />
int m_count;<br />
int m_curuid; //当前正在运行的纤程的uid,==-1表示在scheduler中运行<br />
std::list m_uthreadpool;//fiber池<br />
//std::map&lt;void*,std::list &gt; m_wait4lock;<br />
//std::list m_wait4lock;<br />
static const int reservesize = 65536;<br />
static const int commitsize = 8192;<br />
};<br />
#endif</p>
<p>scheduler.cpp</p>
<p>view plaincopy to clipboardprint?<br />
#include "stdafx.h"<br />
//#include "Scheduler.h"<br />
#include<br />
#include<br />
#include "fiberApi.h"<br />
#include "uLock.h"<br />
//extern umutex *g_lock;<br />
uthread_t Scheduler::FiberStartRun(runnable *param)<br />
{<br />
uthread_t uid = GetFreeUthread();<br />
if(uid != -1)<br />
{<br />
m_uthreads[uid]-&gt;SetRunnable(param);<br />
Add2Active(m_uthreads[uid]);<br />
}<br />
return uid;<br />
}<br />
void Scheduler::Schedule()<br />
{<br />
{<br />
//看看是否有可以获取锁的纤程<br />
_node *tmp = NULL;<br />
while(tmp = m_unlockevent.pop())<br />
{<br />
umutex *um = (umutex*)tmp-&gt;val.lock_addr;<br />
uthread *ut = tmp-&gt;val.ut;<br />
if(um-&gt;_Lock(ut))<br />
{<br />
//加锁成功，将纤程从等待队列中删除并投入到可运行队列中<br />
Add2Active(ut);<br />
}<br />
//std::map&lt;void*,std::list &gt;::iterator it = m_wait4lock.find(tmp-&gt;val);<br />
//if(it != m_wait4lock.end())<br />
//{<br />
//尝试加锁<br />
/*if(!it-&gt;second.empty())<br />
{<br />
umutex *um = (umutex*)it-&gt;first;<br />
uthread *ut = it-&gt;second.front();<br />
if(um-&gt;_Lock(ut))<br />
{<br />
//加锁成功，将纤程从等待队列中删除并投入到可运行队列中</p>
<p>it-&gt;second.pop_front();<br />
Add2Active(ut);<br />
}<br />
}*/</p>
<p>//}<br />
//else<br />
//{<br />
//在Wait4Lock调用完成前，其它线程的解锁可能已经调用过NotifyUnLock了，<br />
//所以这里把解锁消息重新放回队列中，再次尝试<br />
// m_unlockevent.push(tmp);<br />
//}<br />
}<br />
}<br />
//将所有等待添加到m_activeList中的纤程都添加进去<br />
{<br />
for(unsigned int i = 0; i SetNext(0);<br />
if(m_active_tail)<br />
{<br />
m_active_tail-&gt;SetNext(ut);<br />
m_active_tail = ut;<br />
}<br />
else<br />
{<br />
m_active_head = m_active_tail = ut;<br />
}<br />
}<br />
pending_index = 0;<br />
}<br />
uthread *cur = m_active_head;<br />
uthread *pre = NULL;<br />
while(cur)<br />
{<br />
m_curuid = cur-&gt;GetUid();<br />
SwitchToFiber(cur-&gt;GetUContext());<br />
m_curuid = -1;<br />
unsigned char status = cur-&gt;GetStatus();<br />
//当纤程处于以下状态时需要从可运行队列中移除<br />
if(status == DEAD || status == SLEEP || status == WAIT4EVENT || status == UNACTIVED || status == YIELD)<br />
{<br />
//删除首元素<br />
if(cur == m_active_head)<br />
{<br />
//同时也是尾元素<br />
if(cur == m_active_tail)<br />
m_active_head = m_active_tail = NULL;<br />
else<br />
m_active_head = cur-&gt;Next();<br />
}<br />
else if(cur == m_active_tail)<br />
{<br />
pre-&gt;SetNext(NULL);<br />
m_active_tail = pre;<br />
}<br />
else<br />
pre-&gt;SetNext(cur-&gt;Next());<br />
uthread *tmp = cur;<br />
cur = cur-&gt;Next();<br />
tmp-&gt;SetNext(0);<br />
//如果仅仅是让出处理器，需要重新投入到可运行队列中<br />
if(status == YIELD)<br />
Add2Active(tmp);</p>
<p>}<br />
else<br />
{<br />
pre = cur;<br />
cur = cur-&gt;Next();<br />
}<br />
}<br />
//看看有没有timeout的纤程<br />
{<br />
uLong now = GetTickCount();<br />
while(m_timeoutlist.Min() !=0 &amp;&amp; m_timeoutlist.Min() ut-&gt;GetStatus() == WAIT4EVENT || timeout-&gt;ut-&gt;GetStatus() == SLEEP)<br />
{<br />
timeout-&gt;ut-&gt;wakeuptick = timeout-&gt;_timeout;<br />
Add2Active(timeout-&gt;ut);<br />
}<br />
}<br />
}<br />
}<br />
void Scheduler::Destroy()<br />
{<br />
for(int i = 0; i GetUContext());<br />
delete m_uthreads[i];<br />
}<br />
}<br />
ConvertFiberToThread();<br />
}<br />
void Scheduler::Block(BlockStruct *bs,uLong ms)<br />
{<br />
if(ms &gt; 0)<br />
{<br />
st_timeout &amp;_st_timeout = m_uthreads[m_curuid]-&gt;GetTimeoutSt();<br />
_st_timeout._timeout = GetTickCount() + ms;//time(NULL) + timeout;<br />
if(!_st_timeout.index)<br />
{<br />
m_timeoutlist.Insert(&amp;_st_timeout);<br />
}<br />
else<br />
{<br />
m_timeoutlist.Change(&amp;_st_timeout);<br />
}<br />
}<br />
m_uthreads[m_curuid]-&gt;SetBs(bs);<br />
m_uthreads[m_curuid]-&gt;SetStatus(WAIT4EVENT);<br />
SwitchToFiber(m_pUthreadContext);<br />
m_uthreads[m_curuid]-&gt;SetBs(0);<br />
}<br />
void Scheduler::Init()<br />
{<br />
m_pUthreadContext = ConvertThreadToFiber(NULL);</p>
<p>//创建fiber池<br />
for(int i = 0 ; i SetUContext(uthreadcontext);<br />
m_uthreads[i] = nthread;<br />
nthread-&gt;SetUid(i);<br />
m_uthreadpool.push_back(i);<br />
}<br />
}<br />
//将一个纤程添加到可运行队列中<br />
void Scheduler::Add2Active(uthread *ut)<br />
{<br />
//如果已经在active中了则不能再次添加<br />
if(ut-&gt;GetStatus() != ACTIVED)<br />
{<br />
ut-&gt;SetStatus(ACTIVED);<br />
m_pendingAdd[pending_index++] = ut-&gt;GetUid();<br />
}<br />
}<br />
void Scheduler::ClearActiveList()<br />
{<br />
pending_index = 0;<br />
uthread *cur = m_active_head;<br />
while(cur)<br />
{<br />
uthread *next = cur-&gt;Next();<br />
cur-&gt;SetNext(0);<br />
cur = next;<br />
}<br />
m_active_head = m_active_tail = NULL;<br />
}<br />
void Scheduler::Sleep(uLong ms)<br />
{<br />
if(ms &gt; 0)<br />
{<br />
st_timeout &amp;_st_timeout = m_uthreads[m_curuid]-&gt;GetTimeoutSt();<br />
_st_timeout._timeout = GetTickCount() + ms;//time(NULL) + seconds;<br />
if(!_st_timeout.index)<br />
{<br />
m_timeoutlist.Insert(&amp;_st_timeout);<br />
}<br />
else<br />
{<br />
m_timeoutlist.Change(&amp;_st_timeout);<br />
}<br />
m_uthreads[m_curuid]-&gt;SetStatus(SLEEP);<br />
}<br />
SwitchToFiber(m_pUthreadContext);<br />
}<br />
//纤程在等待lock_addr锁，需要将纤程移出可运行队列，并记等待信息<br />
void Scheduler::Wait4Lock()<br />
{<br />
/*std::map&lt;void*,std::list &gt;::iterator it = m_wait4lock.find(lock_addr);<br />
uthread *current_uthread = m_uthreads[m_curuid];<br />
if(it == m_wait4lock.end())<br />
m_wait4lock.insert(std::make_pair(lock_addr,std::list(1,current_uthread)));<br />
else<br />
it-&gt;second.push_back(current_uthread);<br />
*/<br />
uthread *current_uthread = m_uthreads[m_curuid];<br />
//m_wait4lock.push_back(current_uthread);<br />
current_uthread-&gt;SetStatus(WAIT4EVENT);<br />
//切换回调度器<br />
SwitchToFiber(m_pUthreadContext);<br />
}<br />
#include "stdafx.h"<br />
//#include "Scheduler.h"<br />
#include<br />
#include<br />
#include "fiberApi.h"<br />
#include "uLock.h"<br />
//extern umutex *g_lock;<br />
uthread_t Scheduler::FiberStartRun(runnable *param)<br />
{<br />
uthread_t uid = GetFreeUthread();<br />
if(uid != -1)<br />
{<br />
m_uthreads[uid]-&gt;SetRunnable(param);<br />
Add2Active(m_uthreads[uid]);<br />
}<br />
return uid;<br />
}<br />
void Scheduler::Schedule()<br />
{<br />
{<br />
//看看是否有可以获取锁的纤程<br />
_node *tmp = NULL;<br />
while(tmp = m_unlockevent.pop())<br />
{<br />
umutex *um = (umutex*)tmp-&gt;val.lock_addr;<br />
uthread *ut = tmp-&gt;val.ut;<br />
if(um-&gt;_Lock(ut))<br />
{<br />
//加锁成功，将纤程从等待队列中删除并投入到可运行队列中<br />
Add2Active(ut);<br />
}<br />
//std::map&lt;void*,std::list &gt;::iterator it = m_wait4lock.find(tmp-&gt;val);<br />
//if(it != m_wait4lock.end())<br />
//{<br />
//尝试加锁<br />
/*if(!it-&gt;second.empty())<br />
{<br />
umutex *um = (umutex*)it-&gt;first;<br />
uthread *ut = it-&gt;second.front();<br />
if(um-&gt;_Lock(ut))<br />
{<br />
//加锁成功，将纤程从等待队列中删除并投入到可运行队列中</p>
<p>it-&gt;second.pop_front();<br />
Add2Active(ut);<br />
}<br />
}*/</p>
<p>//}<br />
//else<br />
//{<br />
//在Wait4Lock调用完成前，其它线程的解锁可能已经调用过NotifyUnLock了，<br />
//所以这里把解锁消息重新放回队列中，再次尝试<br />
// m_unlockevent.push(tmp);<br />
//}<br />
}<br />
}<br />
//将所有等待添加到m_activeList中的纤程都添加进去<br />
{<br />
for(unsigned int i = 0; i SetNext(0);<br />
if(m_active_tail)<br />
{<br />
m_active_tail-&gt;SetNext(ut);<br />
m_active_tail = ut;<br />
}<br />
else<br />
{<br />
m_active_head = m_active_tail = ut;<br />
}<br />
}<br />
pending_index = 0;<br />
}<br />
uthread *cur = m_active_head;<br />
uthread *pre = NULL;<br />
while(cur)<br />
{<br />
m_curuid = cur-&gt;GetUid();<br />
SwitchToFiber(cur-&gt;GetUContext());<br />
m_curuid = -1;<br />
unsigned char status = cur-&gt;GetStatus();<br />
//当纤程处于以下状态时需要从可运行队列中移除<br />
if(status == DEAD || status == SLEEP || status == WAIT4EVENT || status == UNACTIVED || status == YIELD)<br />
{<br />
//删除首元素<br />
if(cur == m_active_head)<br />
{<br />
//同时也是尾元素<br />
if(cur == m_active_tail)<br />
m_active_head = m_active_tail = NULL;<br />
else<br />
m_active_head = cur-&gt;Next();<br />
}<br />
else if(cur == m_active_tail)<br />
{<br />
pre-&gt;SetNext(NULL);<br />
m_active_tail = pre;<br />
}<br />
else<br />
pre-&gt;SetNext(cur-&gt;Next());<br />
uthread *tmp = cur;<br />
cur = cur-&gt;Next();<br />
tmp-&gt;SetNext(0);<br />
//如果仅仅是让出处理器，需要重新投入到可运行队列中<br />
if(status == YIELD)<br />
Add2Active(tmp);</p>
<p>}<br />
else<br />
{<br />
pre = cur;<br />
cur = cur-&gt;Next();<br />
}<br />
}<br />
//看看有没有timeout的纤程<br />
{<br />
uLong now = GetTickCount();<br />
while(m_timeoutlist.Min() !=0 &amp;&amp; m_timeoutlist.Min() ut-&gt;GetStatus() == WAIT4EVENT || timeout-&gt;ut-&gt;GetStatus() == SLEEP)<br />
{<br />
timeout-&gt;ut-&gt;wakeuptick = timeout-&gt;_timeout;<br />
Add2Active(timeout-&gt;ut);<br />
}<br />
}<br />
}<br />
}<br />
void Scheduler::Destroy()<br />
{<br />
for(int i = 0; i GetUContext());<br />
delete m_uthreads[i];<br />
}<br />
}<br />
ConvertFiberToThread();<br />
}<br />
void Scheduler::Block(BlockStruct *bs,uLong ms)<br />
{<br />
if(ms &gt; 0)<br />
{<br />
st_timeout &amp;_st_timeout = m_uthreads[m_curuid]-&gt;GetTimeoutSt();<br />
_st_timeout._timeout = GetTickCount() + ms;//time(NULL) + timeout;<br />
if(!_st_timeout.index)<br />
{<br />
m_timeoutlist.Insert(&amp;_st_timeout);<br />
}<br />
else<br />
{<br />
m_timeoutlist.Change(&amp;_st_timeout);<br />
}<br />
}<br />
m_uthreads[m_curuid]-&gt;SetBs(bs);<br />
m_uthreads[m_curuid]-&gt;SetStatus(WAIT4EVENT);<br />
SwitchToFiber(m_pUthreadContext);<br />
m_uthreads[m_curuid]-&gt;SetBs(0);<br />
}<br />
void Scheduler::Init()<br />
{<br />
m_pUthreadContext = ConvertThreadToFiber(NULL);</p>
<p>//创建fiber池<br />
for(int i = 0 ; i SetUContext(uthreadcontext);<br />
m_uthreads[i] = nthread;<br />
nthread-&gt;SetUid(i);<br />
m_uthreadpool.push_back(i);<br />
}<br />
}<br />
//将一个纤程添加到可运行队列中<br />
void Scheduler::Add2Active(uthread *ut)<br />
{<br />
//如果已经在active中了则不能再次添加<br />
if(ut-&gt;GetStatus() != ACTIVED)<br />
{<br />
ut-&gt;SetStatus(ACTIVED);<br />
m_pendingAdd[pending_index++] = ut-&gt;GetUid();<br />
}<br />
}<br />
void Scheduler::ClearActiveList()<br />
{<br />
pending_index = 0;<br />
uthread *cur = m_active_head;<br />
while(cur)<br />
{<br />
uthread *next = cur-&gt;Next();<br />
cur-&gt;SetNext(0);<br />
cur = next;<br />
}<br />
m_active_head = m_active_tail = NULL;<br />
}<br />
void Scheduler::Sleep(uLong ms)<br />
{<br />
if(ms &gt; 0)<br />
{<br />
st_timeout &amp;_st_timeout = m_uthreads[m_curuid]-&gt;GetTimeoutSt();<br />
_st_timeout._timeout = GetTickCount() + ms;//time(NULL) + seconds;<br />
if(!_st_timeout.index)<br />
{<br />
m_timeoutlist.Insert(&amp;_st_timeout);<br />
}<br />
else<br />
{<br />
m_timeoutlist.Change(&amp;_st_timeout);<br />
}<br />
m_uthreads[m_curuid]-&gt;SetStatus(SLEEP);<br />
}<br />
SwitchToFiber(m_pUthreadContext);<br />
}<br />
//纤程在等待lock_addr锁，需要将纤程移出可运行队列，并记等待信息<br />
void Scheduler::Wait4Lock()<br />
{<br />
/*std::map&lt;void*,std::list &gt;::iterator it = m_wait4lock.find(lock_addr);<br />
uthread *current_uthread = m_uthreads[m_curuid];<br />
if(it == m_wait4lock.end())<br />
m_wait4lock.insert(std::make_pair(lock_addr,std::list(1,current_uthread)));<br />
else<br />
it-&gt;second.push_back(current_uthread);<br />
*/<br />
uthread *current_uthread = m_uthreads[m_curuid];<br />
//m_wait4lock.push_back(current_uthread);<br />
current_uthread-&gt;SetStatus(WAIT4EVENT);<br />
//切换回调度器<br />
SwitchToFiber(m_pUthreadContext);<br />
}</p>
<p>然后是一些API</p>
<p>fiberApi.h</p>
<p>view plaincopy to clipboardprint?<br />
#ifndef _FIBERAPI_H<br />
#define _FIBERAPI_H<br />
#include "Scheduler.h"<br />
#include<br />
//与每个线程相关的纤程调度器<br />
//extern std::map g_tlssc;<br />
extern Scheduler* g_tlssc[1019];<br />
void _Yield(uChar);<br />
void ReleaseUthread(int);<br />
void ReleaseCurrentUthread();//释放当前的纤程<br />
void SetCurrentUthreadState(uChar);//设置当前纤程的状态<br />
void Add2Active(uthread*);<br />
uthread *GetCurrentUThread();<br />
uthread_t GetCurrentUThreadId();<br />
void Wait4Lock();<br />
void NotifyUnLock(void*,uthread*);<br />
#endif<br />
#ifndef _FIBERAPI_H<br />
#define _FIBERAPI_H<br />
#include "Scheduler.h"<br />
#include<br />
//与每个线程相关的纤程调度器<br />
//extern std::map g_tlssc;<br />
extern Scheduler* g_tlssc[1019];<br />
void _Yield(uChar);<br />
void ReleaseUthread(int);<br />
void ReleaseCurrentUthread();//释放当前的纤程<br />
void SetCurrentUthreadState(uChar);//设置当前纤程的状态<br />
void Add2Active(uthread*);<br />
uthread *GetCurrentUThread();<br />
uthread_t GetCurrentUThreadId();<br />
void Wait4Lock();<br />
void NotifyUnLock(void*,uthread*);<br />
#endif</p>
<p>fiberApi.cpp</p>
<p>view plaincopy to clipboardprint?<br />
#include "stdafx.h"<br />
#include "fiberApi.h"<br />
//std::map g_tlssc;<br />
Scheduler* g_tlssc[1019];<br />
void _Yield(uChar state)<br />
{<br />
DWORD currenttrheadid = GetCurrentThreadId();<br />
g_tlssc[currenttrheadid%512]-&gt;_Yield(state);<br />
}<br />
void ReleaseUthread(int uthreadid)<br />
{<br />
DWORD currenttrheadid = GetCurrentThreadId();<br />
g_tlssc[currenttrheadid%512]-&gt;ReleaseUthread(uthreadid);<br />
}<br />
void ReleaseCurrentUthread()<br />
{<br />
DWORD currenttrheadid = GetCurrentThreadId();<br />
Scheduler *sc = g_tlssc[currenttrheadid%512];<br />
sc-&gt;ReleaseUthread(sc-&gt;m_curuid);<br />
}<br />
void SetCurrentUthreadState(uChar state)<br />
{<br />
DWORD currenttrheadid = GetCurrentThreadId();<br />
Scheduler *sc = g_tlssc[currenttrheadid%512];<br />
sc-&gt;m_uthreads[sc-&gt;m_curuid]-&gt;SetStatus(state);<br />
}<br />
void Add2Active(uthread *ut)<br />
{<br />
DWORD currenttrheadid = GetCurrentThreadId();<br />
g_tlssc[currenttrheadid%512]-&gt;Add2Active(ut);<br />
}<br />
uthread *GetCurrentUThread()<br />
{<br />
DWORD currenttrheadid = GetCurrentThreadId();<br />
Scheduler *sc = g_tlssc[currenttrheadid%512];<br />
return sc-&gt;m_uthreads[sc-&gt;m_curuid];<br />
}<br />
uthread_t GetCurrentUThreadId()<br />
{<br />
DWORD currenttrheadid = GetCurrentThreadId();<br />
Scheduler *sc = g_tlssc[currenttrheadid%512];<br />
return sc-&gt;m_curuid;<br />
}<br />
void Wait4Lock()<br />
{<br />
DWORD currenttrheadid = GetCurrentThreadId();<br />
g_tlssc[currenttrheadid%512]-&gt;Wait4Lock();<br />
}<br />
void NotifyUnLock(void *lock_addr,uthread *ut)<br />
{<br />
_node *nn = ut-&gt;GetUnlockEvent();<br />
nn-&gt;val.lock_addr = lock_addr;<br />
ut-&gt;GetScheduler()-&gt;NotifyUnlock(nn);<br />
//g_tlssc[threadid]-&gt;NotifyUnlock(lock_addr);<br />
//std::map::iterator it = g_tlssc.begin();<br />
//std::map::iterator end = g_tlssc.end();<br />
//for(; it != end; ++it)<br />
// it-&gt;second.NotifyUnlock(lock_addr);<br />
}<br />
#include "stdafx.h"<br />
#include "fiberApi.h"<br />
//std::map g_tlssc;<br />
Scheduler* g_tlssc[1019];<br />
void _Yield(uChar state)<br />
{<br />
DWORD currenttrheadid = GetCurrentThreadId();<br />
g_tlssc[currenttrheadid%512]-&gt;_Yield(state);<br />
}<br />
void ReleaseUthread(int uthreadid)<br />
{<br />
DWORD currenttrheadid = GetCurrentThreadId();<br />
g_tlssc[currenttrheadid%512]-&gt;ReleaseUthread(uthreadid);<br />
}<br />
void ReleaseCurrentUthread()<br />
{<br />
DWORD currenttrheadid = GetCurrentThreadId();<br />
Scheduler *sc = g_tlssc[currenttrheadid%512];<br />
sc-&gt;ReleaseUthread(sc-&gt;m_curuid);<br />
}<br />
void SetCurrentUthreadState(uChar state)<br />
{<br />
DWORD currenttrheadid = GetCurrentThreadId();<br />
Scheduler *sc = g_tlssc[currenttrheadid%512];<br />
sc-&gt;m_uthreads[sc-&gt;m_curuid]-&gt;SetStatus(state);<br />
}<br />
void Add2Active(uthread *ut)<br />
{<br />
DWORD currenttrheadid = GetCurrentThreadId();<br />
g_tlssc[currenttrheadid%512]-&gt;Add2Active(ut);<br />
}<br />
uthread *GetCurrentUThread()<br />
{<br />
DWORD currenttrheadid = GetCurrentThreadId();<br />
Scheduler *sc = g_tlssc[currenttrheadid%512];<br />
return sc-&gt;m_uthreads[sc-&gt;m_curuid];<br />
}<br />
uthread_t GetCurrentUThreadId()<br />
{<br />
DWORD currenttrheadid = GetCurrentThreadId();<br />
Scheduler *sc = g_tlssc[currenttrheadid%512];<br />
return sc-&gt;m_curuid;<br />
}<br />
void Wait4Lock()<br />
{<br />
DWORD currenttrheadid = GetCurrentThreadId();<br />
g_tlssc[currenttrheadid%512]-&gt;Wait4Lock();<br />
}<br />
void NotifyUnLock(void *lock_addr,uthread *ut)<br />
{<br />
_node *nn = ut-&gt;GetUnlockEvent();<br />
nn-&gt;val.lock_addr = lock_addr;<br />
ut-&gt;GetScheduler()-&gt;NotifyUnlock(nn);<br />
//g_tlssc[threadid]-&gt;NotifyUnlock(lock_addr);<br />
//std::map::iterator it = g_tlssc.begin();<br />
//std::map::iterator end = g_tlssc.end();<br />
//for(; it != end; ++it)<br />
// it-&gt;second.NotifyUnlock(lock_addr);<br />
}</p>
<p>测试代码：</p>
<p>view plaincopy to clipboardprint?<br />
// fiberFramework.cpp : 定义控制台应用程序的入口点。<br />
//<br />
#include "stdafx.h"<br />
#include "CThread.h"<br />
#include "fiberApi.h"<br />
#include "uLock.h"<br />
#include "CLock.h"<br />
std::list g_testlist;<br />
umutex *g_lock;<br />
//zMutex *g_lock;<br />
//zLightMutex *g_lock;<br />
static volatile bool finish = false;<br />
static volatile long count = 0;<br />
zThreadGroup g_threadgroup;<br />
DWORD starttime = 0;<br />
DWORD endtime = 0;<br />
class uworker : public runnable<br />
{<br />
public:<br />
void main_routine()<br />
{<br />
while(1)<br />
{<br />
g_lock-&gt;Lock();<br />
if(g_testlist.empty())<br />
{<br />
starttime = GetTickCount();<br />
}<br />
if(g_testlist.size() == 100000)<br />
{<br />
endtime = GetTickCount();<br />
finish = true;<br />
g_lock-&gt;UnLock();<br />
return;<br />
}<br />
else<br />
{<br />
g_testlist.push_back(GetCurrentThreadId()+GetCurrentUThreadId());<br />
InterlockedIncrement(&amp;count);<br />
//printf("uthread:%d\n",GetCurrentThreadId());<br />
}<br />
g_lock-&gt;UnLock();<br />
}<br />
}<br />
};<br />
class CWorkerThread : public zThread,private Noncopyable<br />
{<br />
public:<br />
CWorkerThread(const std::string &amp;name = std::string("zThread"),const bool joinable = true)<br />
:zThread(name,joinable){}<br />
~CWorkerThread(){}<br />
void run()<br />
{<br />
Scheduler *sc = new Scheduler;<br />
sc-&gt;Init();<br />
//g_tlssc.insert(std::make_pair(GetCurrentThreadId(),sc));<br />
if(g_tlssc[GetCurrentThreadId()%512] != NULL)<br />
{<br />
printf("error here\n");<br />
getchar();<br />
exit(0);<br />
}<br />
g_tlssc[GetCurrentThreadId()%512] = sc;<br />
uworker uw1;<br />
//uworker uw2;<br />
sc-&gt;FiberStartRun(&amp;uw1);<br />
//sc-&gt;FiberStartRun(&amp;uw2);<br />
while(!finish)<br />
{<br />
sc-&gt;Schedule();<br />
}<br />
printf("%d\n",GetCurrentThreadId());</p>
<p>/*while(1)<br />
{<br />
g_lock-&gt;Lock();<br />
if(g_testlist.empty())<br />
{<br />
starttime = GetTickCount();;<br />
}<br />
if(g_testlist.size() == 100000)<br />
{<br />
endtime = GetTickCount();<br />
finish = true;<br />
g_lock-&gt;UnLock();<br />
printf("finish\n");<br />
return;<br />
}<br />
else<br />
{<br />
g_testlist.push_back(GetCurrentThreadId());<br />
InterlockedIncrement(&amp;count);<br />
//printf("uthread:%d\n",GetCurrentThreadId());<br />
}<br />
g_lock-&gt;UnLock();<br />
}*/</p>
<p>}<br />
};<br />
int _tmain(int argc, _TCHAR* argv[])<br />
{<br />
memset(g_tlssc,0,sizeof(g_tlssc));<br />
void *buf = _aligned_malloc(sizeof(*g_lock),4);<br />
g_lock = new (buf)umutex;<br />
//g_lock = new zMutex;<br />
//g_lock = new zLightMutex;<br />
//创建两个线程<br />
CWorkerThread *cw1 = new CWorkerThread;<br />
CWorkerThread *cw2 = new CWorkerThread;<br />
/*CWorkerThread *cw3 = new CWorkerThread;<br />
CWorkerThread *cw4 = new CWorkerThread;<br />
CWorkerThread *cw5 = new CWorkerThread;<br />
CWorkerThread *cw6 = new CWorkerThread;<br />
CWorkerThread *cw7 = new CWorkerThread;<br />
CWorkerThread *cw8 = new CWorkerThread;*/<br />
g_threadgroup.add(cw1);<br />
g_threadgroup.add(cw2);<br />
/*g_threadgroup.add(cw3);<br />
g_threadgroup.add(cw4);<br />
g_threadgroup.add(cw5);<br />
g_threadgroup.add(cw6);<br />
g_threadgroup.add(cw7);<br />
g_threadgroup.add(cw8);*/<br />
struct TestCallback : public zThreadGroup::Callback<br />
{<br />
void exec(zThread *e)<br />
{<br />
e-&gt;start();<br />
}<br />
~TestCallback(){}<br />
};<br />
TestCallback CallBack;<br />
g_threadgroup.execAll(CallBack);<br />
while(!_kbhit())//等待服务器终止<br />
{<br />
Sleep(10);<br />
}<br />
printf("list size = %d\n",g_testlist.size());<br />
printf("time %d\n",endtime - starttime);<br />
getchar();<br />
getchar();<br />
return 0;<br />
}<br />
// fiberFramework.cpp : 定义控制台应用程序的入口点。<br />
//<br />
#include "stdafx.h"<br />
#include "CThread.h"<br />
#include "fiberApi.h"<br />
#include "uLock.h"<br />
#include "CLock.h"<br />
std::list g_testlist;<br />
umutex *g_lock;<br />
//zMutex *g_lock;<br />
//zLightMutex *g_lock;<br />
static volatile bool finish = false;<br />
static volatile long count = 0;<br />
zThreadGroup g_threadgroup;<br />
DWORD starttime = 0;<br />
DWORD endtime = 0;<br />
class uworker : public runnable<br />
{<br />
public:<br />
void main_routine()<br />
{<br />
while(1)<br />
{<br />
g_lock-&gt;Lock();<br />
if(g_testlist.empty())<br />
{<br />
starttime = GetTickCount();<br />
}<br />
if(g_testlist.size() == 100000)<br />
{<br />
endtime = GetTickCount();<br />
finish = true;<br />
g_lock-&gt;UnLock();<br />
return;<br />
}<br />
else<br />
{<br />
g_testlist.push_back(GetCurrentThreadId()+GetCurrentUThreadId());<br />
InterlockedIncrement(&amp;count);<br />
//printf("uthread:%d\n",GetCurrentThreadId());<br />
}<br />
g_lock-&gt;UnLock();<br />
}<br />
}<br />
};<br />
class CWorkerThread : public zThread,private Noncopyable<br />
{<br />
public:<br />
CWorkerThread(const std::string &amp;name = std::string("zThread"),const bool joinable = true)<br />
:zThread(name,joinable){}<br />
~CWorkerThread(){}<br />
void run()<br />
{<br />
Scheduler *sc = new Scheduler;<br />
sc-&gt;Init();<br />
//g_tlssc.insert(std::make_pair(GetCurrentThreadId(),sc));<br />
if(g_tlssc[GetCurrentThreadId()%512] != NULL)<br />
{<br />
printf("error here\n");<br />
getchar();<br />
exit(0);<br />
}<br />
g_tlssc[GetCurrentThreadId()%512] = sc;<br />
uworker uw1;<br />
//uworker uw2;<br />
sc-&gt;FiberStartRun(&amp;uw1);<br />
//sc-&gt;FiberStartRun(&amp;uw2);<br />
while(!finish)<br />
{<br />
sc-&gt;Schedule();<br />
}<br />
printf("%d\n",GetCurrentThreadId());</p>
<p>/*while(1)<br />
{<br />
g_lock-&gt;Lock();<br />
if(g_testlist.empty())<br />
{<br />
starttime = GetTickCount();;<br />
}<br />
if(g_testlist.size() == 100000)<br />
{<br />
endtime = GetTickCount();<br />
finish = true;<br />
g_lock-&gt;UnLock();<br />
printf("finish\n");<br />
return;<br />
}<br />
else<br />
{<br />
g_testlist.push_back(GetCurrentThreadId());<br />
InterlockedIncrement(&amp;count);<br />
//printf("uthread:%d\n",GetCurrentThreadId());<br />
}<br />
g_lock-&gt;UnLock();<br />
}*/</p>
<p>}<br />
};<br />
int _tmain(int argc, _TCHAR* argv[])<br />
{<br />
memset(g_tlssc,0,sizeof(g_tlssc));<br />
void *buf = _aligned_malloc(sizeof(*g_lock),4);<br />
g_lock = new (buf)umutex;<br />
//g_lock = new zMutex;<br />
//g_lock = new zLightMutex;<br />
//创建两个线程<br />
CWorkerThread *cw1 = new CWorkerThread;<br />
CWorkerThread *cw2 = new CWorkerThread;<br />
/*CWorkerThread *cw3 = new CWorkerThread;<br />
CWorkerThread *cw4 = new CWorkerThread;<br />
CWorkerThread *cw5 = new CWorkerThread;<br />
CWorkerThread *cw6 = new CWorkerThread;<br />
CWorkerThread *cw7 = new CWorkerThread;<br />
CWorkerThread *cw8 = new CWorkerThread;*/<br />
g_threadgroup.add(cw1);<br />
g_threadgroup.add(cw2);<br />
/*g_threadgroup.add(cw3);<br />
g_threadgroup.add(cw4);<br />
g_threadgroup.add(cw5);<br />
g_threadgroup.add(cw6);<br />
g_threadgroup.add(cw7);<br />
g_threadgroup.add(cw8);*/<br />
struct TestCallback : public zThreadGroup::Callback<br />
{<br />
void exec(zThread *e)<br />
{<br />
e-&gt;start();<br />
}<br />
~TestCallback(){}<br />
};<br />
TestCallback CallBack;<br />
g_threadgroup.execAll(CallBack);<br />
while(!_kbhit())//等待服务器终止<br />
{<br />
Sleep(10);<br />
}<br />
printf("list size = %d\n",g_testlist.size());<br />
printf("time %d\n",endtime - starttime);<br />
getchar();<br />
getchar();<br />
return 0;<br />
}</p>
<p>经过进一步测试，在ulock的lock和unlock中使用的无锁队列m_blockthread可能因为多线程操作导致解锁通告丢失。</p>
<p>因此，m_blockthread需要改为普通队列，并且在操作前暂时用自旋锁锁定（暂时使用，希望可以找到更好的方法）。</p>
<p>大致修改如下：</p>
<p>view plaincopy to clipboardprint?<br />
void Lock()<br />
{<br />
if(InterlockedCompareExchange(&amp;flag,1,0) == 1)<br />
{<br />
uthread *currentUThread = GetCurrentUThread();<br />
_node tmp = currentUThread-&gt;GetLockNode();<br />
while(InterlockedCompareExchange(&amp;spinlock,1,0) == 1);<br />
push(tmp);<br />
InterlockedCompareExchange(&amp;spinlock,0,1);<br />
Wait4Lock();<br />
}<br />
}<br />
void UnLock()<br />
{<br />
if(InterlockedCompareExchange(&amp;flag,0,1) == 0)<br />
return;<br />
while(InterlockedCompareExchange(&amp;spinlock,1,0) == 1);<br />
_node *tmp = pop();<br />
InterlockedCompareExchange(&amp;spinlock,0,1);<br />
if(tmp)<br />
NotifyUnLock(this,tmp-&gt;val);<br />
}<br />
void Lock()<br />
{<br />
if(InterlockedCompareExchange(&amp;flag,1,0) == 1)<br />
{<br />
uthread *currentUThread = GetCurrentUThread();<br />
_node tmp = currentUThread-&gt;GetLockNode();<br />
while(InterlockedCompareExchange(&amp;spinlock,1,0) == 1);<br />
push(tmp);<br />
InterlockedCompareExchange(&amp;spinlock,0,1);<br />
Wait4Lock();<br />
}<br />
}<br />
void UnLock()<br />
{<br />
if(InterlockedCompareExchange(&amp;flag,0,1) == 0)<br />
return;<br />
while(InterlockedCompareExchange(&amp;spinlock,1,0) == 1);<br />
_node *tmp = pop();<br />
InterlockedCompareExchange(&amp;spinlock,0,1);<br />
if(tmp)<br />
NotifyUnLock(this,tmp-&gt;val);<br />
}</p>
<p>其次，还有一个问题需要解决，就是各纤程获得锁的次数不平均，具体例子如下：</p>
<p>在双核机器上启动两个线程，线程上各运行一个纤程，对testlist进行写入的时候</p>
<p>会发现，大部分的写入是由其中一个纤程完成的，而另外一个纤程则很少能获得</p>
<p>写入的机会。</p>
<p>下面是修改后的uLock.h，解决了纤程获得锁不平均的问题，只要创建的调度线程</p>
<p>不超过cpu的数量，基本保证了各纤程有均等的机会获得锁。</p>
<p>view plaincopy to clipboardprint?<br />
#ifndef _ULOCK_H<br />
#define _ULOCK_H<br />
#pragma pack(push)<br />
#pragma pack(4)<br />
#include "fiberApi.h"<br />
//#include "lockfree_queue.h"<br />
class Scheduler;<br />
//纤程间使用的用户级锁<br />
struct umutex<br />
{<br />
friend class Scheduler;<br />
public:<br />
umutex():flag(0),spinlock(0),m_head(0),m_tail(0)<br />
{<br />
}<br />
void Lock()<br />
{<br />
if(InterlockedCompareExchange(&amp;flag,1,0) == 1)<br />
{</p>
<p>uthread *currentUThread = GetCurrentUThread();<br />
_node *tmp = currentUThread-&gt;GetLockNode();<br />
while(InterlockedCompareExchange(&amp;spinlock,1,0) == 1);<br />
//再次尝试加锁<br />
if(InterlockedCompareExchange(&amp;flag,1,0) == 0)<br />
{<br />
InterlockedCompareExchange(&amp;spinlock,0,1);<br />
return;<br />
}<br />
push(tmp);<br />
InterlockedCompareExchange(&amp;spinlock,0,1);</p>
<p>//加锁失败，阻塞当前纤程<br />
Wait4Lock();<br />
}<br />
}<br />
void UnLock()<br />
{<br />
if(InterlockedCompareExchange(&amp;flag,0,1) == 0)<br />
{<br />
//没有lock<br />
return;<br />
}<br />
//已经解锁，挑选一个纤程，并将它唤醒<br />
while(InterlockedCompareExchange(&amp;spinlock,1,0) == 1);<br />
_node *tmp = pop();<br />
InterlockedCompareExchange(&amp;spinlock,0,1);</p>
<p>if(tmp)<br />
{<br />
NotifyUnLock(this,tmp-&gt;val);<br />
}<br />
}<br />
private:<br />
bool _Lock(uthread *ut)<br />
{<br />
bool ret = InterlockedCompareExchange(&amp;flag,1,0) == 0;<br />
if(!ret)<br />
{<br />
uthread *currentUThread = GetCurrentUThread();<br />
_node *tmp = ut-&gt;GetLockNode();<br />
while(InterlockedCompareExchange(&amp;spinlock,1,0) == 1);<br />
//再次尝试加锁<br />
if(InterlockedCompareExchange(&amp;flag,1,0) == 0)<br />
{<br />
InterlockedCompareExchange(&amp;spinlock,0,1);<br />
return true;<br />
}</p>
<p>push(tmp);<br />
InterlockedCompareExchange(&amp;spinlock,0,1);</p>
<p>}<br />
return ret;<br />
}<br />
void push(_node *blockut)<br />
{<br />
blockut-&gt;_next = NULL;<br />
if(NULL == m_tail)<br />
{<br />
m_head = m_tail = blockut;<br />
}<br />
else<br />
{<br />
m_tail-&gt;_next = blockut;<br />
m_tail = blockut;<br />
}<br />
}<br />
_node *pop()<br />
{<br />
if(NULL == m_head)<br />
return NULL;<br />
else<br />
{<br />
_node *ret = m_head;<br />
m_head = m_head-&gt;_next;<br />
if(m_head == NULL)<br />
m_tail = m_head;<br />
return ret;<br />
}<br />
}<br />
private:<br />
volatile long flag;//如果被持有则置1,否则置0<br />
volatile long spinlock;//自旋锁，保护m_blockthread;<br />
//队列，记录阻塞在这个锁上的纤程<br />
_node *m_head;<br />
_node *m_tail;<br />
};<br />
#pragma pack(pop)<br />
#endif<br />
#ifndef _ULOCK_H<br />
#define _ULOCK_H<br />
#pragma pack(push)<br />
#pragma pack(4)<br />
#include "fiberApi.h"<br />
//#include "lockfree_queue.h"<br />
class Scheduler;<br />
//纤程间使用的用户级锁<br />
struct umutex<br />
{<br />
friend class Scheduler;<br />
public:<br />
umutex():flag(0),spinlock(0),m_head(0),m_tail(0)<br />
{<br />
}<br />
void Lock()<br />
{<br />
if(InterlockedCompareExchange(&amp;flag,1,0) == 1)<br />
{</p>
<p>uthread *currentUThread = GetCurrentUThread();<br />
_node *tmp = currentUThread-&gt;GetLockNode();<br />
while(InterlockedCompareExchange(&amp;spinlock,1,0) == 1);<br />
//再次尝试加锁<br />
if(InterlockedCompareExchange(&amp;flag,1,0) == 0)<br />
{<br />
InterlockedCompareExchange(&amp;spinlock,0,1);<br />
return;<br />
}<br />
push(tmp);<br />
InterlockedCompareExchange(&amp;spinlock,0,1);</p>
<p>//加锁失败，阻塞当前纤程<br />
Wait4Lock();<br />
}<br />
}<br />
void UnLock()<br />
{<br />
if(InterlockedCompareExchange(&amp;flag,0,1) == 0)<br />
{<br />
//没有lock<br />
return;<br />
}<br />
//已经解锁，挑选一个纤程，并将它唤醒<br />
while(InterlockedCompareExchange(&amp;spinlock,1,0) == 1);<br />
_node *tmp = pop();<br />
InterlockedCompareExchange(&amp;spinlock,0,1);</p>
<p>if(tmp)<br />
{<br />
NotifyUnLock(this,tmp-&gt;val);<br />
}<br />
}<br />
private:<br />
bool _Lock(uthread *ut)<br />
{<br />
bool ret = InterlockedCompareExchange(&amp;flag,1,0) == 0;<br />
if(!ret)<br />
{<br />
uthread *currentUThread = GetCurrentUThread();<br />
_node *tmp = ut-&gt;GetLockNode();<br />
while(InterlockedCompareExchange(&amp;spinlock,1,0) == 1);<br />
//再次尝试加锁<br />
if(InterlockedCompareExchange(&amp;flag,1,0) == 0)<br />
{<br />
InterlockedCompareExchange(&amp;spinlock,0,1);<br />
return true;<br />
}</p>
<p>push(tmp);<br />
InterlockedCompareExchange(&amp;spinlock,0,1);</p>
<p>}<br />
return ret;<br />
}<br />
void push(_node *blockut)<br />
{<br />
blockut-&gt;_next = NULL;<br />
if(NULL == m_tail)<br />
{<br />
m_head = m_tail = blockut;<br />
}<br />
else<br />
{<br />
m_tail-&gt;_next = blockut;<br />
m_tail = blockut;<br />
}<br />
}<br />
_node *pop()<br />
{<br />
if(NULL == m_head)<br />
return NULL;<br />
else<br />
{<br />
_node *ret = m_head;<br />
m_head = m_head-&gt;_next;<br />
if(m_head == NULL)<br />
m_tail = m_head;<br />
return ret;<br />
}<br />
}<br />
private:<br />
volatile long flag;//如果被持有则置1,否则置0<br />
volatile long spinlock;//自旋锁，保护m_blockthread;<br />
//队列，记录阻塞在这个锁上的纤程<br />
_node *m_head;<br />
_node *m_tail;<br />
};<br />
#pragma pack(pop)<br />
#endif</p>
<p>修改后的测试代码：</p>
<p>view plaincopy to clipboardprint?<br />
// fiberFramework.cpp : 定义控制台应用程序的入口点。<br />
//<br />
#include "stdafx.h"<br />
#include "CThread.h"<br />
#include "fiberApi.h"<br />
#include "uLock.h"<br />
#include "CLock.h"<br />
#define TESTSIZE 1000000<br />
int g_testlist[TESTSIZE];<br />
int g_testlistcs[TESTSIZE];<br />
int g_testmutex[TESTSIZE];<br />
umutex *g_lock;<br />
zMutex *g_lockmutex;<br />
zLightMutex *g_lockcs;<br />
/*std::list g_testlist2;<br />
std::list g_testlistcs2;<br />
std::list g_testmutex2;<br />
umutex *g_lock2;<br />
zMutex *g_lockmutex2;<br />
zLightMutex *g_lockcs2;<br />
*/<br />
static volatile bool finish = false;<br />
static volatile long count = 0;<br />
zThreadGroup g_threadgroup;<br />
DWORD starttime = 0;<br />
DWORD endtime = 0;<br />
class uworker : public runnable<br />
{<br />
public:<br />
void main_routine()<br />
{<br />
while(1)<br />
{<br />
g_lock-&gt;Lock();<br />
if(count==0)<br />
{<br />
starttime = GetTickCount();<br />
}<br />
if(count == TESTSIZE)<br />
{<br />
endtime = GetTickCount();<br />
finish = true;<br />
g_lock-&gt;UnLock();<br />
return;<br />
}<br />
else<br />
{<br />
g_testlist[count] = GetCurrentThreadId()+GetCurrentUThreadId();<br />
//InterlockedIncrement(&amp;count);<br />
}<br />
++count;<br />
g_lock-&gt;UnLock();<br />
_Yield(YIELD);<br />
volatile int c = 0;<br />
for(volatile int cc = 0; cc Init();<br />
//g_tlssc.insert(std::make_pair(GetCurrentThreadId(),sc));<br />
if(g_tlssc[GetCurrentThreadId()%TLSSIZE] != NULL)<br />
{<br />
printf("error here\n");<br />
getchar();<br />
exit(0);<br />
}<br />
g_tlssc[GetCurrentThreadId()%TLSSIZE] = sc;<br />
{<br />
uworker uw1;<br />
uworker uw2;<br />
uworker uw3;<br />
uworker uw4;<br />
sc-&gt;FiberStartRun(&amp;uw1);<br />
sc-&gt;FiberStartRun(&amp;uw2);<br />
sc-&gt;FiberStartRun(&amp;uw3);<br />
sc-&gt;FiberStartRun(&amp;uw4);<br />
}<br />
/*{<br />
uworker uw1;<br />
uworker uw2;<br />
uworker uw3;<br />
uworker uw4;<br />
sc-&gt;FiberStartRun(&amp;uw1);<br />
sc-&gt;FiberStartRun(&amp;uw2);<br />
sc-&gt;FiberStartRun(&amp;uw3);<br />
sc-&gt;FiberStartRun(&amp;uw4);<br />
}*/</p>
<p>while(!finish)<br />
{<br />
sc-&gt;Schedule();<br />
}</p>
<p>}<br />
};<br />
class CWorkerThreadCs : public zThread,private Noncopyable<br />
{<br />
public:<br />
CWorkerThreadCs(const std::string &amp;name = std::string("zThread"),const bool joinable = true)<br />
:zThread(name,joinable){}<br />
~CWorkerThreadCs(){}<br />
void run()<br />
{<br />
while(1)<br />
{<br />
g_lockcs-&gt;Lock();<br />
if(count == 0)<br />
{<br />
starttime = GetTickCount();;<br />
}<br />
if(count == TESTSIZE)<br />
{<br />
endtime = GetTickCount();<br />
g_lockcs-&gt;UnLock();<br />
return;<br />
}<br />
else<br />
{<br />
g_testlistcs[count] = GetCurrentThreadId();<br />
//InterlockedIncrement(&amp;count);<br />
}<br />
++count;<br />
g_lockcs-&gt;UnLock();<br />
volatile int c = 0;<br />
for(volatile int cc = 0; cc Lock();<br />
if(count == 0)<br />
{<br />
starttime = GetTickCount();;<br />
}<br />
if(count == TESTSIZE)<br />
{<br />
endtime = GetTickCount();<br />
g_lockmutex-&gt;UnLock();<br />
//printf("finish\n");<br />
return;<br />
}<br />
else<br />
{<br />
g_testmutex[count] = GetCurrentThreadId();<br />
//InterlockedIncrement(&amp;count);<br />
//printf("uthread:%d\n",GetCurrentThreadId());<br />
}<br />
++count;<br />
g_lockmutex-&gt;UnLock();<br />
volatile int c = 0;<br />
for(volatile int cc = 0; cc start();<br />
}<br />
~TestCallback(){}<br />
};<br />
void testfiber(int n)<br />
{<br />
void *buf = _aligned_malloc(sizeof(*g_lock),4);<br />
g_lock = new (buf)umutex;<br />
for(int i = 0; i &lt; n; ++i)<br />
{<br />
CWorkerThread *cw1 = new CWorkerThread;<br />
g_threadgroup.add(cw1);<br />
}<br />
TestCallback CallBack;<br />
g_threadgroup.execAll(CallBack);<br />
g_threadgroup.joinAll();<br />
printf("test fiber\n");<br />
printf("count %d\n",count);<br />
printf("time %d\n",endtime - starttime);<br />
std::map stat;<br />
for(int i = 0; i &lt; TESTSIZE; ++i)<br />
{<br />
std::map::iterator it = stat.find(g_testlist[i]);<br />
if(it == stat.end())<br />
{<br />
stat.insert(std::make_pair(g_testlist[i],1));<br />
}<br />
else<br />
{<br />
stat[g_testlist[i]]++;<br />
}<br />
}<br />
printf("stat size = %d\n",stat.size());<br />
for(std::map::iterator it = stat.begin(); it != stat.end(); ++it)<br />
{<br />
printf("id=%d,count=%d\n",it-&gt;first,it-&gt;second);<br />
}<br />
}<br />
void testcs(int n)<br />
{<br />
g_lockcs = new zLightMutex;<br />
for(int i = 0; i &lt; n; ++i)<br />
{<br />
CWorkerThreadCs *cw1 = new CWorkerThreadCs;<br />
g_threadgroup.add(cw1);<br />
}<br />
TestCallback CallBack;<br />
g_threadgroup.execAll(CallBack);<br />
//while(!_kbhit())//等待服务器终止<br />
//{<br />
// Sleep(10);<br />
//}<br />
g_threadgroup.joinAll();<br />
printf("test cs\n");<br />
printf("count %d\n",count);<br />
printf("time %d\n",endtime - starttime);<br />
std::map stat;<br />
for(int i = 0; i &lt; TESTSIZE; ++i)<br />
{<br />
std::map::iterator it = stat.find(g_testlistcs[i]);<br />
if(it == stat.end())<br />
{<br />
stat.insert(std::make_pair(g_testlistcs[i],1));<br />
}<br />
else<br />
{<br />
stat[g_testlistcs[i]]++;<br />
}<br />
}<br />
printf("stat size = %d\n",stat.size());<br />
for(std::map::iterator it = stat.begin(); it != stat.end(); ++it)<br />
{<br />
printf("id=%d,count=%d\n",it-&gt;first,it-&gt;second);<br />
}<br />
}<br />
void testmutex(int n)<br />
{<br />
g_lockmutex = new zMutex;<br />
for(int i = 0; i &lt; n; ++i)<br />
{<br />
CWorkerThreadMutex *cw1 = new CWorkerThreadMutex;<br />
g_threadgroup.add(cw1);<br />
}<br />
TestCallback CallBack;<br />
g_threadgroup.execAll(CallBack);<br />
g_threadgroup.joinAll();<br />
printf("test mutex\n");<br />
printf("count %d\n",count);<br />
printf("time %d\n",endtime - starttime);<br />
std::map stat;<br />
for(int i = 0; i &lt; TESTSIZE; ++i)<br />
{<br />
std::map::iterator it = stat.find(g_testmutex[i]);<br />
if(it == stat.end())<br />
{<br />
stat.insert(std::make_pair(g_testmutex[i],1));<br />
}<br />
else<br />
{<br />
stat[g_testmutex[i]]++;<br />
}<br />
}<br />
printf("stat size = %d\n",stat.size());<br />
for(std::map::iterator it = stat.begin(); it != stat.end(); ++it)<br />
{<br />
printf("id=%d,count=%d\n",it-&gt;first,it-&gt;second);<br />
}<br />
}<br />
int _tmain(int argc, _TCHAR* argv[])<br />
{<br />
int n = _ttol(argv[1]);<br />
memset(g_tlssc,0,sizeof(g_tlssc));<br />
count = 0;<br />
testfiber(n/4);<br />
count = 0;<br />
testcs(n);<br />
count = 0;<br />
testmutex(n);</p>
<p>/*LockFreeQueue q;<br />
for(int i = 0; i &lt; 5; ++i)<br />
{<br />
_node *pNode = new _node;<br />
pNode-&gt;val = i;<br />
q.push(pNode);<br />
}<br />
//q.print();<br />
for(int i = 0; i &lt; 5; ++i)<br />
{<br />
_node *pNode = q.pop();<br />
printf("%d\n",pNode-&gt;val);<br />
}<br />
_node *pNode = q.pop();<br />
*/<br />
getchar();<br />
return 0;<br />
}<br />
// fiberFramework.cpp : 定义控制台应用程序的入口点。<br />
//<br />
#include "stdafx.h"<br />
#include "CThread.h"<br />
#include "fiberApi.h"<br />
#include "uLock.h"<br />
#include "CLock.h"<br />
#define TESTSIZE 1000000<br />
int g_testlist[TESTSIZE];<br />
int g_testlistcs[TESTSIZE];<br />
int g_testmutex[TESTSIZE];<br />
umutex *g_lock;<br />
zMutex *g_lockmutex;<br />
zLightMutex *g_lockcs;<br />
/*std::list g_testlist2;<br />
std::list g_testlistcs2;<br />
std::list g_testmutex2;<br />
umutex *g_lock2;<br />
zMutex *g_lockmutex2;<br />
zLightMutex *g_lockcs2;<br />
*/<br />
static volatile bool finish = false;<br />
static volatile long count = 0;<br />
zThreadGroup g_threadgroup;<br />
DWORD starttime = 0;<br />
DWORD endtime = 0;<br />
class uworker : public runnable<br />
{<br />
public:<br />
void main_routine()<br />
{<br />
while(1)<br />
{<br />
g_lock-&gt;Lock();<br />
if(count==0)<br />
{<br />
starttime = GetTickCount();<br />
}<br />
if(count == TESTSIZE)<br />
{<br />
endtime = GetTickCount();<br />
finish = true;<br />
g_lock-&gt;UnLock();<br />
return;<br />
}<br />
else<br />
{<br />
g_testlist[count] = GetCurrentThreadId()+GetCurrentUThreadId();<br />
//InterlockedIncrement(&amp;count);<br />
}<br />
++count;<br />
g_lock-&gt;UnLock();<br />
_Yield(YIELD);<br />
volatile int c = 0;<br />
for(volatile int cc = 0; cc Init();<br />
//g_tlssc.insert(std::make_pair(GetCurrentThreadId(),sc));<br />
if(g_tlssc[GetCurrentThreadId()%TLSSIZE] != NULL)<br />
{<br />
printf("error here\n");<br />
getchar();<br />
exit(0);<br />
}<br />
g_tlssc[GetCurrentThreadId()%TLSSIZE] = sc;<br />
{<br />
uworker uw1;<br />
uworker uw2;<br />
uworker uw3;<br />
uworker uw4;<br />
sc-&gt;FiberStartRun(&amp;uw1);<br />
sc-&gt;FiberStartRun(&amp;uw2);<br />
sc-&gt;FiberStartRun(&amp;uw3);<br />
sc-&gt;FiberStartRun(&amp;uw4);<br />
}<br />
/*{<br />
uworker uw1;<br />
uworker uw2;<br />
uworker uw3;<br />
uworker uw4;<br />
sc-&gt;FiberStartRun(&amp;uw1);<br />
sc-&gt;FiberStartRun(&amp;uw2);<br />
sc-&gt;FiberStartRun(&amp;uw3);<br />
sc-&gt;FiberStartRun(&amp;uw4);<br />
}*/</p>
<p>while(!finish)<br />
{<br />
sc-&gt;Schedule();<br />
}</p>
<p>}<br />
};<br />
class CWorkerThreadCs : public zThread,private Noncopyable<br />
{<br />
public:<br />
CWorkerThreadCs(const std::string &amp;name = std::string("zThread"),const bool joinable = true)<br />
:zThread(name,joinable){}<br />
~CWorkerThreadCs(){}<br />
void run()<br />
{<br />
while(1)<br />
{<br />
g_lockcs-&gt;Lock();<br />
if(count == 0)<br />
{<br />
starttime = GetTickCount();;<br />
}<br />
if(count == TESTSIZE)<br />
{<br />
endtime = GetTickCount();<br />
g_lockcs-&gt;UnLock();<br />
return;<br />
}<br />
else<br />
{<br />
g_testlistcs[count] = GetCurrentThreadId();<br />
//InterlockedIncrement(&amp;count);<br />
}<br />
++count;<br />
g_lockcs-&gt;UnLock();<br />
volatile int c = 0;<br />
for(volatile int cc = 0; cc Lock();<br />
if(count == 0)<br />
{<br />
starttime = GetTickCount();;<br />
}<br />
if(count == TESTSIZE)<br />
{<br />
endtime = GetTickCount();<br />
g_lockmutex-&gt;UnLock();<br />
//printf("finish\n");<br />
return;<br />
}<br />
else<br />
{<br />
g_testmutex[count] = GetCurrentThreadId();<br />
//InterlockedIncrement(&amp;count);<br />
//printf("uthread:%d\n",GetCurrentThreadId());<br />
}<br />
++count;<br />
g_lockmutex-&gt;UnLock();<br />
volatile int c = 0;<br />
for(volatile int cc = 0; cc start();<br />
}<br />
~TestCallback(){}<br />
};<br />
void testfiber(int n)<br />
{<br />
void *buf = _aligned_malloc(sizeof(*g_lock),4);<br />
g_lock = new (buf)umutex;<br />
for(int i = 0; i &lt; n; ++i)<br />
{<br />
CWorkerThread *cw1 = new CWorkerThread;<br />
g_threadgroup.add(cw1);<br />
}<br />
TestCallback CallBack;<br />
g_threadgroup.execAll(CallBack);<br />
g_threadgroup.joinAll();<br />
printf("test fiber\n");<br />
printf("count %d\n",count);<br />
printf("time %d\n",endtime - starttime);<br />
std::map stat;<br />
for(int i = 0; i &lt; TESTSIZE; ++i)<br />
{<br />
std::map::iterator it = stat.find(g_testlist[i]);<br />
if(it == stat.end())<br />
{<br />
stat.insert(std::make_pair(g_testlist[i],1));<br />
}<br />
else<br />
{<br />
stat[g_testlist[i]]++;<br />
}<br />
}<br />
printf("stat size = %d\n",stat.size());<br />
for(std::map::iterator it = stat.begin(); it != stat.end(); ++it)<br />
{<br />
printf("id=%d,count=%d\n",it-&gt;first,it-&gt;second);<br />
}<br />
}<br />
void testcs(int n)<br />
{<br />
g_lockcs = new zLightMutex;<br />
for(int i = 0; i &lt; n; ++i)<br />
{<br />
CWorkerThreadCs *cw1 = new CWorkerThreadCs;<br />
g_threadgroup.add(cw1);<br />
}<br />
TestCallback CallBack;<br />
g_threadgroup.execAll(CallBack);<br />
//while(!_kbhit())//等待服务器终止<br />
//{<br />
// Sleep(10);<br />
//}<br />
g_threadgroup.joinAll();<br />
printf("test cs\n");<br />
printf("count %d\n",count);<br />
printf("time %d\n",endtime - starttime);<br />
std::map stat;<br />
for(int i = 0; i &lt; TESTSIZE; ++i)<br />
{<br />
std::map::iterator it = stat.find(g_testlistcs[i]);<br />
if(it == stat.end())<br />
{<br />
stat.insert(std::make_pair(g_testlistcs[i],1));<br />
}<br />
else<br />
{<br />
stat[g_testlistcs[i]]++;<br />
}<br />
}<br />
printf("stat size = %d\n",stat.size());<br />
for(std::map::iterator it = stat.begin(); it != stat.end(); ++it)<br />
{<br />
printf("id=%d,count=%d\n",it-&gt;first,it-&gt;second);<br />
}<br />
}<br />
void testmutex(int n)<br />
{<br />
g_lockmutex = new zMutex;<br />
for(int i = 0; i &lt; n; ++i)<br />
{<br />
CWorkerThreadMutex *cw1 = new CWorkerThreadMutex;<br />
g_threadgroup.add(cw1);<br />
}<br />
TestCallback CallBack;<br />
g_threadgroup.execAll(CallBack);<br />
g_threadgroup.joinAll();<br />
printf("test mutex\n");<br />
printf("count %d\n",count);<br />
printf("time %d\n",endtime - starttime);<br />
std::map stat;<br />
for(int i = 0; i &lt; TESTSIZE; ++i)<br />
{<br />
std::map::iterator it = stat.find(g_testmutex[i]);<br />
if(it == stat.end())<br />
{<br />
stat.insert(std::make_pair(g_testmutex[i],1));<br />
}<br />
else<br />
{<br />
stat[g_testmutex[i]]++;<br />
}<br />
}<br />
printf("stat size = %d\n",stat.size());<br />
for(std::map::iterator it = stat.begin(); it != stat.end(); ++it)<br />
{<br />
printf("id=%d,count=%d\n",it-&gt;first,it-&gt;second);<br />
}<br />
}<br />
int _tmain(int argc, _TCHAR* argv[])<br />
{<br />
int n = _ttol(argv[1]);<br />
memset(g_tlssc,0,sizeof(g_tlssc));<br />
count = 0;<br />
testfiber(n/4);<br />
count = 0;<br />
testcs(n);<br />
count = 0;<br />
testmutex(n);</p>
<p>/*LockFreeQueue q;<br />
for(int i = 0; i &lt; 5; ++i)<br />
{<br />
_node *pNode = new _node;<br />
pNode-&gt;val = i;<br />
q.push(pNode);<br />
}<br />
//q.print();<br />
for(int i = 0; i &lt; 5; ++i)<br />
{<br />
_node *pNode = q.pop();<br />
printf("%d\n",pNode-&gt;val);<br />
}<br />
_node *pNode = q.pop();<br />
*/<br />
getchar();<br />
return 0;<br />
}</p>
<p>经过测试，如果临界区内的操作很简单，例如只是对数组进行一次写入，</p>
<p>则fiber的同步机制和使用critical_section同步的性能大体相当。临界</p>
<p>区内的操作越复杂，fiber同步就越优于critical_section同步.</p>
]]></content:encoded>
			<wfw:commentRss>http://software.intel.com/zh-cn/blogs/2010/08/18/400005148/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>

