调用的时候 编译器 COBJEVENT cEvent;
cEvent.pFunc(pObj,...) ; //参数列表
我初涉这个领域,不太理解你们所说的事件模型到底指得什么?就是说一件事件完成后在某个地方得到通知么?如果是这个意思的话,在windows的环境下有个事件内核对象。
//interface the all observer classes should implement
public interface IObserver
{
void Notify(object anObject);
}//IObserver
//interface that all observable classes should implement
public interface IObservable
{
void Register(IObserver anObserver);
void UnRegister(IObserver anObserver);
}//IObservable
下面就需要B 对象在 Notify 中,通过大量的Switch case
或者if else
来实现不同事件的不同处理。很显然当事件很多的时候,这个简直就是噩梦了。
.NET
里面没有使用上述的接口,而是使用了代理(Delegate)。这就更加简化了事件的处理。但是在
C++
中好像还没有什么好的办法。现在VC7中新增的统一事件模型,它新增了__hook,
__raise
等等几个不符合标准的关键字,的确能很直观的解决问题,但是不知道其效率、开销如何,不太敢使用,不知道哪位朋友有这方面的经验,或者有其他的解决办法。
class A;
{
public:
COBJEVENT m_Event;
.....
}
使用的时候
A * pObject=new A;
//开始HOOK这个事件
pObject->m_Event=this->Func;
// unhook
pObject->m_Evnet=NULL;
//在A的代码里
A::Dothing()
if m_Event.pFunc!=NULL
//编译器做相关的代码
m_Event(this,.....);
这样使用最简单,
和目前的C#方式一样,不过C#是抄袭DELPHI的方式比注册方式还要简单,而且语法要
好看的多.
用摸版的实现办法可以看游戏编程jincui
中这里面 this->Func
怕是需要静态函数吧,直接调用成员函数估计会有一点难度。
下面就是例子
typedef void ( CEVENTPTR::* CObjectFuncPtr )(int nCount)
这样就可以了,我后面的一些代码是编译器实现的
if m_Event.pFunc!=NULL
//编译器做相关的代码
m_Event(this,.....);
里面包含了 this
指针。和普通的函数指针还是有一些差别。
在C++程序中,很多函数是成员函数,即这些函数是某个类中的一部分。你不可以像一个普通的函数指针那样指向一个成员函数,正确的做法应该是,你必须使用一个成员函数指针。一个成员函数的指针指向类中的一个成员函数,并和以前有相同的参数,声明如下:
float (SomeClass::*my_memfunc_ptr)(int, char *);
//对于使用const关键字修饰的成员函数,声明如下:
float (SomeClass::*my_const_memfunc_ptr)(int, char *) const;
注意使用了特殊的运算符(::*),而“SomeClass”是声明中的一部分。成员函数指针有一个可怕的限制:它们只能指向一个特定的类中的成员函数。对每一种参数的组合,需要有不同的成员函数指针类型,而且对每种使用const修饰的函数和不同类中的函数,也要有不同的函数指针类型。在MSVC中,对下面这四种调用方式都有一种不同的调用类型:__cdecl,
__stdcall, __fastcall, 和
__thiscall。(__thiscall是缺省的方式,有趣的是,在任何官方文档中从没有对__thiscall关键字的详细描述,但是它经常在错误信息中出现。如果你显式地使用它,你会看到“它被保留作为以后使用(it
is reserved for future
use)”的错误提示。)如果你使用了成员函数指针,你最好使用typedef以防止混淆。
将函数指针指向型如float SomeClass::some_member_func(int, char
*)的函数,你可以这样写:
my_memfunc_ptr = &SomeClass::some_member_func;
很多编译器(比如MSVC)会让你去掉“&”,而其他一些编译器(比如GNU
G++)则需要添加“&”,所以在手写程序的时候我建议把它添上。若要调用成员函数指针,你需要先建立SomeClass的一个实例,并使用特殊操作符“->*”,这个操作符的优先级较低,你需要将其适当地放入圆括号内。
SomeClass *x = new SomeClass;
(x->*my_memfunc_ptr)(6, "Another Arbitrary Parameter");
//如果类在栈上,你也可以使用“.*”运算符。
SomeClass y;
(y.*my_memfunc_ptr)(15, "Different parameters this time");
不要怪我使用如此奇怪的语法——看起来C++的设计者对标点符号有着由衷的感情!C++相对于C增加了三种特殊运算符来支持成员指针。“::*”用于指针的声明,而“->*”和“.*”用来调用指针指向的函数。这样看起来对一个语言模糊而又很少使用的部分的过分关注是多余的。(你当然可以重载“->*”这些运算符,但这不是本文所要涉及的范围。)
一个成员函数指针可以被设置成0,并可以使用“==”和“!=”比较运算符,但只能限定在同一个类中的成员函数的指针之间进行这样的比较。任何成员函数指针都可以和0做比较以判断它是否为空。与函数指针不同,不等运算符(<,
>, <=, >=)对成员函数指针是不可用的。
成员函数指针的怪异之处
成员函数指针有时表现得很奇怪。首先,你不可以用一个成员函数指针指向一个静态成员函数,你必须使用普通的函数指针才行(在这里“成员函数指针”会产生误解,它实际上应该是“非静态成员函数指针”才对)。其次,当使用类的继承时,会出现一些比较奇怪的情况。比如,下面的代码在MSVC下会编译成功(注意代码注释):
#include “stdio.h”
class SomeClass {
public:
virtual void some_member_func(int x, char *p) {
printf("In SomeClass"); };
};
class DerivedClass : public SomeClass {
public:
// 如果你把下一行的注释销掉,带有 line
(*)的那一行会出现错误
// virtual void some_member_func(int x, char *p) { printf("In
DerivedClass"); };
};
int main() {
//声明SomeClass的成员函数指针
typedef void (SomeClass::*SomeClassMFP)(int, char *);
SomeClassMFP my_memfunc_ptr;
my_memfunc_ptr = &DerivedClass::some_member_func; // ---- line (*)
return 0;
}
奇怪的是,&DerivedClass::some_member_func是一个SomeClass类的成员函数指针,而不是DerivedClass类的成员函数指针!(一些编译器稍微有些不同:比如,对于Digital
Mars
C++,在上面的例子中,&DerivedClass::some_member_func会被认为没有定义。)但是,如果在DerivedClass类中重写(override)了some_member_func函数,代码就无法通过编译,因为现在的&DerivedClass::some_member_func已成为DerivedClass类中的成员函数指针!
成员函数指针之间的类型转换是一个讨论起来非常模糊的话题。在C++的标准化的过程中,在涉及继承的类的成员函数指针时,对于将成员函数指针转化为基类的成员函数指针还是转化为子类成员函数指针的问题和是否可以将一个类的成员函数指针转化为另一个不相关的类的成员函数指针的问题,人们曾有过很激烈的争论。然而不幸的是,在标准委员会做出决定之前,不同的编译器生产商已经根据自己对这些问题的不同的回答实现了自己的编译器。根据标准(第5.2.10/9节),你可以使用reinterpret_cast在一个成员函数指针中保存一个与本来的类不相关的类的成员函数。有关成员函数指针转换的问题的最终结果也没有确定下来。你现在所能做的还是像以前那样——将成员函数指针转化为本类的成员函数的指针。在文章的后面我会继续讨论这个问题,因为这正是各个编译器对这样一个标准没有达成共识的一个话题。
在一些编译器中,在基类和子类的成员函数指针之间的转换时常有怪事发生。当涉及到多重继承时,使用reinterpret_cast将子类转换成基类时,对某一特定编译器来说有可能通过编译,而也有可能通不过编译,这取决于在子类的基类列表中的基类的顺序!下面就是一个例子:
class Derived: public Base1, public Base2 // 情况 (a)
class Derived2: public Base2, public Base1 // 情况 (b)
typedef void (Derived::* Derived_mfp)();
typedef void (Derived2::* Derived2_mfp)();
typedef void (Base1::* Base1mfp) ();
typedef void (Base2::* Base2mfp) ();
Derived_mfp x;
对于情况(a),static_cast<Base1mfp>(x)是合法的,而static_cast<Base2mfp>(x)则是错误的。然而情况(b)却与之相反。你只可以安全地将子类的成员函数指针转化为第一个基类的成员函数指针!如果你要实验一下,MSVC会发出C4407号警告,而Digital
Mars
C++会出现编译错误。如果用reinterpret_cast代替static_cast,这两个编译器都会发生错误,但是两种编译器对此有着不同的原因。但是一些编译器对此细节置之不理,大家可要小心了!
标准C++中另一条有趣的规则是:你可以在类定义之前声明它的成员函数指针。这对一些编译器会有一些无法预料的副作用。我待会讨论这个问题,现在你只要知道要尽可能得避免这种情况就是了。
需要值得注意的是,就像成员函数指针,标准C++中同样提供了成员数据指针(member
data
pointer)。它们具有相同的操作符,而且有一些实现原则也是相同的。它们用在stl::stable_sort的一些实现方案中,而对此很多其他的应用我就不再提及了。
成员函数指针的使用
现在你可能会觉得成员函数指针是有些奇异。但它可以用来做什么呢?对此我在网上做了非常广泛的调查。最后我总结出使用成员函数指针的两点原因:
* 用来做例子给
C++初学者看,帮助它们学习语法;或者
* 为了实现“委托(
delegate)”!
成员函数指针在STL和Boost库的单行函数适配器(one-line
function
adaptor)中的使用是微不足道的,而且允许你将成员函数和标准算法混合使用。但是它们最重要的应用是在不同类型的应用程序框架中,比如它们形成了MFC消息系统的核心。
当你使用MFC的消息映射宏(比如ON_COMMAND)时,你会组装一个包含消息ID和成员函数指针(型如:CCmdTarget::*成员函数指针)的序列。这是MFC类必须继承CCmdTarget才可以处理消息的原因之一。但是,各种不同的消息处理函数具有不同的参数列表(比如OnDraw处理函数的第一个参数的类型为CDC
*),所以序列中必须包含各种不同类型的成员函数指针。MFC是怎样做到这一点的呢?MFC利用了一个可怕的编译器漏洞(hack),它将所有可能出现的成员函数指针放到一个庞大的联合(union)中,从而避免了通常需要进行的C++类型匹配检查。(看一下afximpl.h和cmdtarg.cpp中名为MessageMapFunctions的union,你就会发现这一恐怖的事实。)因为MFC有如此重要的一部分代码,所以事实是,所有的编译器都为这个漏洞开了绿灯。(但是,在后面我们会看到,如果一些类用到了多重继承,这个漏洞在MSVC中就不会起作用,这正是在使用MFC时只能必须使用单一继承的原因。)
在boost::function中有类似的漏洞(但不是太严重)。看起来如果你想做任何有关成员函数指针的比较有趣的事,你就必须做好与这个语言的漏洞进行挑战的准备。要是你想否定C++的成员函数指针设计有缺陷的观点,看来是很难的。
在写这篇文章中,我有一点需要指明:“允许成员函数指针之间进行转换(cast),而不允许在转换完成后调用其中的函数”,把这个规则纳入C++的标准中是可笑的。首先,很多流行的编译器对这种转换不支持(所以,转换是标准要求的,但不是可移植的)。其次,所有的编译器,如果转换成功,调用转换后的成员函数指针时仍然可以实现你预期的功能:那编译器就没有所谓的“undefined
behavior(未定义的行为)”这类错误出现的必要了(调用(Invocation)是可行的,但这不是标准!)。第三,允许转换而不允许调用是完全没有用处的,只有转换和调用都可行,才能方便而有效地实现委托,从而使这种语言受益。
为了让你确信这一具有争议的论断,考虑一下在一个文件中只有下面的一段代码,这段代码是合法的:
class SomeClass;
typedef void (SomeClass::* SomeClassFunction)(void);
void Invoke(SomeClass *pClass, SomeClassFunction funcptr) {
(pClass->*funcptr)(); };
注意到编译器必须生成汇编代码来调用成员函数指针,其实编译器对SomeClass类一无所知。显然,除非链接器进行了一些极端精细的优化措施,否则代码会忽视类的实际定义而能够正确地运行。而这造成的直接后果是,你可以“安全地”调用从完全不同的其他类中转换过来的成员函数指针。
为解释我的断言的另一半——转换并不能按照标准所说的方式进行,我需要在细节上讨论编译器是怎样实现成员函数指针的。我同时会解释为什么使用成员函数指针的规则具有如此严格的限制。获得详细论述成员函数指针的文档不是太容易,并且大家对错误的言论已经习以为常了,所以,我仔细检查了一系列编译器生成的汇编代码…
sunway 写道:
> 用对象函数指针自己实现一个也是很容易的。
>
>
>
2006/2/21, sunway <sunh...@gmail.com>:
> 随意一点好,而且大家一般白天都在工作,偶尔看一下Group,看到有新的想法回一下,
> 要什么都想全了,还要讨论干吗?
>
>
>
--
Donald
我个人觉得ACE已经做的很不错了
麻烦我倒没觉得,可能是早在使用ACE之前就已经研究过很多网络框架的原因吧
基本上跟POSA2里面描述的没啥出入
不知道自己做底层框架做出来都是什么架构呢?
我很好奇
BUG不少?比如说呢?
老实说,ACE我现在也只是看,还没机会具体使用,有经验的不妨说一说啊
2006/2/21, sunway <sunh...@gmail.com>:
--
Donald
--
Donald
在 06-2-26,sunbi...@gmail.com<sunbi...@gmail.com> 写道:
--
Donald
My Blog:http://flyingbug.blogjava.net
--
Best regards
大宝(sodme)
msn : sod...@hotmail.com
Email : sodm...@gmail.com
ACE中各个操作系统的差异屏蔽的还是很好的。在框架和包装上有一些参差不齐的感觉,Smit博士和一些学生写的非常不错,还有一些就一般般了,但是这个框架是很健壮的,只是有些瑕疵而已。再就是由于涉及的面太广,C++语言自身的复杂性来说,门槛比较高,能用好不容易,做大系统就应该使用它的思想,如果有精力的话可以不用他的实现,那样你要做非常多的工作。
如果小系统,它的框架可能会把问题搞复杂也发挥不了它的优势,但是如果只用到对象包装那一层,而不是框架层,它也会为你省下非常多的工作,特别是用C++开发的话。如果要做的不是核心系统,而是业务层那就要TAO实现的Corba,或者ICE,J2EE,.net那些了。
也说点感想,如果ACE能象ICE那样那样支持多语言、代码清晰的话就好了,如果在屏蔽操作系统差异的时候多用点C++中基于policy-based策略划分来屏蔽操作系统差异和功能组合的话,而不是过多的应用OO的多态,那就更好了,不过这也有代码的历史原因和模版的一些缺点导致的。
说起ACE的Bug我也发现过一个,Proactor还有ACE_DLL等几个,也不是什么大不了的,就象以前ACE和MFC还有Winmian程序的内存泄露问题一样。内存在是因为ACE有自己的内存管理机制,在非mian入口的程序需要手动初试化,ACE框架中只帮mian做了替换而已。Proactor和ACE_DLL基本上也都是在他们的开发版本中出现的,二处内存泄露,也不影响使用。我提交Bug后Smit博士亲自负责维护,而且Bug很快在后来的稳定版本中解决了。
为ACE辟谣,虽然她的实现不是那样的理想,但是里面的模型思想,真是一个宝藏!
(喜欢高能和分布式网络编程的朋友们,和你们交个朋友,多多指教、切磋、共同进步,我的blog:http://wolf.bloghome.cn)
On Mon, 27 Feb 2006 16:22:47 -0000
"alvi...@gmail.com" <alvi...@gmail.com> 撰写于:
>
> 露个脸,也来说二句。我用ACE一年左右,学了非常多东西,用起来是越来越顺手,ACE的架构模型是非常先进的,就模型上来说起码先进其他语言平台5到10年,看看Java的nio,J2SE5.0的Concurrency吧。
>
能稍微描述一下这先进的5到10年体现在什么地方吗?
--
Roger Chen <che...@gmail.com>
Donald 写道:
再按模型来说,Reactor的事件通知、Proactor的异步模型,Java,.net的网络模型还没有达到这个高度,这里只指的是网络通讯的模型,不是应用服务器这样的业务应用层次,也算是系统层。
象java的Concurrency包,就是个很好的例子,几乎的就是照着ACE的Task框架来的,看看C++网络编程二卷和ACE编程指南APG,中的相关例子吧。
ACE是个实现,可能感觉上没有很多商业的产品那么易用和全面,但是这就好比学术和工业,她所支撑和实现的是一个理论模型,而不是商业化的产品。商业化的产品会变,也许过个二年它又会新瓶旧酒又来一遍。就好比各种类Unix和Unix的思想一样,能说Linux就比那些老的Unix系统先进吗?实际上很多Linux的新特性,那些商用、非商用的Unix很早也有,只不过他很好的借助了GNU的力量。Unix的模型和思想能否定吗?我想POSA的模型也经过锤炼了的,是从工程实践中提取的学术模型,我们可能总会忽略理论模型,但实用技术研究到了深的层次又会回归到理论,因为那才是精髓。
而那些商业产品和平台不都还在挣扎么,为的是什么,是更快的响应市场、靠语法糖笼络开发人员,巩固他们的平台,占有市场,以获得各种利润。如果他们给你的是多么先进强大如何美妙的开发平台产品,往往你很难清晰的理解他们的平台框架和思想,因为你就是他们的实验品。他们的大师给你定义游戏规则,系统级开发也就没有我们的地盘了,我们永远是沉睡的neo。
(说先进,确切的说是ACE的模型,POSA所描述的那些,那些流行的商业平台在网络通讯模型上是没有说在哪以项上推翻或者超越的,顶多是新的一些模型。)
Roger Chen 写道:
> 就拿Proactor,Reactor,Task,Stream框架来说。Java里的Nio也都停留在select,poll的模型上,而且是前几年才加入的。连接、关闭等事件响应是异步的,但是读写仍然是同步的,算是半异步的模型。象Proactor包装的IOCP和Posix
> AIO,所有的事件都可以是异步的,包括数据的读写,也都交给系统内核去完成后通知了,这对服务器的磁盘操作来说是非常有利的。也包括网络IO,网络IO在高负载的时候可以选用,降低并发线程占用的资源。
>
NIO所采用的是Reactor的模型。所有的事件都是异步的,包括连接、关闭、读、写
。但不同的地方在于,NIO异步读、写时会即时得到响应结果,而不是等事件完成
后才通过通知机制得到。
我对C++的网络开发不熟悉,不过我看到过sodme的这篇文章:
http://blog.csdn.net/sodme/archive/2006/02/15/599132.aspx,觉得NIO的这种
机制应该和epoll是一样的。
实际上这种机制给了应用更大的弹性。基于nio,可以设计出各种应用模型。当然
,也带来了缺点,就是可能没有直接在内核完成操作然后通知应用来得高效。
> 再按模型来说,Reactor的事件通知、Proactor的异步模型,Java,.net的网络模型还没有达到这个高度,这里只指的是网络通讯的模型,不是应用服务器这样的业务应用层次,也算是系统层。
>
> 象java的Concurrency包,就是个很好的例子,几乎的就是照着ACE的Task框架来的,看看C++网络编程二卷和ACE编程指南APG,中的相关例子吧。
这个就不好评价了,我根本不了解ACE的Task框架。但是我并不认为concurrent包
是照着Task框架来的,JSR 166专家组绝对不是吃素的。
但我认为它们之间肯定会有类似的地方,就好像可以说Java里面a+b就是照着C里面
的a+b来的。
>
> ACE是个实现,可能感觉上没有很多商业的产品那么易用和全面,但是这就好比学术和工业,她所支撑和实现的是一个理论模型,而不是商业化的产品。商业化的产品会变,也许过个二年它又会新瓶旧酒又来一遍。就好比各种类Unix和Unix的思想一样,能说Linux就比那些老的Unix系统先进吗?实际上很多Linux的新特性,那些商用、非商用的Unix很早也有,只不过他很好的借助了GNU的力量。Unix的模型和思想能否定吗?我想POSA的模型也经过锤炼了的,是从工程实践中提取的学术模型,我们可能总会忽略理论模型,但实用技术研究到了深的层次又会回归到理论,因为那才是精髓。
>
> 而那些商业产品和平台不都还在挣扎么,为的是什么,是更快的响应市场、靠语法糖笼络开发人员,巩固他们的平台,占有市场,以获得各种利润。如果他们给你的是多么先进强大如何美妙的开发平台产品,往往你很难清晰的理解他们的平台框架和思想,因为你就是他们的实验品。他们的大师给你定义游戏规则,系统级开发也就没有我们的地盘了,我们永远是沉睡的neo。
>
> (说先进,确切的说是ACE的模型,POSA所描述的那些,那些流行的商业平台在网络通讯模型上是没有说在哪以项上推翻或者超越的,顶多是新的一些模型。)
>
这个就太远了,没有人否定POSA2里面的模型,事实上大部分做网络应用的人也就
是在POSA2里面转圈圈。
但说到模型,实际上是更为宏观的一个层面,所以我并不认可你说的ACE的模型领
先其他语言平台5到10年。
假设在window系统没有提供iocp以前,能不能用select做出一个proactor模型来?
当然可以,只不过效率方面比不上而已。java里面的nio也是如此,它提供的只是
一个比较底层一点的api,基于这些api,使用者可以搭建出各种各样的模型,只不
过效率上会有一些问题,这是硬伤。
JSR 203也早提出在java中加入新的异步I/O,这就相当于可以利用各个操作系统级
的实现,不过一直没有人推动这件事情。
我认可ACE,认可POSA2。但是我认为你的靶子打错了。
> Roger Chen 写道:
>
> > To avlin:
> >
> > On Mon, 27 Feb 2006 16:22:47 -0000
> > "alvi...@gmail.com" <alvi...@gmail.com> 撰写于:
> >
> > >
> > > 露个脸,也来说二句。我用ACE一年左右,学了非常多东西,用起来是越来越顺手,ACE的架构模型是非常先进的,就模型上来说起码先进其他语言平台5到10年,看看Java的nio,J2SE5.0的Concurrency吧。
> > >
> >
> > 能稍微描述一下这先进的5到10年体现在什么地方吗?
> >
> > --
> > Roger Chen <che...@gmail.com>
>
>
--
Roger Chen <che...@gmail.com>
> On Tue, 28 Feb 2006 08:31:16 -0000
> "alvi...@gmail.com" <alvi...@gmail.com> 撰写于:
>
> > 就拿Proactor,Reactor,Task,Stream框架来说。Java里的Nio也都停留在select,poll的模型上,而且是前几年才加入的。连接、关闭等事件响应是异步的,但是读写仍然是同步的,算是半异步的模型。象Proactor包装的IOCP和Posix
> > AIO,所有的事件都可以是异步的,包括数据的读写,也都交给系统内核去完成后通知了,这对服务器的磁盘操作来说是非常有利的。也包括网络IO,网络IO在高负载的时候可以选用,降低并发线程占用的资源。
> >
>
> NIO所采用的是Reactor的模型。所有的事件都是异步的,包括连接、关闭、读、写
> 。但不同的地方在于,NIO异步读、写时会即时得到响应结果,而不是等事件完成
> 后才通过通知机制得到。
>
> 我对C++的网络开发不熟悉,不过我看到过sodme的这篇文章:
> http://blog.csdn.net/sodme/archive/2006/02/15/599132.aspx,觉得NIO的这种
> 机制应该和epoll是一样的。
>
> 实际上这种机制给了应用更大的弹性。基于nio,可以设计出各种应用模型。当然
> ,也带来了缺点,就是可能没有直接在内核完成操作然后通知应用来得高效。
是Reactor的处理过程要利用线程池,或者单线程并行,NIO的读写也需要在另外的线程里。
>
>
> > 再按模型来说,Reactor的事件通知、Proactor的异步模型,Java,.net的网络模型还没有达到这个高度,这里只指的是网络通讯的模型,不是应用服务器这样的业务应用层次,也算是系统层。
> >
> > 象java的Concurrency包,就是个很好的例子,几乎的就是照着ACE的Task框架来的,看看C++网络编程二卷和ACE编程指南APG,中的相关例子吧。
>
> 这个就不好评价了,我根本不了解ACE的Task框架。但是我并不认为concurrent包
> 是照着Task框架来的,JSR 166专家组绝对不是吃素的。
>
> 但我认为它们之间肯定会有类似的地方,就好像可以说Java里面a+b就是照着C里面
> 的a+b来的。
>
哈哈,我没偏见的,别激动啊。C++,Java我都搞的。C/C++/Java都是同根生,还有什么好争论,只不过是从系统层到业务层,各自占领地盘而已。发个email到JSR
166的专家组问下啊,POSA1/POSA2都很早就出了啊。
> >
> > ACE是个实现,可能感觉上没有很多商业的产品那么易用和全面,但是这就好比学术和工业,她所支撑和实现的是一个理论模型,而不是商业化的产品。商业化的产品会变,也许过个二年它又会新瓶旧酒又来一遍。就好比各种类Unix和Unix的思想一样,能说Linux就比那些老的Unix系统先进吗?实际上很多Linux的新特性,那些商用、非商用的Unix很早也有,只不过他很好的借助了GNU的力量。Unix的模型和思想能否定吗?我想POSA的模型也经过锤炼了的,是从工程实践中提取的学术模型,我们可能总会忽略理论模型,但实用技术研究到了深的层次又会回归到理论,因为那才是精髓。
> >
> > 而那些商业产品和平台不都还在挣扎么,为的是什么,是更快的响应市场、靠语法糖笼络开发人员,巩固他们的平台,占有市场,以获得各种利润。如果他们给你的是多么先进强大如何美妙的开发平台产品,往往你很难清晰的理解他们的平台框架和思想,因为你就是他们的实验品。他们的大师给你定义游戏规则,系统级开发也就没有我们的地盘了,我们永远是沉睡的neo。
> >
> > (说先进,确切的说是ACE的模型,POSA所描述的那些,那些流行的商业平台在网络通讯模型上是没有说在哪以项上推翻或者超越的,顶多是新的一些模型。)
> >
>
> 这个就太远了,没有人否定POSA2里面的模型,事实上大部分做网络应用的人也就
> 是在POSA2里面转圈圈。
>
呵呵,我太情绪化了。当我发彪啊。未来是我们的啊。可惜我们还弱啊。。。很悲哀的。。。特别是在国内。
> 但说到模型,实际上是更为宏观的一个层面,所以我并不认可你说的ACE的模型领
> 先其他语言平台5到10年。
>
说了是网络通讯啊。个人感觉而已,感叹而已。这个应该是不朽的,哪怕多进程阻塞模型都还有人用。不过从系统j层接口来说,这个框架个接口还是不错的。有多语言的版本就更好了。
> 假设在window系统没有提供iocp以前,能不能用select做出一个proactor模型来?
> 当然可以,只不过效率方面比不上而已。java里面的nio也是如此,它提供的只是
> 一个比较底层一点的api,基于这些api,使用者可以搭建出各种各样的模型,只不
> 过效率上会有一些问题,这是硬伤。
是,操作系统的用户空间的资源是有限的,内核空间可以把资源调度的更好,特别是I/O,就好比硬件的轮询、中断、DMA、管道样的。
>
> JSR 203也早提出在java中加入新的异步I/O,这就相当于可以利用各个操作系统级
> 的实现,不过一直没有人推动这件事情。
操作系统异步IO的接口差异太大,难度很大,所以说ACE了不起,但是还不是极致,要把基于模板的Policy-base的策略编程来屏蔽差异和功能划分就好了,就像Loki。
其实也没必要局限在某个单一的平台,特别是商业平台,如果有精力的话。其实技术都是通的,表面的,回归了还是理论,再说白点还是人,人解决问题的方法和思路,还有他们的感受。
>
> 我认可ACE,认可POSA2。但是我认为你的靶子打错了。
>
没有说Java的不好啊,其实Java现在的一些基础设施也开始不错起来啊。如果说还只有老的阻塞IO,那还怎么说呢。NIO的读写的确还没有进入内核态,还是用户在线程池里干的。不过象Posix
aio,iocp,epoll这些除非在比较变态的条件下才使用,各个操作系统的接口差异较大,不过这也算cut
edge的东西吧。
不敢苟同. 你认为高性能的网络应用,只有在BT条件下才会使用吗?我的看法恰恰相反,高性能的应用领域会越来越广泛,而且,可以这样说:任何一个优秀的网络应用系统,都必须解决高并发,高负载的问题,只要他是基于网络的.
> 引用 alvin的:
> -----------------------------------------
> 不过象Posix aio,iocp,epoll这些除非在比较变态的条件下才使用...
> ---------------------------------------------
>
> 不敢苟同. 你认为高性能的网络应用,只有在BT条件下才会使用吗?我的看法恰恰相反,高性能的应用领域会越来越广泛,而且,可以这样说:任何一个优秀的网络应用系统,都必须解决高并发,高负载的问题,只要他是基于网络的.
>
哇啊啊,火药味十足啊。
apache没用吧?ICE没用吧。使用线程池方式是编写简单,但是扩展麻烦,而且各session数据不容易同步,线程切换会消耗系统资源。使用异步IO那就是编写麻烦一些,数据处理容易集中进行,易扩充和各session交互,但是数据传递会消耗系统的锁资源,数据需要同步。如果是比较独立的处理,在非高负载的情况下,还是Reactor线程池里效率较高,但是在高压力且数据处理需要交互的情况下使用异步IO是比较好的。我看了C++网络编程和APG里讲过的,异步IO用来处理服务器磁盘文件IO是很好,但是处理网络IO,要求高负载可以,要求效率一般用传统模型,平台接口差异小,程序容易移植。
(大家千万别对我不满啊!个人意见而已,我没攻击你们啊。大家讨论问题,切磋啊。)
其实说回来这个主题也很广,不确定的,我谈了下ACE和POSA的看法而已啊,唠嗑了点Java的东西,没有说那个模型好坏么。其实高能网络,在单机不能承载的情况下还可以做集群,做分布式的。
(没有做辩论的想法,先跟大家混个脸熟,呵呵。)
大宝(sodme) 写道:
但反应式的读写还是要在线程池里做,一般处理也绑定在线程里。一般反应式做事件通知的消息机制也不错的,比如那些Time
Schedule,事件等等。
sunway 写道: