??xml version="1.0" encoding="utf-8" standalone="yes"?>亚洲伊人久久成综合人影院,久久久久九九精品影院,久久人人爽人人爽人人片AV东京热 http://www.shnenglu.com/kevinlynx/category/7299.html低调做技术__ C/C++\MMORPG服务器\模块架构__ TODOQlinux env/read more books __Kevin Lynxzh-cnThu, 21 Mar 2013 15:19:32 GMTThu, 21 Mar 2013 15:19:32 GMT60析软g工程开发方法学RUPhttp://www.shnenglu.com/kevinlynx/archive/2013/03/21/198692.htmlKevin LynxKevin LynxThu, 21 Mar 2013 13:41:00 GMThttp://www.shnenglu.com/kevinlynx/archive/2013/03/21/198692.htmlhttp://www.shnenglu.com/kevinlynx/comments/198692.htmlhttp://www.shnenglu.com/kevinlynx/archive/2013/03/21/198692.html#Feedback0http://www.shnenglu.com/kevinlynx/comments/commentRss/198692.htmlhttp://www.shnenglu.com/kevinlynx/services/trackbacks/198692.html

前言

因ؓ(f)之前一直处在游戏开发行业,׃U种原因一直对软g工程中的目理、项目开发方法缺乏体验。虽焉目中也曾倡导~写更多的文档,无论是模块说明文还是设计文档,但效果一直不好。不甚理想的地方主要体现在文的规范性欠~、不l一、Q于表面没有实质内宏V文的~写~Z详尽的方法指|那么所谓的设计文要么是用来敷衍上U要么就是随着开发h员的水^不一而千差万别?/p>

当我开始目前这个非游戏目Ӟ我也曾想Q前期做好结构设计,制定好关键问题的解决Ҏ(gu)Q那么要完成q个目׃在话下了(jin)。但是我很快面临了(jin)一个问题:(x)需求不定。回惌n处游戏公司的那些日子Q程序员L抱怨策划需求变更过快过多,在每一ơ策划提Z个需求变更时Q}慎的E序员都?x)再三让{划保证Q放?j),不?x)变(sh)(jin)。而我面(f)的问题则更ؓ(f)严峻。我意识刎ͼ目的需求,p用户也无法一一|列出来。我们需要的是需求调研。但q你将客户的所有需求全部挖掘出来后Q这几乎不可能,因ؓ(f)他们自己也不太清楚自己想要什么)(j)Q当你交付(sh)(jin)W一个Y件版本,几乎可以肯定客户?x)提Z大堆的需求变_(d)(x)我要的不是这个,我要的那个怎么没有Q哦Q我当初以ؓ(f)你说的是另一个意思?/p>

当然Q需求调研这U工作不是让E序员去做的Q那?x)更?zhn)剧Q无论是对客戯是对E序员而言Q他们都是在对牛弹琴Q。但需求的不确定性也L存在的?/p>

事实上,需求变化本w就是一个很正常的现象。我一向愿意更(zhn)观地处理Y件开发方面的问题Q所谓小?j)得万q船。基于此Q我军_摆好?j)态学学Y件开发的Ҏ(gu)学?/p>

概要

本文要描q、ȝ?jin)RUP开发方法学的主要内容,l合我自q感受阐述?jin)一些RUP的核?j)原则。我怿我所理解的内Ҏ(gu)肤浅的,对于非代码的表达我更怿其是存在歧义的。所以本文仅当是一U经验参考,不必当真?/p>

RUP据传是用于指导大型甚臌大型目开发的Q我们做的不是这栯模的目。但是我们需要记录下整个目的开发过E,通过q个q程中出的工gM一个h可以看出q个目是如何实现出来的Q其目的在于规避唯有从v量代码中才能熟?zhn)目实现q种问题。这里出C(jin)一个概念:(x)工gQ其指的是Y仉目开发过E中M留下记录的事物,例如文、图、代码等?strong>RUP的一个重要思想Q在于其整个软g开发过E都是可推导?/strong>。例如我们通常说的软g架构Q或一点的模块l构Q都是通过开发过E中前面阶段产出的工件推导得出,?strong>不是凭借程序员的经验拍脑袋惛_来的Q经验不太可靠,q且千差万别Q?strong>推导意味着每个环节变得可靠)(j)。我们借助RUP的这个特性,创徏q些工gQ用以徏立v软g实现的可靠知识库?/p>

RUP概览

以下均摘?lt;Thinking in UML>中对RUP的描qͼ(x)

l一q程归纳和集成了(jin)软g开发活动中的最?jng)_践,它定义了(jin)软g开发过E中最重要的阶D和工作Q四个阶D和?ji)个核?j)工作)(j)Q定义了(jin)参与软g开发过E的各种角色和他们的职责Q还定义?jin)Y件生产过E中产生的工Ӟq提供了(jin)模板。最后,采用演进式Y件生命周期(q代Q将工作、角色和工g串在一P形成?jin)统一q程?/p>

l一q程是一U追求稳定的软gҎ(gu)Q它q求开发稳定架构,控制变更

l一q程集成?jin)面向对象方法、UML语言、核?j)工作流、工件模板和q程指导{知?/p>

单来_(d)RUP作ؓ(f)一UY仉目开发方法学Q?strong>它定义了(jin)软g开发的每一个过E,最重要的是它指g(jin)在每一个过E需要Z么,q些产出又是怎样得到。它试图规范化整个流E,以规遉K求变_(d)目参与者水q不一{带来的目不可控等问题Q以期一个Y件品稳定地开发出?/strong>。在一个项目开发过E中Q最核心(j)的资源是人,最不可控的亦是人?/p>

RUPq程与实?/h2>

我觉得要快速学?fn)一U知识,需要首先获得这门知识的M框架。另一斚wQ在我们获得更多信息后,我们需要挖掘出q门知识的核?j)思想。学?fn)RUP我觉得从q两斚w入手是相Ҏ(gu)较快速和有效的手Dc(din)?/p>

RUP框架

RUP定义?jin)Y件开发过E的四个阶段Q以?个工作流E?/strong>。一张极为经典的RUP开发过E框架图如下Q?/p>

rup

RUP整个Y件开发过E分为四个阶D:(x)

  • 先启(Inception)?/li>
  • _֌(Elaboration)
  • 构徏(Construction)
  • 产品?Transition)

每一个阶D늚工作分ؓ(f)9个流E:(x)

  • 业务建模
  • 需?/li>
  • 分析设计
  • 实施
  • 部v
  • 配置与变更管?/li>
  • 目理
  • 环境

其中Q前6个流E被l称?#8221;engineering disciplines”Q后3个流E被UCؓ(f)”supporting disciplines”。当?dng)我们主要x(chng)?个流E。那么,q些工作程和开发阶D又有什么关pdQ上图中其实已经阐明?jin)这些关pR?/p>

RUP指导q代开发。在软g开发的q?个阶D中Q每一个阶D会(x)被分q次q代。而每一ơP代则늛?jin)?个工作流E。随着开发阶D向产品化靠q,自然而然圎ͼ需求的变更、增加自然会(x)减少Q所以从图中可以看出Q开发过E越到后期,其工作流E中关于需求的工作则越。同P在先启阶D,光求相关的工作则占据了(jin)该阶D늚主要工作内容?/p>

RUP中的q代要求在每一ơP代中Q都?x)完整地实施一遍整个工作流E。在软g实施阶段Q甚至会(x)在每一个P代过E完后输Z个可q行的Y件版本。这个版本可能会(x)被交付给客户Q以期进一步地在功能需求上取得与客户一致的意见。这倒是同敏捷开发有点类伹{?/p>

既然制定?jin)工作流E,那每一个工作流E该如何d施呢Q?strong>RUP制定?jin)每个工作流E需要参与的角色Q这些角色需要从事的zdQ以?qing)这些活动生的工g?/strong>

q句话实际上反映?jin)RUP的一个重要信息,摘自wikiQ?/p>

RUP is based on a set of building blocks, or content elements, describing what is to be produced, the necessary skills required and the step-by-step explanation describing how specific development goals are to be achieved. The main building blocks, or content elements, are the following:

  • Roles (who) – A Role defines a set of related skills, competencies and responsibilities.
  • Work Products (what) – A Work Product represents something resulting from a task, including all the documents and models produced while working through the process.
  • Tasks (how) – A Task describes a unit of work assigned to a Role that provides a meaningful result.

RUP建模

在我看来QRUP每个工作程所完成的工作,是一个徏模的q程。所谓徏模,单来说就是将需要描q的事物通过更系l的形式表达出来Q以期获得对该事物更深入的理解?lt;Thinking in UML>中定义徏模概念ؓ(f)Q?/p>

建模(modeling)Q是指通过对客观事物徏立一U抽象的Ҏ(gu)用以表征事物q获得对事物本n的理解,同时把这U理解概念化Q将q些逻辑概念l织hQ构成一U对所观察的对象的内部l构和工作原理的便于理解的表达?/p>

在这里,建模的过E需要用一些工兗在RUP中徏模用UML来完成。在<Thinking in UML>中讲qC(jin)UML的核?j)模型,包括Q?/p>

  • 业务用例模型
  • 概念用例模型
  • pȝ用例模型
  • 领域模型
  • 分析模型
  • 软g架构和框?/li>
  • 设计模型
  • lg模型
  • 实施模型

可能在大家的普遍认识中,UML无非是几种图,q且_看一眼理解v来也不困难,甚至q能用来ȝcd做下代码l构设计。但UML的作用不仅仅如此?/p>

以上所描述的UML核心(j)模型中,每个模型q不单指的的是一UUML图。每个模型实际上都会(x)包含几种UML图,?x)包含若q张UML图。这些模型基本上渗透于RUP?个工作流E中Q只不过不同的工作流E用的模型比重不一而已?/p>

例如?#8220;分析设计”工作程中,可能?x)用到pȝ用例模型、分析模型、Y件架构和框架、设计模型等Q而业务用例模型可能在q个程中根本不?x)用刎ͼ相反Q业务用例模型则可能?#8220;业务建模”程中被q泛使用?/p>

前已q及(qing)在RUP的每个工作流E中QRUP定义?jin)该程需要参与的角色Q以?qing)这些角色需要进行的zdQ例如这里可以看?#8220;分析设计”程中的角色和活动集Q摘?lt;Thinking in UML>Q:(x)

analyse-action

相应的,在该工作程中需要出的工g集ؓ(f)Q摘?lt;Thinking in UML>Q:(x)

analyse-ar

既然使用?jin)UML作ؓ(f)建模工具Q所以可以简单地说这些工件主要就是UML图,当然也会(x)有其他文档性质的事物,例如|络协议l构、数据库表等UML无法描述的东西则通过普通文字性文描q?/p>

RUP最?jng)_?/h3>

到目前ؓ(f)止我们已l了(jin)解到RUP定义?jin)开发过E?phase)Q定义了(jin)每个q程包含的若q工作流E,q定义了(jin)每个工作程需要哪些角色从事哪些活动来完成哪些工g。除此之外,RUPq提供了(jin)6条最?jng)_는以指DY件开发:(x)

  • q代开?/li>
  • 理需?/li>
  • 使用Zlg的架?/li>
  • 可视建模
  • 持箋(hu)的质量验?/li>
  • 控制变更

q些实践在我看来仅仅是一些项目开发的指导原则Q它们渗透到每一个过E,每一个工作流E。在目q程中实践这些原则,用以保?rn)目的成功。例如我们用UML建模Q以辑ֈ“可视建模”。我们通过建立需求用例,?#8220;理需?#8221;?/p>

RUP核心(j)思想

g没有文来专门阐qRUP的核?j)思想Q但我觉得掌握其核心(j)思想才是学习(fn)的要Ҏ(gu)在。要理解一UY件开发方法学的核?j)思想Q其实最好是其与别的方法学做比较。这里先我的一些感惛_阐述?/p>

用例驱动

用例驱动指的是整个Y仉目的推进q程Q是依靠“用例”来完成?lt;Thinking in UML>Q?/p>

在实际的软g目中,一个Y件要实现的功能通过用例来捕P接下来的所有分析、设计、实现、测试都q例来取得Q即以实现用例ؓ(f)目标。在l一q程中用例能够驱动的不仅仅是分析设计?/p>

用例单来说就是描qC(jin)一个系l功能。但必须注意的是Q这仅仅是它定义的一部分。用例主要分布在“业务建模”?#8220;需?#8221;?#8220;分析设计”q些工作q程中。在不同的过E中用例的粒度和性质都不一栗例如对于一个借书pȝ而言Q在业务建模阶段Q我们可以获取出一?#8220;借书”用例Q其pȝ边界甚至不是pȝ而可能仅x(chng)q个业务本nQ因个阶D还没有考虑到计机如何实现q个借书业务Q;在系l分析阶D,我们可以将“借书”q个用例l化为用户和计算Y件系l的交互Q进一步地Q我们可能会(x)q一步精化这个用例,例如用户通过|页l端“借书”。(q里描述?jin)很多徏模的l节Q可不必qQ本文只l出一个概要性的介绍Q?/p>

我们说用例驱动Y件开发,但它如何驱动的呢Q我在实际的建模q程中,最明显的感受就是用例驱动了(jin)整个建模q程?/p>

  • 在需求分析阶D,我以pȝ使用者的角度l制Z(jin)一份用例图Q用于表达用者对该系l的需?/li>
  • 然后我绘制序列图Q活动图{)(j)来实现这些用例,也就是阐qC用者具体是如何与系l交互的
  • 从之前的建模q程中我获得对系l功能需求方面的认识
  • Z前面的分析我可以l制出系l用例图Q以明确pȝ的各个功能需?/li>
  • 同样针对用例l制用例实现?/li>
  • 用例本n应该包含更多的文,因此我编写用例规U用以详l描q各个用?/li>
  • 从用例规U、用例实C我可以抽d一些分析类Q较设计cL高抽象的c)(j)Q包含用例场景中涉及(qing)到的实体Q控刉辑
  • l化q些分析c,分析类l织h形成pȝQ我?x)用界面cd衔接各个控制c?/li>
  • 得到的分析cL模块来划分,从而可以得C个初步的pȝ架构
  • 初步考虑pȝ实现Q我甚至?x)得C个初步是的系l部|图
  • 回过头不断审视系l用例,以确认我是否实现?jin)所有用例,q可以保证我的分析实C(jin)所有需求,我不用枚举所有系l特性是否被我考虑周全Q我仅需在已有用例图中核?/strong>
  • Z模块实现各个用例Q或者基于分析类来实现系l用?/li>
  • 通过重新l制以及(qing)核实用例Q可以进一步精化分析类Q分析类在很大程度上?x)一一对应到设计类Q而设计类则对应到实际的代?/li>
  • 可以q入设计阶段Q设计阶D会(x)考虑到系l的实现l节Q例如用的语言Q用的框架{?/li>

q入设计阶段后,虽然可以q一步徏模,得到?x)直接映到代码的类图、序列图{,但这L(fng)囑֜面(f)需求变更时Q基本上?x)面临修改,q意味着l护q些文需要耗费_֊。所以,<Thinking in UML>中主张将_֊攑֜l护分析cL型中Q而通过其他U定实现从分析类到实际代码的转换。我觉得q个也在理?/p>

规范化整个过E?/h3>

我个得RUP的一大特点在于规范化?jin)整个Y件开发过E,每一个步骤需要哪些角色参与,该干什么,怎么d都有指导。加之这些活动的”可推导?#8220;Q这意味着不论参与角色属于什么水qI都可以稳固地推进目q程?/p>

此外Q这U规范化也会(x)l项目留下详l的演化q程。你可以明确地看到整个Y件是如何演化出最l的产品代码Q可以深入地理解目代码中的设计?/p>

ȝ

我只是一个RUP新手Q即便如此,我依然不觉得RUP是Y件开发的万能药。我怿M软g开发方法都是有局限性的。我们在实际使用的时候也只是吸取其精华。不同的开发方法其适用范围也是不一L(fng)。正如有人将RUP和XP做比较时_(d)如果你用RUPd一个杂货铺Q在没开张之前你已l破产了(jin)Q同样如果你用XPd飞机Q飞机毁?jin)十来次也许才能做出来(from <Thinking in UML> againQ?/p>

参考文?/h2>

Kevin Lynx 2013-03-21 21:41 发表评论
]]>MMO游戏对象属性设?/title><link>http://www.shnenglu.com/kevinlynx/archive/2011/05/02/145504.html</link><dc:creator>Kevin Lynx</dc:creator><author>Kevin Lynx</author><pubDate>Mon, 02 May 2011 11:19:00 GMT</pubDate><guid>http://www.shnenglu.com/kevinlynx/archive/2011/05/02/145504.html</guid><wfw:comment>http://www.shnenglu.com/kevinlynx/comments/145504.html</wfw:comment><comments>http://www.shnenglu.com/kevinlynx/archive/2011/05/02/145504.html#Feedback</comments><slash:comments>18</slash:comments><wfw:commentRss>http://www.shnenglu.com/kevinlynx/comments/commentRss/145504.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/kevinlynx/services/trackbacks/145504.html</trackback:ping><description><![CDATA[<div id="sgomyko" class="document" id="mmo"> <h1 class="title">MMO游戏对象属性设?/h1> <table class="docinfo" frame="void" rules="none"> <col class="docinfo-name" /> <col class="docinfo-content" /> <tbody valign="top"> <tr><th class="docinfo-name">Author:</th> <td>Kevin Lynx</td></tr> <tr><th class="docinfo-name">Date:</th> <td>5.2.2011</td></tr> </tbody> </table> <p>一般的MMORPG中,游戏对象主要包括怪物和玩家。这两类对象在经q游戏性方面的不断“q化”后,其属性数量及(qing)与之相关的逻辑往(xin)往(xin)?x)变得很巨大。如何将q一块做得既不损失效率,又能保证l构的灵zR清晰、可l护Q本文将提供一U简单的l构?/p> <div id="mcyusse" class="section" id="id1"> <h1>原始l构</h1> <p>最原始的结构,极有可能?</p> <pre class="literal-block"> Player: +---------------+ | property-1 | +---------------+ | property-2 | +---------------+ | ... | +---------------+ | operator-1 | +---------------+ | operator-2 | +---------------+ | ... | +---------------+ </pre> <p>也就是,一个对象ؓ(f)一个C++c,然后里面直接塞满?jin)各U属性名Q然后是针对q个属性的逻辑操作Q函敎ͼ(j)。其l果是Player成ؓ(f)巨类。针对这个情况,一直以来我觉得可以使用一U简单的Ҏ(gu)来拆分这个类。冠以官腔,UC为Entity-Component-based Desgin。生这U想法和我的个h技术积累有一定关p,见下文?/p> </div> <div id="egcceee" class="section" id="policy-based-design"> <h1>Policy-based Design</h1> <p>Policy-based DesignQ基于决{的设计。这个概忉|源于<Modern C++ Design>。虽然这本书讲述的是针对C++模板的用及(qing)设计技巧。但q种思想依然被我潜意识般地用在其他地斏VPolicy大致来说是一个小的组?Component)。它努力不依赖于其他东西Q它可能是个简单的c,它拥有极的数据l构Q及(qing)针对q些数据的极操作接口。D例而言Q玩家MP的自动回复功能,可装Z个Policy。将许多Policyl合hQ就可完成一个复杂的功能?/p> <p>q种思想q可指导很多E序l构斚w的设计。例如在做功能的接口拆分Ӟ将每个函数设计得够小Q小到单U地完成一个功能。一个功能的入口函数Q就之前实现的函数全部组合v来,然后共同完成功能炏V?/p> <p>当然Q?lt;Modern C++ Design>里的Policy在表现Ş式上有所不同。但其核?j)思想相同Q主要体现在 <strong>l合</strong> 特点上?/p> </div> <div id="gccyciq" class="section" id="entity-component-based-design"> <h1>Entity-Component-based Design</h1> <p>Entity-Component-based Design按照google到的文章Q严格来说算是与OOP完全不同的Y件设计方法。不q在q里它将按照我的意思重新被解释?/p> <p>如果说Policy-based Design极大可能地媄(jing)响着我们qx(chng)的细节编码,那么Entity-Component则是直接Ҏ(gu)戏对象的l构设计做直接的说明?<strong>一个游戏对象就是一个Entity?/strong> Entity拥有很少的属性,也许仅包含一个全局标示的ID?<strong>一个Component则是Entity的某个行为、或者说某个l成部分?/strong> 其实说白?jin),以玩家?f)例,一个玩家对象就是一个EntityQ而一个MP的自动回复功能就可被包装Z个Component。这个Component可能包含若干与该功能相关的数据,例如回复旉间隔Q每ơ的回复量等。我们往(xin)玩家对象q个Entityd各种ComponentQ也是l玩家添加各U逻辑功能?/p> <p>但是QComponent之间可能?x)涉及(qing)到交互Q玩家对象之外的模块可能也会(x)与玩家内的某个Component交互。子功能点的拆分Q不得不涉及(qing)到更多的胶水代码Q这也算一U代仗?/p> </div> <div id="oiugcci" class="section" id="id2"> <h1>游戏对象属性设?/h1> <p>q䆾属性结构设计,基本是参考了(jin)上面提到的设计思想。整个系l有如下lg:</p> <pre class="literal-block"> Entity: +-------------------+ | property-table | +-------------------+ | component-table | +-------------------+ Property: +-------------------+ | observer-list | +-------------------+ Component: +--------------------+ | logic-related data | +--------------------+ | logic-related func | +--------------------+ </pre> <p>意即Q所有Entity都包含一个属性表和组件表。这里的属性表q编码的属性数据成员集合,而是一个key-value形式的表。Property包含一个观察者列表,其实是一pd回调函数Q但是这些观察者本质上也是lgQ后面会(x)提到。Component正如上文描述Q仅包含Component本n实现的功能所需要的数据和函数。整个结构大致的代码如下:</p> <pre class="literal-block"> class Entity { private: GUID id; std::map<std::string, IComponent*> components; std::map<std::string, Property*> properties; }; class Property { private: std::string name; Value val; std::vector<IComponent*> observers; }; class IComponent { public: virtual bool Operate (const Args &args) { return false; } virtual void OnNotify (const Property &property, const Args &args) {} protected: std::string name; Entity *entity; }; </pre> <p>属性本w是抽象的,q完全是因ؓ(f)我们属性统一地放在了(jin)一个表里。从而又D属性的g需?a >l箋(hu)阅读</a></p> </div> </div><img src ="http://www.shnenglu.com/kevinlynx/aggbug/145504.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/kevinlynx/" target="_blank">Kevin Lynx</a> 2011-05-02 19:19 <a href="http://www.shnenglu.com/kevinlynx/archive/2011/05/02/145504.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>谈代码分层Q构建模块化E序http://www.shnenglu.com/kevinlynx/archive/2011/04/05/143430.htmlKevin LynxKevin LynxTue, 05 Apr 2011 02:12:00 GMThttp://www.shnenglu.com/kevinlynx/archive/2011/04/05/143430.htmlhttp://www.shnenglu.com/kevinlynx/comments/143430.htmlhttp://www.shnenglu.com/kevinlynx/archive/2011/04/05/143430.html#Feedback4http://www.shnenglu.com/kevinlynx/comments/commentRss/143430.htmlhttp://www.shnenglu.com/kevinlynx/services/trackbacks/143430.html

浅谈代码分层:构建模块化程序

Author:Kevin Lynx
Date:4.4.2011
Contact:kevinlynx at gmail dot com

模块化的程序是怎样的程序?我们可以说一个具有明显物理结构的软件是模块化的,例如带 插件的软件,一个完整的软件由若干运行时库共同构建;也可以说一个高度面向对象的库是 模块化的,例如图形引擎OGRE;也可以说一些具有明显层次结构的代码是模块化的。

模块化的软件具有很多显而易见的好处。在开发期,一个模块化的设计有利于程序员实现, 使其在实现过程中一直保持清晰的思路,减少潜伏的BUG;而在维护期,则有利于其他程序 员的理解。

在我看来,具有良好模块设计的代码,至少分为两种形式:

  • 整体设计没有层次之分,但也有独立的子模块,子模块彼此之间耦合甚少,这些子模块 构成了一个软件层,共同为上层应用提供服务;
  • 整个库/软件拥有明显的层次之分,从最底层,与应用业务毫无相关的一层,到最顶层, 完全对应用进行直接实现的那一层,每一个相对高层的软件层依赖于更底层的软件层, 逐层构建。

上述两种形式并非完全分离,在分层设计中,某一层软件层也可能由若干个独立的模块构成 。另一方面,这里也不会绝对说低层模块就完全不依赖于高层模块。这种双向依赖绝对不是 好的设计,但事实上我们本来就无法做出完美的设计。

本文将代码分层分为两大类:一是狭义上的分层,这种分层一般伴有文件形式上的表现;一 是广义上的分层,完全着眼于我们平时写的代码。

软件分层

软件分层一般我们可以在很多大型软件/库的结构图中看到。这些分层每一层本身就包含大 量代码。每个模块,每一个软件层都可能被实现为一个运行时库,或者其他以文件形式为 表现的东西。

Example Android

Android是Google推出的智能手机操作系统,在其官方文档中有Android的系统架构图:

imgs/android-architecture.jpg

这幅图中很好地反映了上文中提到的软件层次。整个系统从底层到高层分为Linux kernel, Libraries/Runtime,Application Framework,Applications。最底层的Kernel可以说与应 用完全不相关,直到最上层的Applications,才提供手机诸如联系人、打电话等应用功能。

每一层中,又可能分为若干相互独立(Again,没有绝对)的模块,例如Libraries那一层 中,就包含诸如Surface manager/SGL等模块。它们可能都依赖于Kernel,并且提供接口给 上层,但彼此独立。

Example Compiler

在编译器实现中,也有非常明显的层次之分。这些层次可以完全按照编译原理理论来划分。 包括:

  • 词法分析:将文本代码拆分为一个一个合法的单词
  • 语法分析:基于 词法分析 得到的单词流构建语法树
  • 语义分析:基于 语法分析 得到的语法树进行语义上的检查等
  • 生成器:基于 语义分析 结果(可能依然是语法树)生成中间代码
  • 编译器:基于 生成器 得到的中间代码生成目标机器上的机器代码
  • 链接器:基于 编译器 生成的目标代码链接成最终可执行程序

软件分层的好处之一就是对任务(task)的抽象,封装某个任务的实现细节,提供给其他 依赖模块更友好的使用接口。隔离带来的好处之一就是可轻易替换某个实现。 例如很 多UI库隔离了渲染器的实现,在实际使用过程中,既可以使用Direct X的渲染方式,也可 以使用OpenGL的实现方式。

但正如之前所强调,凡事没有绝对,凡事也不可过度。很多时候无法保证软件层之间就是单 向依赖。而另一些时候过度的分层也导致我们的程序过于松散,效率在粘合层之间绕来绕去 而消失殆尽。

代码分层

如果说软件分层是从大的方面讨论,那么本节说的代码分层,则是从小处入手。而这也更是 贴近我们日常工作的地方。本节讨论的代码分层,不像软件分层那样大。每一层可能就是 百来行代码,几个接口。

Example C中的模块组织

很多C代码写得少的C++程序员甚至对一个大型C程序中的模块组织毫无概念。这是对其他技 术接触少带来的视野狭窄的可怕结果。

在C语言的世界里,并不像某些C++教材中指出的那样,布满全局变量。当然全局变量的使 用也并不是糟糕设计的标志(goto不是魔鬼)。一个良好设计的C语言程序懂得如何去抽象、 封装模块/软件层。我们以Lua的源代码为例。

lua.h文件是暴露给Lua应用(Lua使用者)的直接信息源。接触过Lua的人都知道有个结构体 叫lua_State。但是lua.h中并没有暴露这个结构体的实现。因为一旦暴露了实现,使用者就 可能会随意使用其结构体成员,而这并不是库设计者所希望的。 封装数据的实现,也算 是构建模块化程序的一种方法。

大家都知道暴露在头文件中的信息,则可能被当作该头文件所描述模块的接口描述。所以, 在C语言中任何置于头文件中的信息都需要慎重考虑。

相对的,我们可以在很多.c文件中看到很多static函数。例如lstate.c中的stack_init。 static用于限定其修饰对象的作用域,用它去修饰某个函数,旨在告诉:这个函数仅被当前文件( 模块)使用,它仅用于本模块实现所依赖,它不是提供给模块外的接口! 封装内部实现 ,暴露够用的接口,也是保持模块清晰的方式之一。

良好的语言更懂得对程序员做一种良好设计的导向。但相对而言,C语言较缺乏这方面的语 言机制。在C语言中,良好的设计更依赖于程序员自己的功底。

Example Java中的模块组织

相较而言,Java语言则提供了模块化设计的语法机制。在Java中,如同大部分语言一样,一 般一个代码文件对应于一个代码模块。而在Java中,每个文件内只能有一个public class。 public class作为该模块的对外接口。而在模块内部,则可能有很多其他辅助实现的class ,但它们无法被外部模块访问。这是语言提供的封装机制,一种对程序员的导向。

Example OO语言中类接口设计

无论在C++中,还是在Java中,一个类中的接口,都大致有各种访问权限。例如public、 private、protected。访问权限的加入旨在更精确地暴露模块接口,隐藏细节。

在C中较为缺乏类似的机制,但依然可以这样做。例如将结构体定义于.c文件中,将非 接口函数以static的方式实现于.c文件中。

OO语言中的这些访问权限关键字的应用尤为重要。C++新手们往往不知道哪些成员该public ,哪些该private。C++熟手们在不刨根挖底的情况下,甚至会对每个数据成员写出get/set 接口(那还不如直接public)。在public/private之间,我们需要做的唯一决策就是,哪些 数据/操作并非外部模块所需。如果外部模块不需要,甚至目前不需要,那么此刻,都不要 将其public。一个public信息少的class,往往是一个被使用者更喜欢的class。

(至于protected,则是用于继承体系之间,类之间的信息隐藏。)

Example Lisp中的模块设计

又得提提Lisp。

基于上文,我们发现了各种划分模块、划分代码层的方式,无论是语言提供,还是程序员自 己的应用。但是如何逐个地构建这些层次呢?

Lisp中倡导了一种更能体现这种将代码分层的方式:自底而上地构建代码。这个自底而上, 自然是按照软件层的高低之分而言。这个过程就像上文举的编译原理例子一样。我们先编写 词法分析模块,该模块可能仅暴露一个接口:get-token。然后可以立马对该模块进行功能 测试。然后再编写语法分析模块,该模块也可能只暴露一个接口:parse。语法分析模块建 立于词法分析模块之上。因为我们之前已经对词法分析模块进行过测试,所以对语法分析的 测试也可以立即进行。如此下去,直至构建出整个程序。

每一个代码层都会提供若干接口给上层模块。越上层的模块中,就更贴近于最终目标。每一 层都感觉是建立在新的“语言“之上。按照这种思想,最终我们就可以构建出DSL,即Domain Specific Language。

分层的好处

基于以上,我们可以总结很多代码分层的好处,它们包括(但不限于):

  • 隐藏细节,提供抽象,隐藏的细节包括数据的表示(如lua_State)、功能的实现
  • 在新的一层建立更高层的“语言”
  • 接口清晰,修改维护方便
  • 方便开发,将软件分为若干层次,逐层实现

一个问题的解决

有时候,我们的软件层很难做到单向依赖。这可能是由于前期设计的失误导致,也可能确实 是情况所迫。在很多库代码中,也有现成的例子。一种解决方法就是通过回调。回调的实现 方式可以是回调函数、多态。多态的表现又可能是Listener等模式。

所有这些,主要是让底层模块不用知道高层模块。在代码层次上,它仅仅保存的是一个回调 信息,而这个信息具体是什么,则发生在运行期(话说以前给同事讲过这个)。这样就简单 避免了底层模块依赖高层模块的问题。

END

精确地定义一个软件中有哪些模块,哪些软件层。然后再精确地定义每个模块,每个头文件 ,每个类中哪些信息是提供给外部模块的,哪些信息是私有的。这些过程是设计模块化程 序的重要方式。

但需要重新强调的是,过了某个度,那又是另一种形式的糟糕设计。但其中拿捏技巧,则只 能靠实践获取。



Kevin Lynx 2011-04-05 10:12 发表评论
]]>
低耦合模块间的通信lgQ两个模?/title><link>http://www.shnenglu.com/kevinlynx/archive/2009/08/23/94143.html</link><dc:creator>Kevin Lynx</dc:creator><author>Kevin Lynx</author><pubDate>Sun, 23 Aug 2009 01:55:00 GMT</pubDate><guid>http://www.shnenglu.com/kevinlynx/archive/2009/08/23/94143.html</guid><wfw:comment>http://www.shnenglu.com/kevinlynx/comments/94143.html</wfw:comment><comments>http://www.shnenglu.com/kevinlynx/archive/2009/08/23/94143.html#Feedback</comments><slash:comments>18</slash:comments><wfw:commentRss>http://www.shnenglu.com/kevinlynx/comments/commentRss/94143.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/kevinlynx/services/trackbacks/94143.html</trackback:ping><description><![CDATA[<p style="FONT-SIZE: 10pt"><strong>用?/strong></p> <p style="FONT-SIZE: 10pt">在一个UI与逻辑模块交互比较多的E序中,因ؓ(f)q不惌两个模块发生太大的耦合Q基本目标是<br>可以完全不改代码地换一个UI。逻辑模块需要在产生一些事件后通知到UI模块Qƈ且在q个通知<br>里携带够多的信息(数据Q给接收通知的模块,例如UI模块。逻辑模块q可能被攄于与UI?br>块不同的U程里?/p> <p style="FONT-SIZE: 10pt"><strong>最初的l构</strong></p> <p style="FONT-SIZE: 10pt">最开始我直接采用最单的Ҏ(gu)Q逻辑模块保存?sh)个UI模块传过来的listener。当有事件发生时Q?br>回调相应的接口此通知传出厅R大致结构如下:(x)<br></p> <div style="BORDER-BOTTOM: #cccccc 1px solid; BORDER-LEFT: #cccccc 1px solid; PADDING-BOTTOM: 4px; BACKGROUND-COLOR: #eeeeee; PADDING-LEFT: 4px; WIDTH: 98%; PADDING-RIGHT: 5px; FONT-SIZE: 13px; WORD-BREAK: break-all; BORDER-TOP: #cccccc 1px solid; BORDER-RIGHT: #cccccc 1px solid; PADDING-TOP: 4px"><img id=Codehighlighter1_1_10_Open_Image onclick="this.style.display='none'; Codehighlighter1_1_10_Open_Text.style.display='none'; Codehighlighter1_1_10_Closed_Image.style.display='inline'; Codehighlighter1_1_10_Closed_Text.style.display='inline';" align=top src="http://www.shnenglu.com/Images/OutliningIndicators/ExpandedBlockStart.gif"><img style="DISPLAY: none" id=Codehighlighter1_1_10_Closed_Image onclick="this.style.display='none'; Codehighlighter1_1_10_Closed_Text.style.display='none'; Codehighlighter1_1_10_Open_Image.style.display='inline'; Codehighlighter1_1_10_Open_Text.style.display='inline';" align=top src="http://www.shnenglu.com/Images/OutliningIndicators/ContractedBlock.gif"><span style="COLOR: #000000"> </span><span style="BORDER-BOTTOM: #808080 1px solid; BORDER-LEFT: #808080 1px solid; BACKGROUND-COLOR: #ffffff; DISPLAY: none; BORDER-TOP: #808080 1px solid; BORDER-RIGHT: #808080 1px solid" id=Codehighlighter1_1_10_Closed_Text>/**/</span><span id=Codehighlighter1_1_10_Open_Text><span style="COLOR: #808080">///</span><span style="COLOR: #008000"> Logic</span><span style="COLOR: #808080"></span></span><br><img align=top src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif"><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000"> EventNotify<br><img id=Codehighlighter1_31_101_Open_Image onclick="this.style.display='none'; Codehighlighter1_31_101_Open_Text.style.display='none'; Codehighlighter1_31_101_Closed_Image.style.display='inline'; Codehighlighter1_31_101_Closed_Text.style.display='inline';" align=top src="http://www.shnenglu.com/Images/OutliningIndicators/ExpandedBlockStart.gif"><img style="DISPLAY: none" id=Codehighlighter1_31_101_Closed_Image onclick="this.style.display='none'; Codehighlighter1_31_101_Closed_Text.style.display='none'; Codehighlighter1_31_101_Open_Image.style.display='inline'; Codehighlighter1_31_101_Open_Text.style.display='inline';" align=top src="http://www.shnenglu.com/Images/OutliningIndicators/ContractedBlock.gif"> </span><span style="BORDER-BOTTOM: #808080 1px solid; BORDER-LEFT: #808080 1px solid; BACKGROUND-COLOR: #ffffff; DISPLAY: none; BORDER-TOP: #808080 1px solid; BORDER-RIGHT: #808080 1px solid" id=Codehighlighter1_31_101_Closed_Text><img src="http://www.shnenglu.com/Images/dot.gif"></span><span id=Codehighlighter1_31_101_Open_Text><span style="COLOR: #000000">{<br><img align=top src="http://www.shnenglu.com/Images/OutliningIndicators/InBlock.gif"> </span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">:<br><img align=top src="http://www.shnenglu.com/Images/OutliningIndicators/InBlock.gif">  </span><span style="COLOR: #0000ff">virtual</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000"> OnEnterRgn( Player </span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">player, </span><span style="COLOR: #0000ff">long</span><span style="COLOR: #000000"> rgn_id );<br><img align=top src="http://www.shnenglu.com/Images/OutliningIndicators/ExpandedBlockEnd.gif"> }</span></span><span style="COLOR: #000000">;<br><img align=top src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif"><br><img id=Codehighlighter1_106_112_Open_Image onclick="this.style.display='none'; Codehighlighter1_106_112_Open_Text.style.display='none'; Codehighlighter1_106_112_Closed_Image.style.display='inline'; Codehighlighter1_106_112_Closed_Text.style.display='inline';" align=top src="http://www.shnenglu.com/Images/OutliningIndicators/ExpandedBlockStart.gif"><img style="DISPLAY: none" id=Codehighlighter1_106_112_Closed_Image onclick="this.style.display='none'; Codehighlighter1_106_112_Closed_Text.style.display='none'; Codehighlighter1_106_112_Open_Image.style.display='inline'; Codehighlighter1_106_112_Open_Text.style.display='inline';" align=top src="http://www.shnenglu.com/Images/OutliningIndicators/ContractedBlock.gif"> </span><span style="BORDER-BOTTOM: #808080 1px solid; BORDER-LEFT: #808080 1px solid; BACKGROUND-COLOR: #ffffff; DISPLAY: none; BORDER-TOP: #808080 1px solid; BORDER-RIGHT: #808080 1px solid" id=Codehighlighter1_106_112_Closed_Text>/**/</span><span id=Codehighlighter1_106_112_Open_Text><span style="COLOR: #808080">///</span><span style="COLOR: #008000"> UI</span><span style="COLOR: #808080"></span></span><br><img align=top src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif"><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000"> EventNotifyImpl : </span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000"> EventNotify<br><img id=Codehighlighter1_158_161_Open_Image onclick="this.style.display='none'; Codehighlighter1_158_161_Open_Text.style.display='none'; Codehighlighter1_158_161_Closed_Image.style.display='inline'; Codehighlighter1_158_161_Closed_Text.style.display='inline';" align=top src="http://www.shnenglu.com/Images/OutliningIndicators/ExpandedBlockStart.gif"><img style="DISPLAY: none" id=Codehighlighter1_158_161_Closed_Image onclick="this.style.display='none'; Codehighlighter1_158_161_Closed_Text.style.display='none'; Codehighlighter1_158_161_Open_Image.style.display='inline'; Codehighlighter1_158_161_Open_Text.style.display='inline';" align=top src="http://www.shnenglu.com/Images/OutliningIndicators/ContractedBlock.gif"> </span><span style="BORDER-BOTTOM: #808080 1px solid; BORDER-LEFT: #808080 1px solid; BACKGROUND-COLOR: #ffffff; DISPLAY: none; BORDER-TOP: #808080 1px solid; BORDER-RIGHT: #808080 1px solid" id=Codehighlighter1_158_161_Closed_Text><img src="http://www.shnenglu.com/Images/dot.gif"></span><span id=Codehighlighter1_158_161_Open_Text><span style="COLOR: #000000">{<br><img align=top src="http://www.shnenglu.com/Images/OutliningIndicators/ExpandedBlockEnd.gif"> }</span></span><span style="COLOR: #000000">;<br><img align=top src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif"><br><img id=Codehighlighter1_166_175_Open_Image onclick="this.style.display='none'; Codehighlighter1_166_175_Open_Text.style.display='none'; Codehighlighter1_166_175_Closed_Image.style.display='inline'; Codehighlighter1_166_175_Closed_Text.style.display='inline';" align=top src="http://www.shnenglu.com/Images/OutliningIndicators/ExpandedBlockStart.gif"><img style="DISPLAY: none" id=Codehighlighter1_166_175_Closed_Image onclick="this.style.display='none'; Codehighlighter1_166_175_Closed_Text.style.display='none'; Codehighlighter1_166_175_Open_Image.style.display='inline'; Codehighlighter1_166_175_Open_Text.style.display='inline';" align=top src="http://www.shnenglu.com/Images/OutliningIndicators/ContractedBlock.gif"> </span><span style="BORDER-BOTTOM: #808080 1px solid; BORDER-LEFT: #808080 1px solid; BACKGROUND-COLOR: #ffffff; DISPLAY: none; BORDER-TOP: #808080 1px solid; BORDER-RIGHT: #808080 1px solid" id=Codehighlighter1_166_175_Closed_Text>/**/</span><span id=Codehighlighter1_166_175_Open_Text><span style="COLOR: #808080">///</span><span style="COLOR: #008000"> Logic</span><span style="COLOR: #808080"></span></span><br><img align=top src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif"><span style="COLOR: #000000"> GetEventNotify()</span><span style="COLOR: #000000">-></span><span style="COLOR: #000000">OnEnterRgn( player, rgn_id );<br><img align=top src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif"></span></div> <p style="FONT-SIZE: 10pt"> </p> <p style="FONT-SIZE: 10pt">但是Q在代码写多之后Q逻辑模块需要通知的事件越来越多之后,EventNotifyq个cd?br>膨胀Q接口变多了(jin)、不同接口定义的参数看v来也来恶?j)?jin)?/p> <p style="FONT-SIZE: 10pt"><strong>改进</strong></p> <p style="FONT-SIZE: 10pt">于是我决定将各种事g通知l一化:(x)</p> <p style="FONT-SIZE: 10pt"> </p> <div style="BORDER-BOTTOM: #cccccc 1px solid; BORDER-LEFT: #cccccc 1px solid; PADDING-BOTTOM: 4px; BACKGROUND-COLOR: #eeeeee; PADDING-LEFT: 4px; WIDTH: 98%; PADDING-RIGHT: 5px; FONT-SIZE: 13px; WORD-BREAK: break-all; BORDER-TOP: #cccccc 1px solid; BORDER-RIGHT: #cccccc 1px solid; PADDING-TOP: 4px"><img align=top src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif"><span style="COLOR: #0000ff">struct</span><span style="COLOR: #000000"> Event<br><img id=Codehighlighter1_13_48_Open_Image onclick="this.style.display='none'; Codehighlighter1_13_48_Open_Text.style.display='none'; Codehighlighter1_13_48_Closed_Image.style.display='inline'; Codehighlighter1_13_48_Closed_Text.style.display='inline';" align=top src="http://www.shnenglu.com/Images/OutliningIndicators/ExpandedBlockStart.gif"><img style="DISPLAY: none" id=Codehighlighter1_13_48_Closed_Image onclick="this.style.display='none'; Codehighlighter1_13_48_Closed_Text.style.display='none'; Codehighlighter1_13_48_Open_Image.style.display='inline'; Codehighlighter1_13_48_Open_Text.style.display='inline';" align=top src="http://www.shnenglu.com/Images/OutliningIndicators/ContractedBlock.gif"></span><span style="BORDER-BOTTOM: #808080 1px solid; BORDER-LEFT: #808080 1px solid; BACKGROUND-COLOR: #ffffff; DISPLAY: none; BORDER-TOP: #808080 1px solid; BORDER-RIGHT: #808080 1px solid" id=Codehighlighter1_13_48_Closed_Text><img src="http://www.shnenglu.com/Images/dot.gif"></span><span id=Codehighlighter1_13_48_Open_Text><span style="COLOR: #000000">{<br><img align=top src="http://www.shnenglu.com/Images/OutliningIndicators/InBlock.gif"> </span><span style="COLOR: #0000ff">long</span><span style="COLOR: #000000"> type; </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> 事gcd</span><span style="COLOR: #008000"><br><img align=top src="http://www.shnenglu.com/Images/OutliningIndicators/InBlock.gif"></span><span style="COLOR: #000000"> <img src="http://www.shnenglu.com/Images/dot.gif"> </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> 附属参数</span><span style="COLOR: #008000"><br><img align=top src="http://www.shnenglu.com/Images/OutliningIndicators/ExpandedBlockEnd.gif"></span><span style="COLOR: #000000">}</span></span><span style="COLOR: #000000">;</span></div> <p style="FONT-SIZE: 10pt"> </p> <p style="FONT-SIZE: 10pt">q样Q逻辑模块只需要创Z件结构,两个模块间的通信只需要一个接口即可:(x)</p> <p style="FONT-SIZE: 10pt">void OnNotify( const Event &event );</p> <p style="FONT-SIZE: 10pt">但是问题又来?jin),不同的事件类型携带的附属参数Q数据)(j)不一栗也许,可以使用一个序列化<br>的组Ӟ各U数据先序列化,然后在事件处理模块对应地取数据出来。这样做L觉有点大?br>q戈?jin)。当?dng)也可以用C语言里的不定参数去解冻I如:(x)</p> <p style="FONT-SIZE: 10pt">void OnNotify( long event_type, ... )</p> <p style="FONT-SIZE: 10pt">其实Q我需要的是一个可以表面上cd一P但其内部保存的数据却多样的东ѝ这样一惻I<br>模块p让事情简单化Q?/p> <p style="FONT-SIZE: 10pt"> </p> <div style="BORDER-BOTTOM: #cccccc 1px solid; BORDER-LEFT: #cccccc 1px solid; PADDING-BOTTOM: 4px; BACKGROUND-COLOR: #eeeeee; PADDING-LEFT: 4px; WIDTH: 98%; PADDING-RIGHT: 5px; FONT-SIZE: 13px; WORD-BREAK: break-all; BORDER-TOP: #cccccc 1px solid; BORDER-RIGHT: #cccccc 1px solid; PADDING-TOP: 4px"><img align=top src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif"><span style="COLOR: #000000">template </span><span style="COLOR: #000000"><</span><span style="COLOR: #000000">typename P1, typename P2</span><span style="COLOR: #000000">></span><span style="COLOR: #000000"><br><img align=top src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif"></span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000"> Param<br><img id=Codehighlighter1_48_130_Open_Image onclick="this.style.display='none'; Codehighlighter1_48_130_Open_Text.style.display='none'; Codehighlighter1_48_130_Closed_Image.style.display='inline'; Codehighlighter1_48_130_Closed_Text.style.display='inline';" align=top src="http://www.shnenglu.com/Images/OutliningIndicators/ExpandedBlockStart.gif"><img style="DISPLAY: none" id=Codehighlighter1_48_130_Closed_Image onclick="this.style.display='none'; Codehighlighter1_48_130_Closed_Text.style.display='none'; Codehighlighter1_48_130_Open_Image.style.display='inline'; Codehighlighter1_48_130_Open_Text.style.display='inline';" align=top src="http://www.shnenglu.com/Images/OutliningIndicators/ContractedBlock.gif"></span><span style="BORDER-BOTTOM: #808080 1px solid; BORDER-LEFT: #808080 1px solid; BACKGROUND-COLOR: #ffffff; DISPLAY: none; BORDER-TOP: #808080 1px solid; BORDER-RIGHT: #808080 1px solid" id=Codehighlighter1_48_130_Closed_Text><img src="http://www.shnenglu.com/Images/dot.gif"></span><span id=Codehighlighter1_48_130_Open_Text><span style="COLOR: #000000">{<br><img align=top src="http://www.shnenglu.com/Images/OutliningIndicators/InBlock.gif"></span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">:<br><img align=top src="http://www.shnenglu.com/Images/OutliningIndicators/InBlock.gif"> Param( P1 p1, P2 p2 ) : _p1( p1 ), _p2( p2 )<br><img id=Codehighlighter1_105_108_Open_Image onclick="this.style.display='none'; Codehighlighter1_105_108_Open_Text.style.display='none'; Codehighlighter1_105_108_Closed_Image.style.display='inline'; Codehighlighter1_105_108_Closed_Text.style.display='inline';" align=top src="http://www.shnenglu.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif"><img style="DISPLAY: none" id=Codehighlighter1_105_108_Closed_Image onclick="this.style.display='none'; Codehighlighter1_105_108_Closed_Text.style.display='none'; Codehighlighter1_105_108_Open_Image.style.display='inline'; Codehighlighter1_105_108_Open_Text.style.display='inline';" align=top src="http://www.shnenglu.com/Images/OutliningIndicators/ContractedSubBlock.gif"> </span><span style="BORDER-BOTTOM: #808080 1px solid; BORDER-LEFT: #808080 1px solid; BACKGROUND-COLOR: #ffffff; DISPLAY: none; BORDER-TOP: #808080 1px solid; BORDER-RIGHT: #808080 1px solid" id=Codehighlighter1_105_108_Closed_Text><img src="http://www.shnenglu.com/Images/dot.gif"></span><span id=Codehighlighter1_105_108_Open_Text><span style="COLOR: #000000">{<br><img align=top src="http://www.shnenglu.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif"> }</span></span><span style="COLOR: #000000"><br><img align=top src="http://www.shnenglu.com/Images/OutliningIndicators/InBlock.gif"> <br><img align=top src="http://www.shnenglu.com/Images/OutliningIndicators/InBlock.gif"> P1 _p1;<br><img align=top src="http://www.shnenglu.com/Images/OutliningIndicators/InBlock.gif"> P2 _p2;<br><img align=top src="http://www.shnenglu.com/Images/OutliningIndicators/ExpandedBlockEnd.gif">}</span></span><span style="COLOR: #000000">;<br><img align=top src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif"><br><img align=top src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif">template </span><span style="COLOR: #000000"><</span><span style="COLOR: #000000">typename P1, typename P2</span><span style="COLOR: #000000">></span><span style="COLOR: #000000"><br><img align=top src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif"></span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000"> OnNotify( </span><span style="COLOR: #0000ff">long</span><span style="COLOR: #000000"> event_type, Param</span><span style="COLOR: #000000"><</span><span style="COLOR: #000000">P1, P2</span><span style="COLOR: #000000">></span><span style="COLOR: #000000"> param );<br><img align=top src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif"><br><img align=top src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif">GetNotify()</span><span style="COLOR: #000000">-></span><span style="COLOR: #000000">OnNotify( ET_ENTER_RGN, Param</span><span style="COLOR: #000000"><</span><span style="COLOR: #000000">Player</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">, </span><span style="COLOR: #0000ff">long</span><span style="COLOR: #000000">></span><span style="COLOR: #000000">( player, rgn_id ) );<br><img align=top src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif">GetNotify()</span><span style="COLOR: #000000">-></span><span style="COLOR: #000000">OnNotify( ET_MOVE, Param</span><span style="COLOR: #000000"><</span><span style="COLOR: #0000ff">long</span><span style="COLOR: #000000">, </span><span style="COLOR: #0000ff">long</span><span style="COLOR: #000000">></span><span style="COLOR: #000000">( x, y ) );<br><img align=top src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif"></span></div> <p style="FONT-SIZE: 10pt"> </p> <p style="FONT-SIZE: 10pt">在上面这个例子中Q虽焉过Param的包装,逻辑模块可以在事仉知里放|Q意类型的数据Q但<br>毕竟只支?个参数。实际上Z(jin)实现支持多个参数Qv码得?5个)(j)Q还是免不了(jin)自己实现多个<br>参数的Param?/p> <p style="FONT-SIZE: 10pt">q怺我以前写q宏递归产生代码的东西,可以自动地生成这U情况下诸如Param1、Param2的代码?br>如:(x)</p> <p style="FONT-SIZE: 10pt"> </p> <div style="BORDER-BOTTOM: #cccccc 1px solid; BORDER-LEFT: #cccccc 1px solid; PADDING-BOTTOM: 4px; BACKGROUND-COLOR: #eeeeee; PADDING-LEFT: 4px; WIDTH: 98%; PADDING-RIGHT: 5px; FONT-SIZE: 13px; WORD-BREAK: break-all; BORDER-TOP: #cccccc 1px solid; BORDER-RIGHT: #cccccc 1px solid; PADDING-TOP: 4px"><img align=top src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif"><span style="COLOR: #0000ff">#define</span><span style="COLOR: #000000"> CREATE_PARAM( n ) \</span><span style="COLOR: #000000"><br><img align=top src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif"> template </span><span style="COLOR: #000000"><</span><span style="COLOR: #000000">DEF_PARAM( n )</span><span style="COLOR: #000000">></span><span style="COLOR: #000000"> \<br><img align=top src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif"> </span><span style="COLOR: #0000ff">struct</span><span style="COLOR: #000000"> Param##n \<br><img id=Codehighlighter1_80_217_Open_Image onclick="this.style.display='none'; Codehighlighter1_80_217_Open_Text.style.display='none'; Codehighlighter1_80_217_Closed_Image.style.display='inline'; Codehighlighter1_80_217_Closed_Text.style.display='inline';" align=top src="http://www.shnenglu.com/Images/OutliningIndicators/ExpandedBlockStart.gif"><img style="DISPLAY: none" id=Codehighlighter1_80_217_Closed_Image onclick="this.style.display='none'; Codehighlighter1_80_217_Closed_Text.style.display='none'; Codehighlighter1_80_217_Open_Image.style.display='inline'; Codehighlighter1_80_217_Open_Text.style.display='inline';" align=top src="http://www.shnenglu.com/Images/OutliningIndicators/ContractedBlock.gif"> </span><span style="BORDER-BOTTOM: #808080 1px solid; BORDER-LEFT: #808080 1px solid; BACKGROUND-COLOR: #ffffff; DISPLAY: none; BORDER-TOP: #808080 1px solid; BORDER-RIGHT: #808080 1px solid" id=Codehighlighter1_80_217_Closed_Text><img src="http://www.shnenglu.com/Images/dot.gif"></span><span id=Codehighlighter1_80_217_Open_Text><span style="COLOR: #000000">{ \<br><img align=top src="http://www.shnenglu.com/Images/OutliningIndicators/InBlock.gif">  DEF_PARAM_TYPE( n ); \<br><img align=top src="http://www.shnenglu.com/Images/OutliningIndicators/InBlock.gif">  Param##n( DEF_FUNC_PARAM( n ) ) \<br><img id=Codehighlighter1_150_188_Open_Image onclick="this.style.display='none'; Codehighlighter1_150_188_Open_Text.style.display='none'; Codehighlighter1_150_188_Closed_Image.style.display='inline'; Codehighlighter1_150_188_Closed_Text.style.display='inline';" align=top src="http://www.shnenglu.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif"><img style="DISPLAY: none" id=Codehighlighter1_150_188_Closed_Image onclick="this.style.display='none'; Codehighlighter1_150_188_Closed_Text.style.display='none'; Codehighlighter1_150_188_Open_Image.style.display='inline'; Codehighlighter1_150_188_Open_Text.style.display='inline';" align=top src="http://www.shnenglu.com/Images/OutliningIndicators/ContractedSubBlock.gif">  </span><span style="BORDER-BOTTOM: #808080 1px solid; BORDER-LEFT: #808080 1px solid; BACKGROUND-COLOR: #ffffff; DISPLAY: none; BORDER-TOP: #808080 1px solid; BORDER-RIGHT: #808080 1px solid" id=Codehighlighter1_150_188_Closed_Text><img src="http://www.shnenglu.com/Images/dot.gif"></span><span id=Codehighlighter1_150_188_Open_Text><span style="COLOR: #000000">{ \<br><img align=top src="http://www.shnenglu.com/Images/OutliningIndicators/InBlock.gif">   DEF_MEM_VAR_ASSIGN( n ); \<br><img align=top src="http://www.shnenglu.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif">  }</span></span><span style="COLOR: #000000"> \<br><img align=top src="http://www.shnenglu.com/Images/OutliningIndicators/InBlock.gif">  DEF_VAR_DEF( n ); \<br><img align=top src="http://www.shnenglu.com/Images/OutliningIndicators/ExpandedBlockEnd.gif"> }</span></span><span style="COLOR: #000000"><br><img align=top src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif"><br><img align=top src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif"> CREATE_PARAM( </span><span style="COLOR: #000000">1</span><span style="COLOR: #000000"> );<br><img align=top src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif"> CREATE_PARAM( </span><span style="COLOR: #000000">2</span><span style="COLOR: #000000"> );<br><img align=top src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif"></span></div> <p style="FONT-SIZE: 10pt"> </p> <p style="FONT-SIZE: 10pt">卛_生成Param1和Param2的版本。其实这样定义了(jin)Param1、Param2的东西之后,又得OnNotify<br>的参C是特定的?jin)。虽然可以把Param也泛化,但是在逻辑层写q多的模板代码,L觉不好?/p> <p style="FONT-SIZE: 10pt">于是又想C前写的一个东西,可以把各U类型包装成一U类?--对于外界而言Qany。any?br>boost中有提到Q我只是实现?jin)个单的版本。any的大致实现手法就是在内部通过多态机制将?br>U类型在某种E度上隐藏,如:(x)</p> <p style="FONT-SIZE: 10pt"> </p> <div style="BORDER-BOTTOM: #cccccc 1px solid; BORDER-LEFT: #cccccc 1px solid; PADDING-BOTTOM: 4px; BACKGROUND-COLOR: #eeeeee; PADDING-LEFT: 4px; WIDTH: 98%; PADDING-RIGHT: 5px; FONT-SIZE: 13px; WORD-BREAK: break-all; BORDER-TOP: #cccccc 1px solid; BORDER-RIGHT: #cccccc 1px solid; PADDING-TOP: 4px"><img align=top src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif"><span style="COLOR: #000000">        </span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000"> base_type<br><img id=Codehighlighter1_32_169_Open_Image onclick="this.style.display='none'; Codehighlighter1_32_169_Open_Text.style.display='none'; Codehighlighter1_32_169_Closed_Image.style.display='inline'; Codehighlighter1_32_169_Closed_Text.style.display='inline';" align=top src="http://www.shnenglu.com/Images/OutliningIndicators/ExpandedBlockStart.gif"><img style="DISPLAY: none" id=Codehighlighter1_32_169_Closed_Image onclick="this.style.display='none'; Codehighlighter1_32_169_Closed_Text.style.display='none'; Codehighlighter1_32_169_Open_Image.style.display='inline'; Codehighlighter1_32_169_Open_Text.style.display='inline';" align=top src="http://www.shnenglu.com/Images/OutliningIndicators/ContractedBlock.gif">        </span><span style="BORDER-BOTTOM: #808080 1px solid; BORDER-LEFT: #808080 1px solid; BACKGROUND-COLOR: #ffffff; DISPLAY: none; BORDER-TOP: #808080 1px solid; BORDER-RIGHT: #808080 1px solid" id=Codehighlighter1_32_169_Closed_Text><img src="http://www.shnenglu.com/Images/dot.gif"></span><span id=Codehighlighter1_32_169_Open_Text><span style="COLOR: #000000">{<br><img align=top src="http://www.shnenglu.com/Images/OutliningIndicators/InBlock.gif">        </span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">:<br><img align=top src="http://www.shnenglu.com/Images/OutliningIndicators/InBlock.gif">            </span><span style="COLOR: #0000ff">virtual</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">~</span><span style="COLOR: #000000">base_type()<br><img id=Codehighlighter1_95_109_Open_Image onclick="this.style.display='none'; Codehighlighter1_95_109_Open_Text.style.display='none'; Codehighlighter1_95_109_Closed_Image.style.display='inline'; Codehighlighter1_95_109_Closed_Text.style.display='inline';" align=top src="http://www.shnenglu.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif"><img style="DISPLAY: none" id=Codehighlighter1_95_109_Closed_Image onclick="this.style.display='none'; Codehighlighter1_95_109_Closed_Text.style.display='none'; Codehighlighter1_95_109_Open_Image.style.display='inline'; Codehighlighter1_95_109_Open_Text.style.display='inline';" align=top src="http://www.shnenglu.com/Images/OutliningIndicators/ContractedSubBlock.gif">            </span><span style="BORDER-BOTTOM: #808080 1px solid; BORDER-LEFT: #808080 1px solid; BACKGROUND-COLOR: #ffffff; DISPLAY: none; BORDER-TOP: #808080 1px solid; BORDER-RIGHT: #808080 1px solid" id=Codehighlighter1_95_109_Closed_Text><img src="http://www.shnenglu.com/Images/dot.gif"></span><span id=Codehighlighter1_95_109_Open_Text><span style="COLOR: #000000">{<br><img align=top src="http://www.shnenglu.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif">            }</span></span><span style="COLOR: #000000"><br><img align=top src="http://www.shnenglu.com/Images/OutliningIndicators/InBlock.gif">            </span><span style="COLOR: #0000ff">virtual</span><span style="COLOR: #000000"> base_type </span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">clone() </span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;<br><img align=top src="http://www.shnenglu.com/Images/OutliningIndicators/ExpandedBlockEnd.gif">        }</span></span><span style="COLOR: #000000">;<br><img align=top src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif">        <br><img align=top src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif">        template </span><span style="COLOR: #000000"><</span><span style="COLOR: #000000">typename _Tp</span><span style="COLOR: #000000">></span><span style="COLOR: #000000"><br><img align=top src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif">        </span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000"> var_holder : </span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000"> base_type<br><img id=Codehighlighter1_265_600_Open_Image onclick="this.style.display='none'; Codehighlighter1_265_600_Open_Text.style.display='none'; Codehighlighter1_265_600_Closed_Image.style.display='inline'; Codehighlighter1_265_600_Closed_Text.style.display='inline';" align=top src="http://www.shnenglu.com/Images/OutliningIndicators/ExpandedBlockStart.gif"><img style="DISPLAY: none" id=Codehighlighter1_265_600_Closed_Image onclick="this.style.display='none'; Codehighlighter1_265_600_Closed_Text.style.display='none'; Codehighlighter1_265_600_Open_Image.style.display='inline'; Codehighlighter1_265_600_Open_Text.style.display='inline';" align=top src="http://www.shnenglu.com/Images/OutliningIndicators/ContractedBlock.gif">        </span><span style="BORDER-BOTTOM: #808080 1px solid; BORDER-LEFT: #808080 1px solid; BACKGROUND-COLOR: #ffffff; DISPLAY: none; BORDER-TOP: #808080 1px solid; BORDER-RIGHT: #808080 1px solid" id=Codehighlighter1_265_600_Closed_Text><img src="http://www.shnenglu.com/Images/dot.gif"></span><span id=Codehighlighter1_265_600_Open_Text><span style="COLOR: #000000">{<br><img align=top src="http://www.shnenglu.com/Images/OutliningIndicators/InBlock.gif">        </span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">:<br><img align=top src="http://www.shnenglu.com/Images/OutliningIndicators/InBlock.gif">            typedef _Tp type;<br><img align=top src="http://www.shnenglu.com/Images/OutliningIndicators/InBlock.gif">            typedef var_holder</span><span style="COLOR: #000000"><</span><span style="COLOR: #000000">type</span><span style="COLOR: #000000">></span><span style="COLOR: #000000"> self;<br><img align=top src="http://www.shnenglu.com/Images/OutliningIndicators/InBlock.gif">        </span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">:<br><img align=top src="http://www.shnenglu.com/Images/OutliningIndicators/InBlock.gif">            var_holder( </span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000"> type </span><span style="COLOR: #000000">&</span><span style="COLOR: #000000">t ) : _t( t )<br><img id=Codehighlighter1_434_448_Open_Image onclick="this.style.display='none'; Codehighlighter1_434_448_Open_Text.style.display='none'; Codehighlighter1_434_448_Closed_Image.style.display='inline'; Codehighlighter1_434_448_Closed_Text.style.display='inline';" align=top src="http://www.shnenglu.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif"><img style="DISPLAY: none" id=Codehighlighter1_434_448_Closed_Image onclick="this.style.display='none'; Codehighlighter1_434_448_Closed_Text.style.display='none'; Codehighlighter1_434_448_Open_Image.style.display='inline'; Codehighlighter1_434_448_Open_Text.style.display='inline';" align=top src="http://www.shnenglu.com/Images/OutliningIndicators/ContractedSubBlock.gif">            </span><span style="BORDER-BOTTOM: #808080 1px solid; BORDER-LEFT: #808080 1px solid; BACKGROUND-COLOR: #ffffff; DISPLAY: none; BORDER-TOP: #808080 1px solid; BORDER-RIGHT: #808080 1px solid" id=Codehighlighter1_434_448_Closed_Text><img src="http://www.shnenglu.com/Images/dot.gif"></span><span id=Codehighlighter1_434_448_Open_Text><span style="COLOR: #000000">{<br><img align=top src="http://www.shnenglu.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif">            }</span></span><span style="COLOR: #000000"><br><img align=top src="http://www.shnenglu.com/Images/OutliningIndicators/InBlock.gif"><br><img align=top src="http://www.shnenglu.com/Images/OutliningIndicators/InBlock.gif">            base_type </span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">clone() </span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000"><br><img id=Codehighlighter1_500_553_Open_Image onclick="this.style.display='none'; Codehighlighter1_500_553_Open_Text.style.display='none'; Codehighlighter1_500_553_Closed_Image.style.display='inline'; Codehighlighter1_500_553_Closed_Text.style.display='inline';" align=top src="http://www.shnenglu.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif"><img style="DISPLAY: none" id=Codehighlighter1_500_553_Closed_Image onclick="this.style.display='none'; Codehighlighter1_500_553_Closed_Text.style.display='none'; Codehighlighter1_500_553_Open_Image.style.display='inline'; Codehighlighter1_500_553_Open_Text.style.display='inline';" align=top src="http://www.shnenglu.com/Images/OutliningIndicators/ContractedSubBlock.gif">            </span><span style="BORDER-BOTTOM: #808080 1px solid; BORDER-LEFT: #808080 1px solid; BACKGROUND-COLOR: #ffffff; DISPLAY: none; BORDER-TOP: #808080 1px solid; BORDER-RIGHT: #808080 1px solid" id=Codehighlighter1_500_553_Closed_Text><img src="http://www.shnenglu.com/Images/dot.gif"></span><span id=Codehighlighter1_500_553_Open_Text><span style="COLOR: #000000">{<br><img align=top src="http://www.shnenglu.com/Images/OutliningIndicators/InBlock.gif">                </span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000"> self( _t );<br><img align=top src="http://www.shnenglu.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif">            }</span></span><span style="COLOR: #000000"><br><img align=top src="http://www.shnenglu.com/Images/OutliningIndicators/InBlock.gif">        </span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">:<br><img align=top src="http://www.shnenglu.com/Images/OutliningIndicators/InBlock.gif">            type _t;<br><img align=top src="http://www.shnenglu.com/Images/OutliningIndicators/ExpandedBlockEnd.gif">        }</span></span><span style="COLOR: #000000"><br><img align=top src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif"></span></div> <p style="FONT-SIZE: 10pt"><br>q样Qanyc通过一个base_typec,利用C++多态机制即可将cd隐藏于var_holder里。那么,<br>最l的事g通知接口成ؓ(f)下面的样子:(x)</p> <p style="FONT-SIZE: 10pt">void OnNotify( long type, any data );</p> <p style="FONT-SIZE: 10pt">OnNotify( ET_ENTER_RGN, any( create_param( player, rgn_id ) ) );其中Qcreate_param<br>是一个辅助函敎ͼ用于创徏各种Param对象?/p> <p style="FONT-SIZE: 10pt">事实上,实现各种ParamN版本Q让其名字不一样其实有点不妥。还有一U方法可以让Param的名?br>只有一个,那就是模板偏特化。例如:(x)</p> <p style="FONT-SIZE: 10pt"> </p> <div style="BORDER-BOTTOM: #cccccc 1px solid; BORDER-LEFT: #cccccc 1px solid; PADDING-BOTTOM: 4px; BACKGROUND-COLOR: #eeeeee; PADDING-LEFT: 4px; WIDTH: 98%; PADDING-RIGHT: 5px; FONT-SIZE: 13px; WORD-BREAK: break-all; BORDER-TOP: #cccccc 1px solid; BORDER-RIGHT: #cccccc 1px solid; PADDING-TOP: 4px"><img align=top src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif"><span style="COLOR: #000000">template </span><span style="COLOR: #000000"><</span><span style="COLOR: #000000">typename _Tp</span><span style="COLOR: #000000">></span><span style="COLOR: #000000"><br><img align=top src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif"></span><span style="COLOR: #0000ff">struct</span><span style="COLOR: #000000"> Param;<br><img align=top src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif"><br><img align=top src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif">template </span><span style="COLOR: #000000"><></span><span style="COLOR: #000000"><br><img align=top src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif"></span><span style="COLOR: #0000ff">struct</span><span style="COLOR: #000000"> Param</span><span style="COLOR: #000000"><</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">()</span><span style="COLOR: #000000">></span><span style="COLOR: #000000">;<br><img align=top src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif"><br><img align=top src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif">template </span><span style="COLOR: #000000"><</span><span style="COLOR: #000000">typename P1</span><span style="COLOR: #000000">></span><span style="COLOR: #000000"><br><img align=top src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif"></span><span style="COLOR: #0000ff">struct</span><span style="COLOR: #000000"> Param</span><span style="COLOR: #000000"><</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">(P1)</span><span style="COLOR: #000000">></span><span style="COLOR: #000000"><br><img align=top src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif"><br><img align=top src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif">template </span><span style="COLOR: #000000"><</span><span style="COLOR: #000000">typename P1, typename P2</span><span style="COLOR: #000000">></span><span style="COLOR: #000000"><br><img align=top src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif"></span><span style="COLOR: #0000ff">struct</span><span style="COLOR: #000000"> Param</span><span style="COLOR: #000000"><</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">(P1,P2)</span><span style="COLOR: #000000">></span><span style="COLOR: #000000"><br><img align=top src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif"></span></div> <p style="FONT-SIZE: 10pt"> </p> <p style="FONT-SIZE: 10pt">q种Ҏ(gu)主要是通过l合ZU函数类型,来实现偏特化。因为我觉得构造一个函数类型给L版,<br>q不是一U合情理的事情。但是,即使用偏特化来让Param名字看v来只有一个,但对于不同的<br>实例化版本,q是不同的类型,所以还是需要any来包装?/p> <p style="FONT-SIZE: 10pt"><strong>实际使用</strong></p> <p style="FONT-SIZE: 10pt">实际使用h让我觉得非常赏心(j)(zhn)目。上面做的这些事情,实际上是做了(jin)一个不同模块间零耦合<br>通信的通道Q零耦合g有点q激Q。现在逻辑模块通知UI模块Q只需要定义新的事件类型,?br>两边分别写通知和处理通知的代码即可?/p> <p style="FONT-SIZE: 10pt">PS:<br>针对一些评论,我再解释下。其实any只是用于包装Param列表而已Q这里也可以用void*Q再转成<br>Param*。在q里q多地关注是用any*q是用void*其实偏离?jin)本文的重点。本文的重点其实是ParamQ?/p> <p style="FONT-SIZE: 10pt"> </p> <div style="BORDER-BOTTOM: #cccccc 1px solid; BORDER-LEFT: #cccccc 1px solid; PADDING-BOTTOM: 4px; BACKGROUND-COLOR: #eeeeee; PADDING-LEFT: 4px; WIDTH: 98%; PADDING-RIGHT: 5px; FONT-SIZE: 13px; WORD-BREAK: break-all; BORDER-TOP: #cccccc 1px solid; BORDER-RIGHT: #cccccc 1px solid; PADDING-TOP: 4px"><img align=top src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif"><span style="COLOR: #000000">OnNotify( NT_ENTER_RGN, ang( create_param( player, rgn_id ) ) );<br><img align=top src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif"><br><img align=top src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif"></span><span style="COLOR: #000000">-></span><span style="COLOR: #000000"><br><img align=top src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif"></span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000"> OnNotify( </span><span style="COLOR: #0000ff">long</span><span style="COLOR: #000000"> type, any data )<br><img id=Codehighlighter1_106_235_Open_Image onclick="this.style.display='none'; Codehighlighter1_106_235_Open_Text.style.display='none'; Codehighlighter1_106_235_Closed_Image.style.display='inline'; Codehighlighter1_106_235_Closed_Text.style.display='inline';" align=top src="http://www.shnenglu.com/Images/OutliningIndicators/ExpandedBlockStart.gif"><img style="DISPLAY: none" id=Codehighlighter1_106_235_Closed_Image onclick="this.style.display='none'; Codehighlighter1_106_235_Closed_Text.style.display='none'; Codehighlighter1_106_235_Open_Image.style.display='inline'; Codehighlighter1_106_235_Open_Text.style.display='inline';" align=top src="http://www.shnenglu.com/Images/OutliningIndicators/ContractedBlock.gif"></span><span style="BORDER-BOTTOM: #808080 1px solid; BORDER-LEFT: #808080 1px solid; BACKGROUND-COLOR: #ffffff; DISPLAY: none; BORDER-TOP: #808080 1px solid; BORDER-RIGHT: #808080 1px solid" id=Codehighlighter1_106_235_Closed_Text><img src="http://www.shnenglu.com/Images/dot.gif"></span><span id=Codehighlighter1_106_235_Open_Text><span style="COLOR: #000000">{<br><img align=top src="http://www.shnenglu.com/Images/OutliningIndicators/InBlock.gif"> Param2</span><span style="COLOR: #000000"><</span><span style="COLOR: #000000">Player</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">, </span><span style="COLOR: #0000ff">long</span><span style="COLOR: #000000">></span><span style="COLOR: #000000"> ParamType;<br><img align=top src="http://www.shnenglu.com/Images/OutliningIndicators/InBlock.gif"> ParamType </span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">p </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> any_cast</span><span style="COLOR: #000000"><</span><span style="COLOR: #000000">ParamType</span><span style="COLOR: #000000">></span><span style="COLOR: #000000">( </span><span style="COLOR: #000000">&</span><span style="COLOR: #000000">data );<br><img align=top src="http://www.shnenglu.com/Images/OutliningIndicators/InBlock.gif"> Player </span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">player </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> p</span><span style="COLOR: #000000">-></span><span style="COLOR: #000000">p1;<br><img align=top src="http://www.shnenglu.com/Images/OutliningIndicators/InBlock.gif"> </span><span style="COLOR: #0000ff">long</span><span style="COLOR: #000000"> rgn_id </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> p</span><span style="COLOR: #000000">-></span><span style="COLOR: #000000">p2;<br><img align=top src="http://www.shnenglu.com/Images/OutliningIndicators/ExpandedBlockEnd.gif">}</span></span><span style="COLOR: #000000"><br><img align=top src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif"><br><img align=top src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif"></span></div> <p style="FONT-SIZE: 10pt"><br><br><a href="http://www.shnenglu.com/Files/kevinlynx/ParamList.rar">下蝲相关代码</a></p> <img src ="http://www.shnenglu.com/kevinlynx/aggbug/94143.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/kevinlynx/" target="_blank">Kevin Lynx</a> 2009-08-23 09:55 <a href="http://www.shnenglu.com/kevinlynx/archive/2009/08/23/94143.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>指针和模块健?/title><link>http://www.shnenglu.com/kevinlynx/archive/2009/06/28/88711.html</link><dc:creator>Kevin Lynx</dc:creator><author>Kevin Lynx</author><pubDate>Sun, 28 Jun 2009 11:35:00 GMT</pubDate><guid>http://www.shnenglu.com/kevinlynx/archive/2009/06/28/88711.html</guid><wfw:comment>http://www.shnenglu.com/kevinlynx/comments/88711.html</wfw:comment><comments>http://www.shnenglu.com/kevinlynx/archive/2009/06/28/88711.html#Feedback</comments><slash:comments>5</slash:comments><wfw:commentRss>http://www.shnenglu.com/kevinlynx/comments/commentRss/88711.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/kevinlynx/services/trackbacks/88711.html</trackback:ping><description><![CDATA[<p><font size=2>仔细x(chng)能导致一个C++E序崩溃的几?0%原因都是跟指针有兟뀂空指针野指针,一不小?br>E序崩?jin)。写C(j)++E序的h基本上都知道q个问题。在我们周围避免q些问题的常规方?br>也很多,诸如auto_ptrQ及(qing)其他Ztemplate的原始指针wrapperQ、SAFE_DELETE。当然也<br>?x)有很多人在实现一个函数时?x)很勤劳地对每一个parameterq行合法判断?</font> <p><font size=2>其实Q我们都知道Qauto_ptrq些东西始终是无法避免野指针和空指针带来的灾难?br>SAFE_DELETE也不能阻止别Z用这个空指针?</font> <p><font size=2>在我看过的一些开源项目的代码中,q些代码lh的感觉就是别人总能详细地掌控各U资?br>Q包括指针及(qing)其他变量Q的使用情况。相比之下,公司隔壁l的老大则显得保守很多。他?br>求我们几乎要Ҏ(gu)有指针的使用q行I值判断(野指针也判断不了(jin)Q,当然Q各U成员变?br>也要q行即现在看上L多大用的初始化?</font> <p><font size=2>也许Q这样做后程序是不会(x)挂掉?jin)。但是,我们的观点来看Q这样反而会(x)隐藏一些BUG?br>Z么我们不能详地ȝ理一个指针?一个指针变?sh)空了(jin),L因ؓ(f)在这之前发生?jin)错?br>。当?dng)野指针本w就是愚蠢代码生的东西Q这里没必要讨论。空指针之所以ؓ(f)I,也是<br>因ؓ(f)在很多时候我们把IZ为失?错误/无效的标志?</font> <p><font size=2>恰好上周我的一些代码就真的在空指针上出C(jin)问题。外|的服务器随时会(x)因ؓ(f)玩家的一?br>临界操作行ؓ(f)而崩溃掉。虽然我通过修改脚本来屏蔽这个问题(因ؓ(f)不能说停机维护就停机<br>l护Q,但是L觉程序是不安全的。h不吃Ҏ(gu)训绝对不学乖?</font> <p><font size=2>后来我对q个问题d思考了(jin)一下。很多程序员都自认聪明。在写C(j)++E序Ӟ我从来不?br>供没用的public接口Q尤其是set/get。我也从来不Ҏ(gu)必要的成员变量进行初始化。我l?br>的理由是对于q些东西我都有很清晰的把握,我ؓ(f)什么要做stupid的事情? </font> <p><font size=2>但是Q我几乎从来没有界定Q指针在哪些情况下需要去判断为空Q函数的参数l对不需要?br>假如函数的参数就是个I指针,那是clientE序员的责Q。仅供模块内使用的指针(包含?br>他资源)(j)在内部用时也不需要去判断。如果去判断?jin),那说明你对你自己写的模块都缺?br>_的把握,证明你的设计思维不够清晰?</font> <p><font size=2>什么时候需要判断?当指针依赖于外部环境Ӟ例如读配|文件、蝲入资源,因ؓ(f)外部因素<br>不确定不在自己控制范围内Q那么进行判断。同P当用了(jin)其他模块q回的指针值时Q也<br>需要判断。这个其实和“外部环境”属于同一U情c(din)因为我们对其他模块也不清楚Q更?br>隐蔽的是Q随着其他模块的改变,来?x)在你的模块里爆发崩溃错误?j)Q其他模块由别hl?br>护,其变化更不受自己控制。之前我对这一点界定不是很清楚Q这也是我犯错的原因?</font> <p><font size=2>现在x(chng)Q像游戏服务器这U程序,里面塞着各种各样的游戏功能。无论是哪一个模块出?br>个空指针讉K出错的问题,都会(x)直接让服务器崩掉。关键是q个l果l常伴随着玩家的损?br>。所以理想状态下Q把每一个模块都攄在单独的q程里,实是很有好处的?</font></p> <img src ="http://www.shnenglu.com/kevinlynx/aggbug/88711.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/kevinlynx/" target="_blank">Kevin Lynx</a> 2009-06-28 19:35 <a href="http://www.shnenglu.com/kevinlynx/archive/2009/06/28/88711.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>最q的两个问题Qless for std::mapQ静(rn)态变量初始化序http://www.shnenglu.com/kevinlynx/archive/2008/11/11/66623.htmlKevin LynxKevin LynxTue, 11 Nov 2008 09:55:00 GMThttp://www.shnenglu.com/kevinlynx/archive/2008/11/11/66623.htmlhttp://www.shnenglu.com/kevinlynx/comments/66623.htmlhttp://www.shnenglu.com/kevinlynx/archive/2008/11/11/66623.html#Feedback13http://www.shnenglu.com/kevinlynx/comments/commentRss/66623.htmlhttp://www.shnenglu.com/kevinlynx/services/trackbacks/66623.html
说下最q自己遇到的两个值得让h注意的问题?br>其一是关于自qstd::map写less predicateQstd::mapW三个参数是一个典型的functor。map内部?br>q个functord定两个元素是否相{,默认使用的是std::less。但是ؓ(f)什么传入的是一个判断第一个参?br>于W二个参数的functorQ而不是一个判断两个参数是否相{的functorQ按照STL文的说法,当检查两
个参数没有小于也没有大于的关pLQ就表示两个参数相等。不怎样Q我遇到?jin)需要自己写q个functor
的需求,于是Q?/p>

struct MyLess
{
    bool operator() ( long left, long right )
    {
        //...
    }
};

DEBUG模式下编译没问题QRELEASE模式下却出现C3848的错误。这有点奇怪了(jin)Q如果确实存在语法错误,
那么DEBUG和RELASE应该一h寏V查?jin)下MSDNQC3848的错误是因ؓ(f)const限定W造成的,如:(x)

const MyLess pr;
pr(); // C3848

于是Q在operator()后加上constQ就O(jin)K?jin)。看?jin)下VC std::map相关代码Q以为是DEBUG和RELEASE使用?jin)?br>同的代码造成。但是我始终没找C同点。另一斚wQ就STL内部的风格来看,应该不会(x)把predicator处理
成const &之类的东西,全部是value形式的。奇怪了(jin)?/p>

W二个问题,涉及(qing)到静(rn)态变量。这个东西给我的印象特别深刻Q因Z前去一家外企应聘时被问刎ͼ当时
觉得那个LEADER特别厉害。回来后让我反思,是不是过多地x(chng)?jin)C++里的花哨Q而漏掉了(jin)C里的朴素Q导?br>我至今对UC存在偏好?/p>

说正题,我现在有如下的文件关p:(x)

// def.h
struct Obj
{
    Obj()
 {
  ObjMgr::AddObj( id, this );
 }
 int id;
};

struct ObjMgr
{
    static void AddObj( int id, Obj *t )
 {
  ObjTable[id] = t;
 }
 static std::map<int, Obj*> ObjTable;
};

static Obj _t;

// ObjMgr.cpp
#include "def.h"

static std::map<int, Obj*>::ObjMgr ObjTable;

// main.cpp
#include "def.h"

q里丄例子可能有点不恰当,我在一台没有编译器的机器上写的q篇文章。忽略掉q些旁支末节。我的意思,
是惌Obj自己自动向ObjMgr里添加自己。我们都知道?rn)态变量将在程序启动时被初始化Q先于main执行之前?/p>

上面代码有两个问题:(x)

一?br>代码没有按照我预期地执行Q如果你按照我的意思做个测试,你的E序甚至在进main之前crash?jin)。我假定?br>用的是VCQ因为我没在其他~译器上试验q。问题就在于QObj的构造依赖于ObjTableq个map对象。在调试q程
中我发现Q虽然ObjTable拥有?jin)内存空_(d)其this指针有效Q但是,map对象q没有得到构造。我的意思是QObj
的构造先于ObjTable构造(下几个断点即可轻易发玎ͼ(j)Q那么在执行map::operator[]Ӟ出错了(jin)Q因个时?br>map里相x(chng)据还没准备好?/p>

那是否存在某U机制可以手动静(rn)态变量的初始化顺序呢Q不知道。我最后怎样解决q个问题的?

二?br>在还没有惛_解决办法之前Q不改变我的设计Q,我发C(jin)q段代码的另一个问题:(x)我在头文仉定义?jin)?rn)?br>变量Qstatic Obj _t; q有什么问题?x(chng)预编译这个过E即可知道,头文件在预编译阶D被文本展开到CPP
文g里,然后QObjMgr.cpp和main.cpp文g里都出现static Obj _t;代码。也是_(d)ObjMgr.obj和main.obj
里都有一个文仉(rn)态变量_t?/p>

看来Q在头文仉放这个静(rn)态变量是肯定不对的。于是,我将_tUd到ObjMgr.cpp里:(x)

// ObjMgr.cpp
#include "def.h"

static std::map<int, Obj*>::ObjMgr ObjTable;
static Obj _t;

按照q样的顺序定义后Q_t的构造居然晚于ObjTable?jin)。也是_(d)攄于前面的变量定义Q就意味着它将?br>首先构造初始化。这样两个问题都解决?jin)?/p>

但是Q谁能保证这一点特性?C标准文档里?q是VC~译器自己?

 

 

 


 



Kevin Lynx 2008-11-11 17:55 发表评论
]]>
Proactor和Reactor模式_l箋(hu)q发pȝ设计的扫?/title><link>http://www.shnenglu.com/kevinlynx/archive/2008/06/06/52356.html</link><dc:creator>Kevin Lynx</dc:creator><author>Kevin Lynx</author><pubDate>Fri, 06 Jun 2008 05:25:00 GMT</pubDate><guid>http://www.shnenglu.com/kevinlynx/archive/2008/06/06/52356.html</guid><wfw:comment>http://www.shnenglu.com/kevinlynx/comments/52356.html</wfw:comment><comments>http://www.shnenglu.com/kevinlynx/archive/2008/06/06/52356.html#Feedback</comments><slash:comments>7</slash:comments><wfw:commentRss>http://www.shnenglu.com/kevinlynx/comments/commentRss/52356.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/kevinlynx/services/trackbacks/52356.html</trackback:ping><description><![CDATA[<p><font size=2>6.6.2008 </font> <p><font size=2>Kevin Lynx </font> <p><font size=2>Proactor?a target=_blank>Reactor</a>都是q发~程中的设计模式。在我看来,他们都是用于z֏/分离IO操作事g的。这里所谓的<br>IO事g也就是诸如read/write的IO操作?z֏/分离"是单独的IO事g通知C层模块。两个模式不同的地方<br>在于QProactor用于异步IOQ而Reactor用于同步IO?</font> <p><font size=2>摘抄一些关键的东西Q?</font> <p><font size=2>"<br>Two patterns that involve event demultiplexors are called Reactor and Proactor [1]. The Reactor patterns <br>involve synchronous I/O, whereas the Proactor pattern involves asynchronous I/O.<br>" </font> <p><font size=2>关于两个模式的大致模型,从以下文字基本可以明白:(x) </font> <p><font size=2>"<br>An example will help you understand the difference between Reactor and Proactor. We will focus on the read <br>operation here, as the write implementation is similar. Here's a read in Reactor: </font> <p><font size=2>* An event handler declares interest in I/O events that indicate readiness for read on a particular socket ;<br>* The event demultiplexor waits for events ;<br>* An event comes in and wakes-up the demultiplexor, and the demultiplexor calls the appropriate handler; <br>* The event handler performs the actual read operation, handles the data read, declares renewed interest in <br>  I/O events, and returns control to the dispatcher . </font> <p><font size=2>By comparison, here is a read operation in Proactor (true async): </font> <p><font size=2>* A handler initiates an asynchronous read operation (note: the OS must support asynchronous I/O). In this <br>  case, the handler does not care about I/O readiness events, but is instead registers interest in receiving <br>  completion events;<br>* The event demultiplexor waits until the operation is completed ;<br>* While the event demultiplexor waits, the OS executes the read operation in a parallel kernel thread, puts <br>  data into a user-defined buffer, and notifies the event demultiplexor that the read is complete ;<br>* The event demultiplexor calls the appropriate handler; <br>* The event handler handles the data from user defined buffer, starts a new asynchronous operation, and returns<br>  control to the event demultiplexor. </font> <p><font size=2>" </font> <p><font size=2>可以看出Q两个模式的相同点,都是Ҏ(gu)个IO事g的事仉知(卛_诉某个模块,q个IO操作可以q行或已l完?。在l构<br>上,两者也有相同点Qdemultiplexor负责提交IO操作(异步)、查询设备是否可操作(同步)Q然后当条g满Ӟ回调handler?br>不同点在于,异步情况?Proactor)Q当回调handlerӞ表示IO操作已经完成Q同步情况下(Reactor)Q回调handlerӞ表示<br>IO讑֤可以q行某个操作(can read or can write)Qhandlerq个时候开始提交操作?</font> <p><font size=2>用select模型写个单的reactorQ大致ؓ(f)Q?</font> <p><font size=2></p> <div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img id=Codehighlighter1_0_3_Open_Image onclick="this.style.display='none'; Codehighlighter1_0_3_Open_Text.style.display='none'; Codehighlighter1_0_3_Closed_Image.style.display='inline'; Codehighlighter1_0_3_Closed_Text.style.display='inline';" src="http://www.shnenglu.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_0_3_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_0_3_Closed_Text.style.display='none'; Codehighlighter1_0_3_Open_Image.style.display='inline'; Codehighlighter1_0_3_Open_Text.style.display='inline';" src="http://www.shnenglu.com/Images/OutliningIndicators/ContractedBlock.gif" align=top><span id=Codehighlighter1_0_3_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff">/**/</span><span id=Codehighlighter1_0_3_Open_Text><span style="COLOR: #808080">///</span></span><br><img src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000"> handler<br><img id=Codehighlighter1_18_124_Open_Image onclick="this.style.display='none'; Codehighlighter1_18_124_Open_Text.style.display='none'; Codehighlighter1_18_124_Closed_Image.style.display='inline'; Codehighlighter1_18_124_Closed_Text.style.display='inline';" src="http://www.shnenglu.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_18_124_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_18_124_Closed_Text.style.display='none'; Codehighlighter1_18_124_Open_Image.style.display='inline'; Codehighlighter1_18_124_Open_Text.style.display='inline';" src="http://www.shnenglu.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_18_124_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.shnenglu.com/Images/dot.gif"></span><span id=Codehighlighter1_18_124_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.shnenglu.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">:<br><img src="http://www.shnenglu.com/Images/OutliningIndicators/InBlock.gif" align=top>    </span><span style="COLOR: #0000ff">virtual</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000"> onRead() </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;<br><img src="http://www.shnenglu.com/Images/OutliningIndicators/InBlock.gif" align=top>    </span><span style="COLOR: #0000ff">virtual</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000"> onWrite() </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;<br><img src="http://www.shnenglu.com/Images/OutliningIndicators/InBlock.gif" align=top>    </span><span style="COLOR: #0000ff">virtual</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000"> onAccept() </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;<br><img src="http://www.shnenglu.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span><span style="COLOR: #000000">; <br><img src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000"> dispatch<br><img id=Codehighlighter1_144_804_Open_Image onclick="this.style.display='none'; Codehighlighter1_144_804_Open_Text.style.display='none'; Codehighlighter1_144_804_Closed_Image.style.display='inline'; Codehighlighter1_144_804_Closed_Text.style.display='inline';" src="http://www.shnenglu.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_144_804_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_144_804_Closed_Text.style.display='none'; Codehighlighter1_144_804_Open_Image.style.display='inline'; Codehighlighter1_144_804_Open_Text.style.display='inline';" src="http://www.shnenglu.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_144_804_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.shnenglu.com/Images/dot.gif"></span><span id=Codehighlighter1_144_804_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.shnenglu.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">:<br><img src="http://www.shnenglu.com/Images/OutliningIndicators/InBlock.gif" align=top>    </span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000"> poll()<br><img id=Codehighlighter1_174_696_Open_Image onclick="this.style.display='none'; Codehighlighter1_174_696_Open_Text.style.display='none'; Codehighlighter1_174_696_Closed_Image.style.display='inline'; Codehighlighter1_174_696_Closed_Text.style.display='inline';" src="http://www.shnenglu.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_174_696_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_174_696_Closed_Text.style.display='none'; Codehighlighter1_174_696_Open_Image.style.display='inline'; Codehighlighter1_174_696_Open_Text.style.display='inline';" src="http://www.shnenglu.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>    </span><span id=Codehighlighter1_174_696_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.shnenglu.com/Images/dot.gif"></span><span id=Codehighlighter1_174_696_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.shnenglu.com/Images/OutliningIndicators/InBlock.gif" align=top>        </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> add fd in the set.<br><img src="http://www.shnenglu.com/Images/OutliningIndicators/InBlock.gif" align=top>        </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"><img src="http://www.shnenglu.com/Images/dot.gif"><br><img src="http://www.shnenglu.com/Images/OutliningIndicators/InBlock.gif" align=top>        </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> poll every fd</span><span style="COLOR: #008000"><br><img src="http://www.shnenglu.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #000000">        </span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000"> c </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> select( </span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">, </span><span style="COLOR: #000000">&</span><span style="COLOR: #000000">read_fd, </span><span style="COLOR: #000000">&</span><span style="COLOR: #000000">write_fd, </span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">, </span><span style="COLOR: #000000">0</span><span style="COLOR: #000000"> );<br><img src="http://www.shnenglu.com/Images/OutliningIndicators/InBlock.gif" align=top>        </span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">( c </span><span style="COLOR: #000000">></span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">0</span><span style="COLOR: #000000"> )<br><img id=Codehighlighter1_329_690_Open_Image onclick="this.style.display='none'; Codehighlighter1_329_690_Open_Text.style.display='none'; Codehighlighter1_329_690_Closed_Image.style.display='inline'; Codehighlighter1_329_690_Closed_Text.style.display='inline';" src="http://www.shnenglu.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_329_690_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_329_690_Closed_Text.style.display='none'; Codehighlighter1_329_690_Open_Image.style.display='inline'; Codehighlighter1_329_690_Open_Text.style.display='inline';" src="http://www.shnenglu.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>        </span><span id=Codehighlighter1_329_690_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.shnenglu.com/Images/dot.gif"></span><span id=Codehighlighter1_329_690_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.shnenglu.com/Images/OutliningIndicators/InBlock.gif" align=top>            </span><span style="COLOR: #0000ff">for</span><span style="COLOR: #000000"> each fd </span><span style="COLOR: #0000ff">in</span><span style="COLOR: #000000"> the read_fd_set<br><img id=Codehighlighter1_386_533_Open_Image onclick="this.style.display='none'; Codehighlighter1_386_533_Open_Text.style.display='none'; Codehighlighter1_386_533_Closed_Image.style.display='inline'; Codehighlighter1_386_533_Closed_Text.style.display='inline';" src="http://www.shnenglu.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_386_533_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_386_533_Closed_Text.style.display='none'; Codehighlighter1_386_533_Open_Image.style.display='inline'; Codehighlighter1_386_533_Open_Text.style.display='inline';" src="http://www.shnenglu.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>            </span><span id=Codehighlighter1_386_533_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.shnenglu.com/Images/dot.gif"></span><span id=Codehighlighter1_386_533_Open_Text><span style="COLOR: #000000">{    </span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000"> fd can read<br><img src="http://www.shnenglu.com/Images/OutliningIndicators/InBlock.gif" align=top>                    _handler</span><span style="COLOR: #000000">-></span><span style="COLOR: #000000">onRead();<br><img src="http://www.shnenglu.com/Images/OutliningIndicators/InBlock.gif" align=top>                </span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000"> fd can accept<br><img src="http://www.shnenglu.com/Images/OutliningIndicators/InBlock.gif" align=top>                    _handler</span><span style="COLOR: #000000">-></span><span style="COLOR: #000000">onAccept();<br><img src="http://www.shnenglu.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>            }</span></span><span style="COLOR: #000000"> <br><img src="http://www.shnenglu.com/Images/OutliningIndicators/InBlock.gif" align=top><br><img src="http://www.shnenglu.com/Images/OutliningIndicators/InBlock.gif" align=top>            </span><span style="COLOR: #0000ff">for</span><span style="COLOR: #000000"> each fd </span><span style="COLOR: #0000ff">in</span><span style="COLOR: #000000"> the write_fd_set<br><img id=Codehighlighter1_593_680_Open_Image onclick="this.style.display='none'; Codehighlighter1_593_680_Open_Text.style.display='none'; Codehighlighter1_593_680_Closed_Image.style.display='inline'; Codehighlighter1_593_680_Closed_Text.style.display='inline';" src="http://www.shnenglu.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_593_680_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_593_680_Closed_Text.style.display='none'; Codehighlighter1_593_680_Open_Image.style.display='inline'; Codehighlighter1_593_680_Open_Text.style.display='inline';" src="http://www.shnenglu.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>            </span><span id=Codehighlighter1_593_680_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.shnenglu.com/Images/dot.gif"></span><span id=Codehighlighter1_593_680_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.shnenglu.com/Images/OutliningIndicators/InBlock.gif" align=top>                </span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000"> fd can write<br><img src="http://www.shnenglu.com/Images/OutliningIndicators/InBlock.gif" align=top>                    _handler</span><span style="COLOR: #000000">-></span><span style="COLOR: #000000">onWrite();<br><img src="http://www.shnenglu.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>            }</span></span><span style="COLOR: #000000"><br><img src="http://www.shnenglu.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>        }</span></span><span style="COLOR: #000000"><br><img src="http://www.shnenglu.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>    }</span></span><span style="COLOR: #000000"> <br><img src="http://www.shnenglu.com/Images/OutliningIndicators/InBlock.gif" align=top><br><img src="http://www.shnenglu.com/Images/OutliningIndicators/InBlock.gif" align=top>    </span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000"> setHandler( handler </span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">_h )<br><img id=Codehighlighter1_739_768_Open_Image onclick="this.style.display='none'; Codehighlighter1_739_768_Open_Text.style.display='none'; Codehighlighter1_739_768_Closed_Image.style.display='inline'; Codehighlighter1_739_768_Closed_Text.style.display='inline';" src="http://www.shnenglu.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_739_768_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_739_768_Closed_Text.style.display='none'; Codehighlighter1_739_768_Open_Image.style.display='inline'; Codehighlighter1_739_768_Open_Text.style.display='inline';" src="http://www.shnenglu.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>    </span><span id=Codehighlighter1_739_768_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.shnenglu.com/Images/dot.gif"></span><span id=Codehighlighter1_739_768_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.shnenglu.com/Images/OutliningIndicators/InBlock.gif" align=top>        _handler </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> _h;<br><img src="http://www.shnenglu.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>    }</span></span><span style="COLOR: #000000"> <br><img src="http://www.shnenglu.com/Images/OutliningIndicators/InBlock.gif" align=top><br><img src="http://www.shnenglu.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #0000ff">private</span><span style="COLOR: #000000">:<br><img src="http://www.shnenglu.com/Images/OutliningIndicators/InBlock.gif" align=top>    handler </span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">_handler;<br><img src="http://www.shnenglu.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span><span style="COLOR: #000000">; <br><img src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif" align=top><br><img id=Codehighlighter1_809_824_Open_Image onclick="this.style.display='none'; Codehighlighter1_809_824_Open_Text.style.display='none'; Codehighlighter1_809_824_Closed_Image.style.display='inline'; Codehighlighter1_809_824_Closed_Text.style.display='inline';" src="http://www.shnenglu.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_809_824_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_809_824_Closed_Text.style.display='none'; Codehighlighter1_809_824_Open_Image.style.display='inline'; Codehighlighter1_809_824_Open_Text.style.display='inline';" src="http://www.shnenglu.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_809_824_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff">/**/</span><span id=Codehighlighter1_809_824_Open_Text><span style="COLOR: #808080">///</span><span style="COLOR: #008000"> application</span><span style="COLOR: #808080"></span></span><br><img src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000"> MyHandler : </span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000"> handler<br><img id=Codehighlighter1_858_965_Open_Image onclick="this.style.display='none'; Codehighlighter1_858_965_Open_Text.style.display='none'; Codehighlighter1_858_965_Closed_Image.style.display='inline'; Codehighlighter1_858_965_Closed_Text.style.display='inline';" src="http://www.shnenglu.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_858_965_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_858_965_Closed_Text.style.display='none'; Codehighlighter1_858_965_Open_Image.style.display='inline'; Codehighlighter1_858_965_Open_Text.style.display='inline';" src="http://www.shnenglu.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_858_965_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.shnenglu.com/Images/dot.gif"></span><span id=Codehighlighter1_858_965_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.shnenglu.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">:<br><img src="http://www.shnenglu.com/Images/OutliningIndicators/InBlock.gif" align=top>    </span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000"> onRead()<br><img id=Codehighlighter1_890_896_Open_Image onclick="this.style.display='none'; Codehighlighter1_890_896_Open_Text.style.display='none'; Codehighlighter1_890_896_Closed_Image.style.display='inline'; Codehighlighter1_890_896_Closed_Text.style.display='inline';" src="http://www.shnenglu.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_890_896_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_890_896_Closed_Text.style.display='none'; Codehighlighter1_890_896_Open_Image.style.display='inline'; Codehighlighter1_890_896_Open_Text.style.display='inline';" src="http://www.shnenglu.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>    </span><span id=Codehighlighter1_890_896_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.shnenglu.com/Images/dot.gif"></span><span id=Codehighlighter1_890_896_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.shnenglu.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>    }</span></span><span style="COLOR: #000000"> <br><img src="http://www.shnenglu.com/Images/OutliningIndicators/InBlock.gif" align=top><br><img src="http://www.shnenglu.com/Images/OutliningIndicators/InBlock.gif" align=top>    </span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000"> onWrite()<br><img id=Codehighlighter1_923_929_Open_Image onclick="this.style.display='none'; Codehighlighter1_923_929_Open_Text.style.display='none'; Codehighlighter1_923_929_Closed_Image.style.display='inline'; Codehighlighter1_923_929_Closed_Text.style.display='inline';" src="http://www.shnenglu.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_923_929_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_923_929_Closed_Text.style.display='none'; Codehighlighter1_923_929_Open_Image.style.display='inline'; Codehighlighter1_923_929_Open_Text.style.display='inline';" src="http://www.shnenglu.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>    </span><span id=Codehighlighter1_923_929_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.shnenglu.com/Images/dot.gif"></span><span id=Codehighlighter1_923_929_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.shnenglu.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>    }</span></span><span style="COLOR: #000000"> <br><img src="http://www.shnenglu.com/Images/OutliningIndicators/InBlock.gif" align=top><br><img src="http://www.shnenglu.com/Images/OutliningIndicators/InBlock.gif" align=top>    </span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000"> onAccept()<br><img id=Codehighlighter1_957_963_Open_Image onclick="this.style.display='none'; Codehighlighter1_957_963_Open_Text.style.display='none'; Codehighlighter1_957_963_Closed_Image.style.display='inline'; Codehighlighter1_957_963_Closed_Text.style.display='inline';" src="http://www.shnenglu.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_957_963_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_957_963_Closed_Text.style.display='none'; Codehighlighter1_957_963_Open_Image.style.display='inline'; Codehighlighter1_957_963_Open_Text.style.display='inline';" src="http://www.shnenglu.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>    </span><span id=Codehighlighter1_957_963_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.shnenglu.com/Images/dot.gif"></span><span id=Codehighlighter1_957_963_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.shnenglu.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>    }</span></span><span style="COLOR: #000000"><br><img src="http://www.shnenglu.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span><span style="COLOR: #000000">; <br><img src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif" align=top></span></div> <p><br>在网上找?jin)䆾Proactor模式比较正式?a href="http://www.shnenglu.com/Files/kevinlynx/proactor2.rar" target=_blank>文档</a>Q其l出?jin)一个M的UMLcdQ比较全面:(x) </font> <p><a href="http://www.shnenglu.com/images/cppblog_com/kevinlynx/WindowsLiveWriter/ProactorReactor__BCB1/proactor_uml.jpg"><img style="BORDER-RIGHT: 0px; BORDER-TOP: 0px; BORDER-LEFT: 0px; BORDER-BOTTOM: 0px" height=317 alt=proactor_uml src="http://www.shnenglu.com/images/cppblog_com/kevinlynx/WindowsLiveWriter/ProactorReactor__BCB1/proactor_uml_thumb.jpg" width=692 border=0></a> <p><font size=2>Ҏ(gu)q䆾图我随便写了(jin)个例子代码:(x) </font> <p><font size=2></p> <div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000"> AsyIOProcessor<br><img id=Codehighlighter1_21_227_Open_Image onclick="this.style.display='none'; Codehighlighter1_21_227_Open_Text.style.display='none'; Codehighlighter1_21_227_Closed_Image.style.display='inline'; Codehighlighter1_21_227_Closed_Text.style.display='inline';" src="http://www.shnenglu.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_21_227_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_21_227_Closed_Text.style.display='none'; Codehighlighter1_21_227_Open_Image.style.display='inline'; Codehighlighter1_21_227_Open_Text.style.display='inline';" src="http://www.shnenglu.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_21_227_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.shnenglu.com/Images/dot.gif"></span><span id=Codehighlighter1_21_227_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.shnenglu.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">:<br><img src="http://www.shnenglu.com/Images/OutliningIndicators/InBlock.gif" align=top>    </span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000"> do_read()<br><img id=Codehighlighter1_54_189_Open_Image onclick="this.style.display='none'; Codehighlighter1_54_189_Open_Text.style.display='none'; Codehighlighter1_54_189_Closed_Image.style.display='inline'; Codehighlighter1_54_189_Closed_Text.style.display='inline';" src="http://www.shnenglu.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_54_189_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_54_189_Closed_Text.style.display='none'; Codehighlighter1_54_189_Open_Image.style.display='inline'; Codehighlighter1_54_189_Open_Text.style.display='inline';" src="http://www.shnenglu.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>    </span><span id=Codehighlighter1_54_189_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.shnenglu.com/Images/dot.gif"></span><span id=Codehighlighter1_54_189_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.shnenglu.com/Images/OutliningIndicators/InBlock.gif" align=top>        </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"><img src="http://www.shnenglu.com/Images/dot.gif">send read operation to OS<br><img src="http://www.shnenglu.com/Images/OutliningIndicators/InBlock.gif" align=top>        </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> read io finished.and dispatch notification</span><span style="COLOR: #008000"><br><img src="http://www.shnenglu.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #000000">        _proactor</span><span style="COLOR: #000000">-></span><span style="COLOR: #000000">dispatch_read();<br><img src="http://www.shnenglu.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>    }</span></span><span style="COLOR: #000000"> <br><img src="http://www.shnenglu.com/Images/OutliningIndicators/InBlock.gif" align=top><br><img src="http://www.shnenglu.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #0000ff">private</span><span style="COLOR: #000000">:<br><img src="http://www.shnenglu.com/Images/OutliningIndicators/InBlock.gif" align=top>    Proactor </span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">_proactor;<br><img src="http://www.shnenglu.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span><span style="COLOR: #000000">; <br><img src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000"> Proactor<br><img id=Codehighlighter1_247_369_Open_Image onclick="this.style.display='none'; Codehighlighter1_247_369_Open_Text.style.display='none'; Codehighlighter1_247_369_Closed_Image.style.display='inline'; Codehighlighter1_247_369_Closed_Text.style.display='inline';" src="http://www.shnenglu.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_247_369_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_247_369_Closed_Text.style.display='none'; Codehighlighter1_247_369_Open_Image.style.display='inline'; Codehighlighter1_247_369_Open_Text.style.display='inline';" src="http://www.shnenglu.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_247_369_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.shnenglu.com/Images/dot.gif"></span><span id=Codehighlighter1_247_369_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.shnenglu.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">:<br><img src="http://www.shnenglu.com/Images/OutliningIndicators/InBlock.gif" align=top>    </span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000"> dispatch_read()<br><img id=Codehighlighter1_286_323_Open_Image onclick="this.style.display='none'; Codehighlighter1_286_323_Open_Text.style.display='none'; Codehighlighter1_286_323_Closed_Image.style.display='inline'; Codehighlighter1_286_323_Closed_Text.style.display='inline';" src="http://www.shnenglu.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_286_323_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_286_323_Closed_Text.style.display='none'; Codehighlighter1_286_323_Open_Image.style.display='inline'; Codehighlighter1_286_323_Open_Text.style.display='inline';" src="http://www.shnenglu.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>    </span><span id=Codehighlighter1_286_323_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.shnenglu.com/Images/dot.gif"></span><span id=Codehighlighter1_286_323_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.shnenglu.com/Images/OutliningIndicators/InBlock.gif" align=top>        _handlerMgr</span><span style="COLOR: #000000">-></span><span style="COLOR: #000000">onRead();<br><img src="http://www.shnenglu.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>    }</span></span><span style="COLOR: #000000"> <br><img src="http://www.shnenglu.com/Images/OutliningIndicators/InBlock.gif" align=top><br><img src="http://www.shnenglu.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #0000ff">private</span><span style="COLOR: #000000">:<br><img src="http://www.shnenglu.com/Images/OutliningIndicators/InBlock.gif" align=top>    HandlerManager </span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">_handlerMgr;<br><img src="http://www.shnenglu.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span><span style="COLOR: #000000">; <br><img src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000"> HandlerManager<br><img id=Codehighlighter1_395_634_Open_Image onclick="this.style.display='none'; Codehighlighter1_395_634_Open_Text.style.display='none'; Codehighlighter1_395_634_Closed_Image.style.display='inline'; Codehighlighter1_395_634_Closed_Text.style.display='inline';" src="http://www.shnenglu.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_395_634_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_395_634_Closed_Text.style.display='none'; Codehighlighter1_395_634_Open_Image.style.display='inline'; Codehighlighter1_395_634_Open_Text.style.display='inline';" src="http://www.shnenglu.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_395_634_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.shnenglu.com/Images/dot.gif"></span><span id=Codehighlighter1_395_634_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.shnenglu.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">:<br><img src="http://www.shnenglu.com/Images/OutliningIndicators/InBlock.gif" align=top>    typedef std::list</span><span style="COLOR: #000000"><</span><span style="COLOR: #000000">Handler</span><span style="COLOR: #000000">*></span><span style="COLOR: #000000"> HandlerList; <br><img src="http://www.shnenglu.com/Images/OutliningIndicators/InBlock.gif" align=top><br><img src="http://www.shnenglu.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">:<br><img src="http://www.shnenglu.com/Images/OutliningIndicators/InBlock.gif" align=top>    </span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000"> onRead()<br><img id=Codehighlighter1_482_593_Open_Image onclick="this.style.display='none'; Codehighlighter1_482_593_Open_Text.style.display='none'; Codehighlighter1_482_593_Closed_Image.style.display='inline'; Codehighlighter1_482_593_Closed_Text.style.display='inline';" src="http://www.shnenglu.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_482_593_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_482_593_Closed_Text.style.display='none'; Codehighlighter1_482_593_Open_Image.style.display='inline'; Codehighlighter1_482_593_Open_Text.style.display='inline';" src="http://www.shnenglu.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>    </span><span id=Codehighlighter1_482_593_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.shnenglu.com/Images/dot.gif"></span><span id=Codehighlighter1_482_593_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.shnenglu.com/Images/OutliningIndicators/InBlock.gif" align=top>        </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> notify all the handlers.</span><span style="COLOR: #008000"><br><img src="http://www.shnenglu.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #000000">        std::for_each( _handlers.begin(), _handlers.end(), onRead );<br><img src="http://www.shnenglu.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>    }</span></span><span style="COLOR: #000000"> <br><img src="http://www.shnenglu.com/Images/OutliningIndicators/InBlock.gif" align=top><br><img src="http://www.shnenglu.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #0000ff">private</span><span style="COLOR: #000000">:<br><img src="http://www.shnenglu.com/Images/OutliningIndicators/InBlock.gif" align=top>    HandlerList </span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">_handlers;<br><img src="http://www.shnenglu.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span><span style="COLOR: #000000">; <br><img src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000"> Handler<br><img id=Codehighlighter1_653_694_Open_Image onclick="this.style.display='none'; Codehighlighter1_653_694_Open_Text.style.display='none'; Codehighlighter1_653_694_Closed_Image.style.display='inline'; Codehighlighter1_653_694_Closed_Text.style.display='inline';" src="http://www.shnenglu.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_653_694_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_653_694_Closed_Text.style.display='none'; Codehighlighter1_653_694_Open_Image.style.display='inline'; Codehighlighter1_653_694_Open_Text.style.display='inline';" src="http://www.shnenglu.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_653_694_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.shnenglu.com/Images/dot.gif"></span><span id=Codehighlighter1_653_694_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.shnenglu.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">:<br><img src="http://www.shnenglu.com/Images/OutliningIndicators/InBlock.gif" align=top>    </span><span style="COLOR: #0000ff">virtual</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000"> onRead() </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;<br><img src="http://www.shnenglu.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span><span style="COLOR: #000000">; <br><img src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> application level handler.</span><span style="COLOR: #008000"><br><img src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000"> MyHandler : </span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000"> Handler<br><img id=Codehighlighter1_762_815_Open_Image onclick="this.style.display='none'; Codehighlighter1_762_815_Open_Text.style.display='none'; Codehighlighter1_762_815_Closed_Image.style.display='inline'; Codehighlighter1_762_815_Closed_Text.style.display='inline';" src="http://www.shnenglu.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_762_815_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_762_815_Closed_Text.style.display='none'; Codehighlighter1_762_815_Open_Image.style.display='inline'; Codehighlighter1_762_815_Open_Text.style.display='inline';" src="http://www.shnenglu.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_762_815_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.shnenglu.com/Images/dot.gif"></span><span id=Codehighlighter1_762_815_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.shnenglu.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">:<br><img src="http://www.shnenglu.com/Images/OutliningIndicators/InBlock.gif" align=top>    </span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000"> onRead() <br><img id=Codehighlighter1_795_813_Open_Image onclick="this.style.display='none'; Codehighlighter1_795_813_Open_Text.style.display='none'; Codehighlighter1_795_813_Closed_Image.style.display='inline'; Codehighlighter1_795_813_Closed_Text.style.display='inline';" src="http://www.shnenglu.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_795_813_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_795_813_Closed_Text.style.display='none'; Codehighlighter1_795_813_Open_Image.style.display='inline'; Codehighlighter1_795_813_Open_Text.style.display='inline';" src="http://www.shnenglu.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>    </span><span id=Codehighlighter1_795_813_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.shnenglu.com/Images/dot.gif"></span><span id=Codehighlighter1_795_813_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.shnenglu.com/Images/OutliningIndicators/InBlock.gif" align=top>        </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> </span><span style="COLOR: #008000"><br><img src="http://www.shnenglu.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top></span><span style="COLOR: #000000">    }</span></span><span style="COLOR: #000000"><br><img src="http://www.shnenglu.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span><span style="COLOR: #000000">; <br><img src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif" align=top></span></div> <p><br>Reactor通过某种变ŞQ可以将其改装ؓ(f)ProactorQ在某些不支持异步IO的系l上Q也可以隐藏底层的实玎ͼ利于~写跨^?br>代码。我们只需要在dispatch(也就是demultiplexor)中封装同步IO操作的代码,在上层,用户提交自己的缓冲区到这一层,<br>q一层检查到讑֤可操作时Q不像原来立卛_调handlerQ而是开始IO操作Q然后将操作l果攑ֈ用户~冲??Q然后再<br>回调handler。这P对于上层handler而言Q就像是proactor一栗详l技法参?a target=_blank>q篇文章</a>?</font> <p><font size=2>其实p计模式而言Q我个h觉得某个模式其实是没有完全固定的l构的。不能说某个模式里就肯定?x)有某个c,cM间的<br>关系p定是q样。在实际写程序过E中也很去特别地实现某个模式,只能说模式会(x)l你更多更好的架构方案?</font> <p><font size=2>最q在看spserver的代码,看到别h提各Uƈ发系l中的模式,有点眼红Q于是才来扫扫盲。知道什么是<a href="http://www.shnenglu.com/kevinlynx/archive/2008/06/04/52127.html" target=_blank>leader follower模式</a>Q?br>reactor, proactorQmultiplexingQ对于心(j)中的那个|络库也来清晰?</font> <p><font size=2>最q还q了(jin)些离q事,写了(jin)传说中的字节编码,用模板的方式实现Q不但保持了(jin)扩展性,q少写很多代码;处于效率考虑Q?br>写了(jin)个static array容器(其实是template <typename _Tp, std::size_t size> class static_array { _Tp _con[size])Q?br>加了(jin)iteratorQ遵循STL标准Q可以结合进STL的各个generic algorithm用,自我感觉不错。基模块搭徏完毕Q解析了(jin)公司<br>服务器网l模块的消息Q我是不是真的打用自己的网l模块重写我的验证服务器Q在另一个给公司写的工具里,因ؓ(f)实在厌恶<br>来多的重复代码,索性写?jin)几个宏Q还真的做到?jin)代码的自动生?D?</font> <p><font size=2>对优雅代码的q求真的成了(jin)U癖?  = =| </font></p> <img src ="http://www.shnenglu.com/kevinlynx/aggbug/52356.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/kevinlynx/" target="_blank">Kevin Lynx</a> 2008-06-06 13:25 <a href="http://www.shnenglu.com/kevinlynx/archive/2008/06/06/52356.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>半同步半异步模式以及(qing)Leader_Follwer模式http://www.shnenglu.com/kevinlynx/archive/2008/06/04/52127.htmlKevin LynxKevin LynxWed, 04 Jun 2008 02:40:00 GMThttp://www.shnenglu.com/kevinlynx/archive/2008/06/04/52127.htmlhttp://www.shnenglu.com/kevinlynx/comments/52127.htmlhttp://www.shnenglu.com/kevinlynx/archive/2008/06/04/52127.html#Feedback4http://www.shnenglu.com/kevinlynx/comments/commentRss/52127.htmlhttp://www.shnenglu.com/kevinlynx/services/trackbacks/52127.htmlq里提到的两个设计模式都是用于高q发pȝ(例如一个高性能的网l服务器)的。这里我只是单地提一下:(x)

1.半同?半异步(half-sync/half-asyncQ:(x)

在网上一份资?/a>中引用了(jin)一本貌似很l典的书里的比喻Q?br>?
许多厅使用 半同?半异?模式的变?sh)。例如,厅常常雇䄦一个领班负责迎接顾客,q在厅J忙时留意给֮安排桌位Q?br>为等待就的֮按序排队是必要的。领班由所有顾客“共享”,不能被Q何特定顾客占用太多时间。当֮在一张桌子入坐后Q?br>有一个侍应生专门张桌子服务?
?

按照另一份似乎比较权威的文档的描qͼ要实现半同步/半异步模式,需要实C层:(x)异步层、同步层、队列层。因为很多操?br>采用异步方式?x)比较有效?例如高效率的|络模型g都采用异步IO)Q但是异步操作的复杂度比较高Q不利于~程。而同?br>操作相对之下~程要简单点。ؓ(f)?jin)结合两者的优点Q就提出?jin)这个模式。而ؓ(f)?jin)让异步层和同步层互盔R信(模块间的通信)Q系
l需要加入一个通信队列。异步层操作结果放入队列,同步层从队列里获取操作结果?

回过头来看看我之前写的那个select|络模型代码Q个为基本上是一个半同步半异步模式的单例子:(x)Buffer相当于通信
队列Q网l底层将数据写入BufferQ上层再同步C该队列里获取出数据。这L(fng)来似乎也没什么难度?= =

关于例子代码Q直接引用iunknownl的Q?

//q就是一个典型的循环队列的定义,iget 是队列头Qiput 是队列尾</STRONG>  
int clifd[MAXNCLI], iget, iput;   
int main( int argc, char * argv[] )  
{  
  ......  
  int listenfd = Tcp_listen( NULL, argv[ 1 ], &addrlen );  
  ......  
  iget = iput = 0;  
  for( int i = 0; i < nthreads; i++ ) {  
    pthread_create( &tptr[i].thread_tid, NULL, &thread_main, (void*)i );  
  for( ; ; ) {  
    connfd = accept( listenfd, cliaddr,, &clilen );  
    clifd[ iput ] = connfd;     // 接受到的q接句柄攑օ队列</STRONG>  
    if( ++iput == MAXNCLI ) iput = 0;    
  }  
}  
void * thread_main( void * arg )  
{  
  for( ; ; ) {  
    while( iget == iput ) pthread_cond_wait( ...... );  
    connfd = clifd[ iget ];     // 从队列中获得q接句柄</STRONG>  
    if( ++iget == MAXNCLI ) iget = 0;  
    ......  
    web_child( connfd );  
    close( connfd );  
  }  

2.领导?q随者(Leader/FollowersQ:(x)

同样Q给出别人引用的比喻Q?br>?br>在日常生zMQ领D?q随者模式用于管理许多飞机场出租车候R台。在该用例中Q出UR扮演“线E”角Ԍ排在W一辆的?br>UR成ؓ(f)领导者,剩下的出UR成ؓ(f)q随者。同P到达出租车候R台的乘客构成?jin)必被多\分解l出UR的事Ӟ一般以先进
先出排序。一般来_(d)如果M出租车可以ؓ(f)M֮服务Q该场景׃要相当于非绑定句?U程兌。然而,如果仅仅是某?br>出租车可以ؓ(f)某些乘客服务Q该场景q当于l定句柄/U程兌?
?

其实q个更简单,我记?lt;unix|络~程>中似乎提到过q个。M有一U网l模?connection-per-thread?)里,一个线E用?br>acceptq接。当接收C个新的连接时Q这个线E就转ؓ(f)connection threadQ而这个线E后面的U程则上升ؓ(f)acceptU程。这里,
acceptU程q当于领导者线E,而其他线E则属于q随者线E?

iunknown 的例子代码:(x)

int listenfd;  
int main( int argc, char * argv[] )  
{  
  ......  
  listenfd = Tcp_listen( NULL, argv[ 1 ], &addrlen );  
  ......  
  for( int i = 0; i < nthreads; i++ ){  
    pthread_create( &tptr[i].thread_tid, NULL, &thread_main, (void*)i );  
  }  
  ......  
}  
void * thread_main( void * arg )  
{  
  for( ; ; ){  
    ......  
    // 多个U程同时d在这?accept 调用上,依靠操作pȝ的队?lt;/STRONG>  
    connfd = accept( listenfd, cliaddr, &clilen );  
    ......  
    web_child( connfd );  
    close( connfd );  
    ......  
  }  



Kevin Lynx 2008-06-04 10:40 发表评论
]]>
Ʒþþþþ| Ʒþþþþ| ݺɫþۺ| ˾þþƷһ| ھƷþþþӰԺվ | þüۺɫۺϰҲȥ| þ޹ҹƷƬ| ŷСþþþþþ| 99ŷƷþþѿ| ޹˾þۺ| ݺݸɺݺݾþ| þĻƵ| þþþAVվ| ޹㽶þþþþ| ƷþþþþĻһ | 鶹ƷþþƷɫۺ| 99ƷۺϾþþþ| þeֻйľƷ99| ձvaĻþ| ŷպ˾Ʒþþѿ| ƷþþþþþþѼ| þùֱ| һɫƵþվ| þٸ۲AV| 99þùۺϾƷ| avttþþƷ| ھƷþþӰԺ| þþþùƷ| ɫ͵͵888ŷƷþþ| þw5www| ձþþþĻ| þþƷɫ鶹| þɫۺ| þþù99þùһ| ޹СƵƷþþ | ˾þۺ| һþ㽶߿ۿ | þþþþþ91Ʒѹۿ| þˬˬƬAV鶹 | þþþ޾Ʒַ | ͵ٸþþþþþþ|