为C++实现一个IDL (五)

来源:转载

本篇没什么清晰的目的,只是解释一下前面的几个问题,并提出一些新的目标。

在“asgard项目遗留问题”中,我简单提到了几个问题,并且想了一些解决方案。

其中,最首要解决的是第2条“服务对象的大小”和第5条“全局元信息”,这2条将影响到调用机制、call对象的生成。一个调用将生成一个call对象,由线程池来处理,同步调用将由异步调用来模拟。

在call对象中,保存了所有in/out参数的包装对象。当处理同步调用时,由于out参数可能是一个栈上对象(或简单类型,这里统称对象),所以需要另一个包装类——outret模板类,它保存out参数的引用。

当同步调用发生时,生成一个call对象(当然out参数的引用已经包含在里面),把这个call对象交给线程池处理,调用的线程阻塞等待调用结束后被唤醒,这就是所谓的异步调用模拟同步调用。由于异步调用被包装起来了,所以在调用者看来跟同步调用没什么区别。当然这个动作并非必要,完全可以不使用模拟,而采用真正的同步调用,只是看到ICE是这么实现的,心痒痒而已。


asgard的目标是把现有的系统功能包装成为服务,所以在通用方面我考虑得比较多。

比如服务端要开放下面这样一个服务:

service StringService
{
Method <string(inout<string>, in<string>)> strcat;
Method <string(inout<string>, in<string>, in<uint>)> strncat;
};
并且把C标准库中的strcat和strncat作为这2个方法的实现。

看一下存在哪些问题?

1、函数第1个参数如果直接映射为string,在服务端将出现缓冲区溢出。

2、C标准库中的strcat返回值是一个指针,它指向strcat的第一个参数(搞这个标准库的人是不是没想过这个返回值多么没用啊??直接返回一个操作的长度不是更好?),在服务端发回客户端时,这个并不需要被发回来,因为strcat的第1个参数已经能带回操作后的内容了。

3、strncat的第3个参数表示第1个缓冲区参数的长度,如果能把它和第1个参数合起来用一个buffer对象表示,就能省事了。

理想情况下,我们的服务对象这样来写:

service StringService
{
Method <void(inout< buffer<char> >, in<string>)> strcat;
Method <void(inout< buffer<char> >, in<string>)> strncat;
};
我们的目的是把老的代码包装成新鲜时髦的服务,当然不用保留老式代码中的指针,以及使用指针和长度2个值来表示一个缓冲区的做法。buffer类在构造时要接受一个size_t参数,指定缓冲区的大小。

这在服务端将产生映射问题,由于这个Method定义的形式和C标准库中的函数形式不一致。

我想应该去实现一个适配器模板类,比如:

this->strcat.setFunction (adapter<char*(char*, const char*), convert<void, 0>(inout< buffer<char> >, in<string>)> (::strcat));

this->strncat.setFunction (adapter<char*(char*, const char*, size_t), convert<void, 0>(inout< buffer<char> >, in<string>, length<in<uint>, 1>)> (::strncat));
convert<void, 0>表示把第0个参数(这里指返回值)转成void类型,length<in<uint>, 1>表示这个参数类型是int<uint>,它是从第1个参数中提取的长度,大致就是使用这种规则,语法可能以后会有变动。

这点内容是我几个月前就在考虑的,也是我想做这个项目的动机,不过直到最近一段时间才从可行性方面仔细考虑。

通过前面几个模板的练习,现在已经大致知道哪些东西是可以用模板做出来,哪些不能使用模板,这应该是最大的收获了。很多东西单靠模板或是虚函数都不好完成,但结合起来就能产生意想不到的效果。



又仔细想了一下,上面的代码应该还可以修改简化:

this->strcat.setFunction (adapter<convert<void, 0>(inout< buffer<char> >, in<string>)> ( ) (::strcat));

this->strncat.setFunction (adapter<convert<void, 0>(inout< buffer<char> >, in<string>, length<in<uint>, 1>)> ( ) (::strncat));
使用一个仿函数来做,函数指针的类型可以从operator ()的参数(模板参数)中推导出来。



分享给朋友:
您可能感兴趣的文章:
随机阅读: