青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

posts - 297,  comments - 15,  trackbacks - 0
出處 http://www.shnenglu.com/cexer/archive/2008/07/08/55670.html

  單件(Singelton)模式可以說是眾多設(shè)計(jì)模式當(dāng)中,理解起來最容易,概念最為簡(jiǎn)單的一個(gè)。并且在實(shí)際的設(shè)計(jì)當(dāng)中也是使用得又最為頻繁 的,甚至有很多其它的模式都要借助單件才能更好地實(shí)現(xiàn)。然而就是這樣被強(qiáng)烈需求的“一句話模式”(一句話就能闡述明白),雖然有無數(shù)的牛人浸淫其中,至今 也沒有誰鼓搗出一個(gè)完美的實(shí)現(xiàn)。我小菜鳥一只自然更不敢逢人便談單件。不過這個(gè)貼的主題是跟單件模式是密不可分的。

  什么又叫做“線程相關(guān)的單件模式”呢?也許你已經(jīng)顧名思義猜出了八九分。不過還是允許我簡(jiǎn)單地用實(shí)例說明一下。

  假設(shè)你要設(shè)計(jì)了一個(gè)簡(jiǎn)單的 GUI 框架,這個(gè)框架當(dāng)中需要這樣一個(gè)全局變量(單件模式),它保存了所有窗口句柄與窗口指針的映射(我見過的數(shù)個(gè)的開源 GUI 框架都有類似的東西。)。在 WIN32 平臺(tái)上就是這樣一個(gè)簡(jiǎn)單的東西:

    //窗口的包裝類
class Window
{
HWND m_hwnd;
public:
bool create();
bool destroy();

//其它細(xì)節(jié)
};

//窗口句柄與其對(duì)象指針的映射
typedef map<HWND,Window*> WindowMap;
typedef WindowMap::iterator WindowIter;
WindowMap theWindowMap;




  每創(chuàng)建一個(gè)窗口,就需要往這個(gè) theWindowMap 當(dāng)中添加映射。每銷毀一個(gè)窗口,則需要從其中刪除掉相關(guān)映射。實(shí)現(xiàn)代碼類似:

    //創(chuàng)建窗口
bool Window::create()
{
m_hwnd=::CreateWindow(/*參數(shù)略*/);
if(!::IsWindow(m_hwnd))
return false;

theWindowMap[m_hwnd]=this; //添加映射
return true;
}

//銷毀窗口
bool Window::destroy()
{
::DestroyWindow(m_hwnd);

theWindowMap.erase(m_hwnd); //刪除映射
return true;
}


  你可以用任何可能的單件模式來實(shí)現(xiàn)這樣一個(gè)全局變量 theWindowMap,它會(huì) 工作得很好。但是當(dāng)如果考慮要給程序添加多線程支持(“多線程”是如此麻煩,它總愛和“但是”一起出現(xiàn),給本來進(jìn)行得很順利的事情引起波折。),就會(huì)發(fā)現(xiàn) 此時(shí)也許純粹的單件模式并不是最好的選擇。例如一個(gè)線程同時(shí)創(chuàng)建窗口,那么兩個(gè)線程同時(shí)調(diào)用:

    theWindowMap[m_hwnd]=this;


  這顯然不是一個(gè)原子操作,可以肯定如果你堅(jiān)持這樣干你的程序會(huì)慢慢走向崩潰,幸運(yùn)一點(diǎn)只是程序運(yùn)行結(jié)果錯(cuò)誤,如果你恰好那幾天印堂發(fā)暗面色發(fā)灰,說不定就因?yàn)檫@小小的錯(cuò)誤,被無良的BOSS作為借口開除掉了,那可是個(gè)悲慘的結(jié)局。

  當(dāng)然大多數(shù)的單件模式已經(jīng)考慮到了多線程的問題。它們的解決方案就是給加上線程鎖 ,我在數(shù)個(gè)開源的 GUI 框架看到他們都采用了這種解決方案。不過這樣做,在線程同步過程當(dāng)中,會(huì)產(chǎn)生與 GUI 框架邏輯不相關(guān)的同步消耗,雖然不是什么大不了的消耗,但是客戶可能因此就選擇了你的竟?fàn)帉?duì)手,如果線程竟?fàn)幖ち遥趶?qiáng)烈渴求資源的環(huán)境(如小型移動(dòng)設(shè) 置)當(dāng)中,這種消耗更是不可忽視的。

  實(shí)際上在應(yīng)用當(dāng)中,極少有線程需要插入刪除其它線程創(chuàng)建的窗口映射(如果確實(shí)有這種需要,那么可以肯定項(xiàng)目的設(shè)計(jì)上出了問題)。在這種情況下本 線程創(chuàng)建窗口映射都將只是本線程存取,類似“Thread-Specific”的概念。也就是說,theWindowMap 當(dāng)中其它線程創(chuàng)建的窗口的映射對(duì)于本線程來說都是不需關(guān)心的,我們卻要為那部分不必要東西整天提心吊膽并付出運(yùn)行時(shí)消耗的代價(jià),這也有點(diǎn)像“穿著棉襖洗 澡”。但是怎么樣才能做到更輕松爽快些呢?

  就本例問題而言,我們需要這樣一種變量來保存窗口映射,它針對(duì)每個(gè)線程有不同的值(Thread-Specific Data),這些值互不影響,并且所有線程對(duì)它的訪問如同是在訪問一個(gè)進(jìn)程內(nèi)的全局變量(Singelton)。

  如果你是熟悉多線程編程的人,那么“Thread-Specific ”一定讓你想起了什么。是的,“Thread-Specific Storage ” (線程相關(guān)存存諸,簡(jiǎn)稱 TSS ),正是我們需要的,這是大多數(shù)操作系統(tǒng)都提供了的一種線程公共資源安全機(jī)制,這種機(jī)制允許以一定方式創(chuàng)建一個(gè)變量,這個(gè)變量在所在進(jìn)程當(dāng)中的每個(gè)線程當(dāng) 中,可以擁有不同的值。在 WIN32 上,這個(gè)變量就稱為“索引”,其相關(guān)的值則稱為“槽”, “Thread-Local Storage”(線程局部存諸,簡(jiǎn)稱 TLS )機(jī)制。它的提了供這樣幾個(gè)函數(shù)來定義,設(shè)置,讀取線程相關(guān)數(shù)據(jù)(關(guān)于 TLS 的更多信息,可以查閱 MSDN ):

    //申請(qǐng)一個(gè)“槽”的索引。
DWORD TlsAlloc( void );

//獲得調(diào)用線程當(dāng)中指定“槽”的值。
VOID* TlsGetValue( DWORD dwTlsIndex );

//設(shè)置調(diào)用線程當(dāng)中指定“槽”的值。
BOOL TlsSetValue( DWORD dwTlsIndex,VOID* lpTlsValue );

//釋放掉申請(qǐng)的“槽”的索引
BOOL TlsFree( DWORD dwTlsIndex );

  具體使用流程方法:先調(diào)用 TlsAlloc 申請(qǐng)一個(gè)“索引”,然后線程在適當(dāng)時(shí)機(jī)創(chuàng)建一個(gè)對(duì)象并調(diào)用 TlsSetValue 將“索引”對(duì)應(yīng)的“槽”設(shè)置為該對(duì)象的指針,在此之后即可用 TlsGetValue 訪問該“糟”。最后在不需要的時(shí)候調(diào)用 TlsFree ,如在本例當(dāng)中,調(diào)用 TlsFree 的最佳時(shí)機(jī)是在進(jìn)程結(jié)束時(shí)。

  先封裝一下 TlsAlloc 和 TlsFree  以方便對(duì) ”索引“的管理。

    class TlsIndex
{
public:
TlsIndex()
:m_index(::TlsAlloc())
{}

~TlsIndex()
{
::TlsFree(m_index);
}

public:
operator DWORD() const
{
return m_index;
}

private:
DWORD m_index;
};

  
  如你所見,類 TlsIndex 將在構(gòu)造的時(shí)候申請(qǐng)一個(gè)“索引”,在析構(gòu)的時(shí)候釋放此“索引”。

  在本例當(dāng)中 TlsIndex 的對(duì)象應(yīng)該存在進(jìn)程的生命周內(nèi),以保證在進(jìn)程退出之前,這個(gè)“索引”都不會(huì)被釋放,這樣的 TlsIndex 對(duì)象聽起來正像一個(gè)全局靜態(tài)對(duì)象,不過 Meyers Singelton (用函數(shù)內(nèi)的靜態(tài)對(duì)象實(shí)現(xiàn))在這里會(huì)更適合,因?yàn)槲覀儾恍枰獙?duì)這個(gè)對(duì)象的生命周末進(jìn)行精確控制,只需要它在需要的時(shí)候創(chuàng)建,然后在進(jìn)程結(jié)束前銷毀即可。這 種方式只需要很少的代碼即可實(shí)現(xiàn),比如:

    DWORD windowMapTlsIndex()
{
static TlsIndex s_ti;  //提供自動(dòng)管理生命周期的“索引”
return s_ti;
}


  利用這個(gè)“索引”,我們就能實(shí)現(xiàn)上述“Thread-Specific”的功能:

    WindowMap* windowMap()
{
WindowMap* wp=reinterpret_cast<WindowMap*>(::TlsGetValue(windowMapTlsIndex()));
if(!wp)
{
wp=new WindowMap();
::TlsSetValue(windowMapTlsIndex(),wp);
}
return wp;
}

#define theWindowMap *(windowMap())

  
  注意各線程訪問以上的代碼不會(huì)存在竟?fàn)帯_@樣就實(shí)現(xiàn)了一個(gè)線程安全且無線程同步消耗版本的“全局對(duì)象” theWindowMap 。我們甚至不用改變Window::create,Window::destory,queryWindow 的代碼,

  這幾個(gè)簡(jiǎn)單的函數(shù)看起來似乎不像一個(gè)“模式”,但是它確實(shí)是的。

  現(xiàn)在總結(jié)一下“線程相關(guān)的單件模式”的概念:保證一個(gè)類在一個(gè)線程當(dāng)中只有一個(gè)實(shí)例,并提供一個(gè)訪問它的線程內(nèi)的訪問點(diǎn)的模式。

  為了不重復(fù)地制造車輪,我將此類應(yīng)用的模式封裝了一下:

    template<typename TDerived>
class TlsSingelton
{
typedef TDerived _Derived;
typedef TlsSingelton<TDerived> _Base;

public:
static _Derived* tlsInstance()
{
return tlsCreate();
}

protected:
static _Derived* tlsCreate()
{
_Derived* derived=tlsGet();
if(derived)
return derived;

derived=new _Derived();
if(derived && TRUE==::TlsSetValue(tlsIndex(),derived))
return derived;

if(derived)
delete derived;

return NULL;
}

static bool tlsDestroy()
{
_Derived* derived=tlsGet();
if(!derived)
return false;

delete derived;
return true;
}

static DWORD tlsIndex()
{
static TlsIndex s_tlsIndex;
return s_tlsIndex;
}

private:
static _Derived* tlsGet()
{
return reinterpret_cast<_Derived*>(::TlsGetValue(tlsIndex()));
}

static bool tlsSet(_Derived* derived)
{
return TRUE==::TlsSetValue(tlsIndex(),derived);
}

//noncopyable
private:
TlsSingelton(const _Base&);
TlsSingelton& operator=(const _Base&);
};


  將 tlsCreate,tlsDestroy 兩個(gè)函數(shù)設(shè)置為保護(hù)成員,是為了防止一些不三不四吊爾啷噹的程序隨意地刪除。

  示例:

    class WindowMapImpl:public TlsSingelton<WindowMap>
{
WindowMap m_map;
public:
WidnowMap& theWindowMapImpl()
{
return m_map;
}

public:
~WindowMapImpl();

protected:
WindowMapImpl(); //只能通過tlsCreate創(chuàng)建
friend class _Base;
};

#define theWindowMap (WindowMapImpl::tlsInstance()->theWindowMapImpl())



  仍不需要修改原有窗口代碼。

posted on 2008-07-20 17:28 chatler 閱讀(130) 評(píng)論(0)  編輯 收藏 引用

只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。
網(wǎng)站導(dǎo)航: 博客園   IT新聞   BlogJava   博問   Chat2DB   管理


<2010年4月>
28293031123
45678910
11121314151617
18192021222324
2526272829301
2345678

常用鏈接

留言簿(10)

隨筆分類(307)

隨筆檔案(297)

algorithm

Books_Free_Online

C++

database

Linux

Linux shell

linux socket

misce

  • cloudward
  • 感覺這個(gè)博客還是不錯(cuò),雖然做的東西和我不大相關(guān),覺得看看還是有好處的

network

OSS

  • Google Android
  • Android is a software stack for mobile devices that includes an operating system, middleware and key applications. This early look at the Android SDK provides the tools and APIs necessary to begin developing applications on the Android platform using the Java programming language.
  • os161 file list

overall

搜索

  •  

最新評(píng)論

閱讀排行榜

評(píng)論排行榜

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            久久久久五月天| 黑人极品videos精品欧美裸| 夜夜嗨av一区二区三区免费区| 乱码第一页成人| 久久精品99国产精品日本 | 亚洲一区二区在线看| 国产精品激情| 久久久国产一区二区三区| 久久精品人人做人人爽| 伊人久久久大香线蕉综合直播| 免费在线播放第一区高清av| 男女精品网站| 在线综合+亚洲+欧美中文字幕| 在线亚洲+欧美+日本专区| 国产美女精品一区二区三区 | 亚洲人www| 一区二区三区四区国产| 国产午夜亚洲精品不卡| 欧美国产成人精品| 国产精品免费一区豆花| 久久综合一区二区| 欧美日韩一区二区三区高清| 欧美一区在线直播| 你懂的国产精品永久在线| 亚洲欧美国产高清| 久久人人九九| 午夜精品久久久久久久99黑人| 久久精品国产免费观看| 中文在线资源观看网站视频免费不卡 | 日韩亚洲在线观看| 亚洲欧美在线观看| 久久久噜噜噜久久中文字免| 夜夜嗨av一区二区三区| 久久久久久久久岛国免费| 一本色道久久88综合日韩精品| 欧美一区二区三区免费视| 99re6这里只有精品| 久久成人综合视频| 亚洲一区二区三区高清 | 欧美色图首页| 欧美激情第9页| 国产欧美日韩在线视频| 亚洲免费观看高清完整版在线观看熊| 国产欧美日韩一区| 夜夜嗨av色一区二区不卡| 亚洲福利视频专区| 欧美一区亚洲一区| 欧美一级视频| 国产精品国产成人国产三级| 亚洲高清电影| 国产日韩久久| 亚洲一区图片| 亚洲欧美在线磁力| 国产精品九色蝌蚪自拍| 亚洲人精品午夜| 亚洲精品日韩激情在线电影| 久久久久久久波多野高潮日日| 欧美一区二区网站| 国产精品欧美日韩一区| 在线视频免费在线观看一区二区| 亚洲精品孕妇| 欧美电影在线观看| 欧美成人伊人久久综合网| 精品91免费| 久久久国产精品亚洲一区| 久久激情综合网| 国产女人精品视频| 欧美一区二区三区另类 | 久久福利精品| 国产一区二区三区在线观看免费 | 性色一区二区| 久久久久国产一区二区三区| 国产日韩av高清| 久久都是精品| 免费一级欧美在线大片| 亚洲精品中文字幕女同| 欧美激情片在线观看| 亚洲看片网站| 亚洲欧美伊人| 国产一区欧美| 久久综合网色—综合色88| 亚洲第一狼人社区| 宅男噜噜噜66一区二区66| 国产精品99一区二区| 亚洲欧美国产高清| 免费不卡欧美自拍视频| 日韩写真视频在线观看| 国产精品国产三级国产专播精品人| 亚洲自拍偷拍网址| 蜜月aⅴ免费一区二区三区| 亚洲人成艺术| 欧美一区国产在线| 欧美激情亚洲另类| 亚洲手机在线| 国内精品久久久久久久影视蜜臀| 久久综合五月| 亚洲新中文字幕| 麻豆精品一区二区综合av| 一区二区三区久久精品| 国产一区二区丝袜高跟鞋图片 | 亚洲欧美在线免费| 欧美mv日韩mv亚洲| 亚洲永久免费精品| 在线日韩欧美| 国产精品日韩精品欧美在线| 久久日韩精品| 亚洲综合999| 亚洲精品视频在线观看网站| 久久久999精品| 亚洲一区二区毛片| 尤物yw午夜国产精品视频| 欧美视频在线视频| 蜜臀久久99精品久久久久久9| 亚洲一区在线看| 亚洲精品久久久久久久久久久久| 久久久久9999亚洲精品| 亚洲视频电影图片偷拍一区| 亚洲第一区色| 韩国欧美国产1区| 国产精品久久久久久久久久妞妞 | 欧美成人四级电影| 久久久久国内| 亚洲欧美国产精品va在线观看 | 久久久青草婷婷精品综合日韩| 一本色道久久综合亚洲精品婷婷| 亚洲第一精品夜夜躁人人躁| 国产精品实拍| 欧美亚洲第一区| 欧美日韩网站| 欧美精品久久一区二区| 免费亚洲电影在线| 久久精品在这里| 欧美在线亚洲在线| 亚洲免费在线看| 亚洲一区二区三区精品视频| 亚洲最新在线| 99亚洲视频| 夜夜嗨av一区二区三区中文字幕 | 亚洲成色最大综合在线| 国产一区二区三区成人欧美日韩在线观看 | 欧美激情亚洲综合一区| 亚洲电影成人| 亚洲国产导航| 亚洲国产乱码最新视频| 亚洲国产精品va在线观看黑人| 欧美 日韩 国产在线| 欧美a级理论片| 欧美成人激情视频| 欧美黄色成人网| 亚洲激情一区| 亚洲欧美三级伦理| 欧美一级黄色网| 久久成人综合网| 免费高清在线一区| 欧美激情日韩| 亚洲日本va在线观看| 99精品视频免费观看| 亚洲性感美女99在线| 欧美一级淫片播放口| 久久久久久网址| 欧美国产日韩在线| 欧美视频中文一区二区三区在线观看 | 在线视频欧美一区| 久久国产精品网站| 男男成人高潮片免费网站| 欧美日韩亚洲一区二| 国产精品最新自拍| 亚洲第一区在线观看| 日韩午夜电影在线观看| 亚洲一区二区三区精品在线观看 | 久久精品国产清高在天天线 | 亚洲毛片视频| 亚洲欧美日韩一区| 久久伊人免费视频| 亚洲国产三级在线| 亚洲一区二区三区中文字幕在线 | 久久国产精品一区二区三区四区| 免费亚洲一区二区| 国产精品乱看| 狠狠色狠色综合曰曰| 亚洲春色另类小说| 亚洲一区二区三区在线看| 久久久久久久久久久一区| 亚洲黄页一区| 久久成人资源| 欧美午夜激情在线| 亚洲国产欧美在线人成| 午夜久久美女| 久久综合综合久久综合| 欧美成人一品| 香蕉av福利精品导航| 欧美日韩精品免费观看视一区二区 | 亚洲免费激情| 久久在线播放| 国产欧美一区二区精品婷婷| 99国产麻豆精品| 欧美高清成人| 久久精品国产成人| 国产精品乱人伦一区二区| 亚洲国产精品久久91精品|