Chinaunix首页 | 论坛 | 博客
  • 博客访问: 14497274
  • 博文数量: 5645
  • 博客积分: 9880
  • 博客等级: 中将
  • 技术积分: 68081
  • 用 户 组: 普通用户
  • 注册时间: 2008-04-28 13:35
文章分类

全部博文(5645)

文章存档

2008年(5645)

我的朋友

分类:

2008-04-28 20:53:18

下载本文示例代码
  一时灵感涌现,有所顿悟,遂记录下来。注意不保证正确性。   我们知道公寓只是个逻辑概念,操作系统只为线程进程分配资源,不会为公寓分配资源。当客户程序调用 CoInitializeEx()时指定公寓类型,是STA还是MTA,只有COM才用到公寓这个概念。那为什么要创建这样一个概念,从根本上说是为了实现在多线程中同步地访问组件,尽可能地为我们编写组件制造方便,免除我们必须自己实现同步控制的麻烦。那它是怎么实现的呢?   对于STA来说,我们知道当以COINIT_APARTMENTTHREADED参数调用CoInitializeEx()的时侯,系统会自动创建一个隐含的窗口。该隐含窗口的消息队列被用于同步化并分派对该STA内创建的对象的方法的调用。在这个公寓外其他线程要想调用该公寓内的对象方法,都必须先放在消息队列里,因为消息队列是线性的,所以自然而然的就解决了同步问题。对于MTA也应该是类似的方法,虽然书上没有说,但我想MTA公寓一样会有一个隐含的窗口。   公寓间必须要调度,这句话包含了两个方面的意思,也即是包含了两种调度。第一个调度是指在公寓间调度接口指针。调用一个对象的方法,首先就是要获得它的接口指针。COM的接口指针是与公寓相关的,显然它们不能直接被某线程用于其它公寓。那样的话就等于跳过了消息队列而直接调用对象了,没法保证同步性。所以这时必须要调度。调度方法很简单,假设在STA2中要得到STA1中的一个对象的接口指针,则在STA1线程里通过调用CoMarshallInterThreadfaceInStream把对象接口指针调度到一个流对象内,然后在STA2线程内通过调用CoGetInterfaceAndReleaseStream反调度该流对象并获得一个指向代理的指针,这个代理在STA2内,并与STA1相关。要注意到的是,STA2得到的指向代理Proxy的指针,而不是直接指向对象接口的指针。第二个调度就很自然了,每当STA2要调用STA1中的接口方法时都要通过Proxy,这也叫调度。   联系到前面讲到的公寓使用窗口消息队列来实现同步化的方法,我们可以猜测这里代理的作用是与这个消息队列相关的。很可能代理就是简单的把对方法的调用放到窗口的消息队列中。   公寓间的这种调度与进程间以及远程间的调度显然是有根本区别的,这一点从另外一个角度也可以看出来。公寓间的调度并非是必须的!如果组件自身已经实现了同步控制,那公寓间的调度就是完全没有必要的了,因为我们说过公寓的作用完全在于帮助我们实现同步访问问题。既然我们可以通过自由线程调度器FTM来跨过公寓间的调度而直接调用接口方法,那也可以看出,公寓间的调度不是必须的!进程间以及远程间的调度肯定都是必须的,那这两种调度之间的区别何在呢?后者的调度产生原因在于进程处于不同的地址空间,甚至是在不同机器上的,需要调度解决这个问题。既包含调度接口指针,也包含了更为重要的参数打包解包的调度。但对于公寓间的调度不存在这个问题,因为公寓的一个基本点在于它是存在于一个进程内的。所以它不需要完成不同地址空间的映射,不需要把函数参数打包解包,它的调度的目的完全是不同的。另外我们也注意到,公寓间的调度只有代理Proxy,没有存根Stub。这也应该证明了我们的猜想吧,公寓间的调度只是为了解决同步性问题,代理的作用仅仅是把函数调度放到消息队列中。   以上内容可以总结为以下几点:   1、MTA公寓也有一个隐含窗口,也是通过窗口消息队列来实现同步性的。   2、公寓间必须调度接口指针,调度的结果是获得一个指向代理的指针。   3、公寓间的接口方法调用,必须通过代理来实现。   4、公寓间的调度完全只是为了实现同步性。   5、公寓间的调度只有代理没有存根。   6、代理的作用只是简单的把接口的方法调用放入窗口消息队列中。   一时灵感涌现,有所顿悟,遂记录下来。注意不保证正确性。   我们知道公寓只是个逻辑概念,操作系统只为线程进程分配资源,不会为公寓分配资源。当客户程序调用 CoInitializeEx()时指定公寓类型,是STA还是MTA,只有COM才用到公寓这个概念。那为什么要创建这样一个概念,从根本上说是为了实现在多线程中同步地访问组件,尽可能地为我们编写组件制造方便,免除我们必须自己实现同步控制的麻烦。那它是怎么实现的呢?   对于STA来说,我们知道当以COINIT_APARTMENTTHREADED参数调用CoInitializeEx()的时侯,系统会自动创建一个隐含的窗口。该隐含窗口的消息队列被用于同步化并分派对该STA内创建的对象的方法的调用。在这个公寓外其他线程要想调用该公寓内的对象方法,都必须先放在消息队列里,因为消息队列是线性的,所以自然而然的就解决了同步问题。对于MTA也应该是类似的方法,虽然书上没有说,但我想MTA公寓一样会有一个隐含的窗口。   公寓间必须要调度,这句话包含了两个方面的意思,也即是包含了两种调度。第一个调度是指在公寓间调度接口指针。调用一个对象的方法,首先就是要获得它的接口指针。COM的接口指针是与公寓相关的,显然它们不能直接被某线程用于其它公寓。那样的话就等于跳过了消息队列而直接调用对象了,没法保证同步性。所以这时必须要调度。调度方法很简单,假设在STA2中要得到STA1中的一个对象的接口指针,则在STA1线程里通过调用CoMarshallInterThreadfaceInStream把对象接口指针调度到一个流对象内,然后在STA2线程内通过调用CoGetInterfaceAndReleaseStream反调度该流对象并获得一个指向代理的指针,这个代理在STA2内,并与STA1相关。要注意到的是,STA2得到的指向代理Proxy的指针,而不是直接指向对象接口的指针。第二个调度就很自然了,每当STA2要调用STA1中的接口方法时都要通过Proxy,这也叫调度。   联系到前面讲到的公寓使用窗口消息队列来实现同步化的方法,我们可以猜测这里代理的作用是与这个消息队列相关的。很可能代理就是简单的把对方法的调用放到窗口的消息队列中。   公寓间的这种调度与进程间以及远程间的调度显然是有根本区别的,这一点从另外一个角度也可以看出来。公寓间的调度并非是必须的!如果组件自身已经实现了同步控制,那公寓间的调度就是完全没有必要的了,因为我们说过公寓的作用完全在于帮助我们实现同步访问问题。既然我们可以通过自由线程调度器FTM来跨过公寓间的调度而直接调用接口方法,那也可以看出,公寓间的调度不是必须的!进程间以及远程间的调度肯定都是必须的,那这两种调度之间的区别何在呢?后者的调度产生原因在于进程处于不同的地址空间,甚至是在不同机器上的,需要调度解决这个问题。既包含调度接口指针,也包含了更为重要的参数打包解包的调度。但对于公寓间的调度不存在这个问题,因为公寓的一个基本点在于它是存在于一个进程内的。所以它不需要完成不同地址空间的映射,不需要把函数参数打包解包,它的调度的目的完全是不同的。另外我们也注意到,公寓间的调度只有代理Proxy,没有存根Stub。这也应该证明了我们的猜想吧,公寓间的调度只是为了解决同步性问题,代理的作用仅仅是把函数调度放到消息队列中。   以上内容可以总结为以下几点:   1、MTA公寓也有一个隐含窗口,也是通过窗口消息队列来实现同步性的。   2、公寓间必须调度接口指针,调度的结果是获得一个指向代理的指针。   3、公寓间的接口方法调用,必须通过代理来实现。   4、公寓间的调度完全只是为了实现同步性。   5、公寓间的调度只有代理没有存根。   6、代理的作用只是简单的把接口的方法调用放入窗口消息队列中。 下载本文示例代码


公寓间的线程调度问题公寓间的线程调度问题公寓间的线程调度问题公寓间的线程调度问题公寓间的线程调度问题公寓间的线程调度问题公寓间的线程调度问题公寓间的线程调度问题公寓间的线程调度问题公寓间的线程调度问题公寓间的线程调度问题公寓间的线程调度问题公寓间的线程调度问题公寓间的线程调度问题公寓间的线程调度问题
阅读(255) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~