重拾cgi——uri绑定

前面两篇博客讲了从uri到模板输出,还没有提到中间处理参数的部分。
首先,参数绑定简单的放在一个map中,这里用的是boost的unordered_map(也就是hashmap),其实已经可以使用c++11提供的unordered_map了。
[cce lang="cpp"]
boost::unordered::unordered_map<std::string, RequestHandleFunc> _mapping;
[/cce]
这个map的value,是一个functor,具体定义为:
[cce lang="cpp"]
typedef boost::function<void (Context &context)> RequestHandleFunc;
[/cce]
也就是没有返回值,参数是Context的函数。
Context结构非常简单,主要是封装了输入和输出,也就是cgi、ostream、dict等对象,没有进行太多的抽象。
[cce lang="cpp"]
struct Context
{
cgicc::Cgicc &cgi;
cgicc::CgiInput &input;
std::ostream &ostream;
boost::shared_ptr<ctemplate::TemplateDictionary> dict;
};
[/cce]
这里增加了cgiInput,主要是因为cgicc封装了常用cgi环境变量,没法取到自定义环境变量(前一篇博客介绍过)。
绑定函数非常简单,就是直接插入,需要注意的是,unordered_map非线程安全,没有线程类似java的concurrent hashmap(google了下intel tbb库有类似的数据结构),所以采用了boost thread库中的互斥变量:
[cce lang="cpp"]
void bind(const std::string &path, RequestHandleFunc func)
{
boost::unique_lock<boost::shared_mutex> lock(_mutex);
_mapping.insert(std::pair<std::string, RequestHandleFunc>(path, func));
}
[/cce]
注意,boost的锁分为unique_lock和shared_lock,这里是“写者”,所以需要独占锁。
处理方法前文已经贴了代码了,同样要注意的是,需要在搜索map的时候加锁。这里是“读者”,所以使用shared_lock即可:
[cce lang="cpp"]
boost::shared_lock<boost::shared_mutex> lock(_mutex);
[/cce]
为了方便绑定,写了个宏,直接绑定。
[cce lang="cpp"]
#define REGISTER_URL(URL, CLASS, METHOD) \
CLASS c##CLASS; Handler::instance().bind(URL, boost::bind(&CLASS::METHOD, &c##CLASS, _1))
[/cce]

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据