boost.asio源码剖析(五) ---- 泛型与面向对象的完美结合
有人说C++是带类的C;有人说C++是面向对象编程语言;有人说C++是面向过程与面向对象结合的语言。类似的评论网上有很多,虽然正确,却片面,是断章取义之言。
C++是实践的产物,C++并没有为了成为某某类型的语言而设计,而是一切以工程实践为目的,一切以提升语言能力为目的。
1983年C++诞生之时,由于兼容C语言而天生拥有了面向过程编程的能力;
1989年推出的2.0版,C++完善了对面向对象编程范式的支持;
1993年的3.0版,C++中引入了模板(template),有了泛型编程的雏形;
1998年的C++第一次标准化,为支持著名的C++标准库中的STL,对泛型编程有了更完善的支持,并且发现了模板元编程;
2011年9月的C++第三次标准化(C++11),进一步加强了泛型编程、模板元编程和并发编程的能力,也进一步加强了直接对硬件的操作能力,并且由于lambda的出现和早就出现在boost库中的bind/function等C++自扩展的组件,C++也拥有了一定程度上的函数式编程能力。
模板技术给C++带来了强大至极的自扩展能力,在不修改编译器和语言核心功能的前提下依然可以使用语言自身模拟出各种各样的编程范式;这各种模拟又为C++语言的前进指引了方向,提供了工程实践的检验机会。经过三十年的实践,C++已逐渐发展为一门多范式编程语言,集面向过程、面向对象、泛型编程、模板元编程、函数式编程等多种范式于一身。随着广大C++er的不断实践与探索,C++会从中汲取经验与教训,越来越强大!
本章中你将看到asio中对泛型编程和面向对象编程两种范式的结合使用,为你打开多范式混合编程的大门。在这里,泛型编程和面向对象编程两种编程范式相辅相成、取长补短,发挥出了单一编程范式无法比拟的强大威力,堪称多范式编程语言的应用典范。
* Service Concept
Service,与basic_io_object结合时是一种泛型Concept,与io_service和service_registry结合时是面向对象思想中service_base的泛化类型。
Service作为泛型Concept时,其约束摘要如下:
class Service
{
public:
typedef ... implementation_type; void construct(implementation_type& );
void destroy(implementation_type& );
io_service& get_io_service();
};
其中,implementation_type是Service对应的I/O对象持有的句柄类型,basic_io_object在构造/析构时会调用construct/destroy接口注册/注销到Service中。
Service与io_service和service_registry结合时,要求其必须继承于service_base。
service_base及其基类io_service::service的类摘要如下:
class io_service::service
: private noncopyable
{
public:
boost::asio::io_service& get_io_service(); protected:
service(boost::asio::io_service& owner);
virtual ~service(); private:
virtual void shutdown_service() = ; virtual void fork_service(boost::asio::io_service::fork_event event); friend class boost::asio::detail::service_registry;
struct key
{
key() : type_info_(), id_() {}
const std::type_info* type_info_;
const boost::asio::io_service::id* id_;
} key_; boost::asio::io_service& owner_;
service * next_;
}; template <typename Type>
class service_base : public io_service::service
{
public:
static boost::asio::detail::service_id<Type> id; service_base(boost::asio::io_service& io_service) : io_service::service(io_service) {}
};
其中,Service在service_registry中是以侵入式的单链表存储的,io_service::service中成员next_即是指向下一个Service的指针。service_base类的模板参数Type即是Service的类型,Service在继承service_base时的写法大致如下:
class Service
: public service_base<Service>
{
};
将两种约束结合,得到一个最简单的可以与I/O对象搭配使用的Service的写法如下:
class Service
: public service_base<Service>
{
public:
typedef ... implementation_type; void construct(implementation_type&);
void destroy(implementation_type&);
io_service& get_io_service();
};
* CSU(Core-Service-User架构)
第一章中单纯从面向对象的角度介绍过Asio的核心架构,本节不再局限于单一编程范式,从源码分析开始剖析Asio的核心架构。
Asio的核心架构是由三大组件构成,其分别是:
让用户直接使用,为用户提供接口的组件,暂且称之为User;
无需用户感知的,为User的接口提供实现的服务组件,称为Service;
负责组合多个Service,并辅助User对象的实例化的核心组件,称为Core;
这种由Core-Service-User三部分组成的架构,为行文方便暂且简称为CSU。
在Asio的CSU架构中,io_service以及几个关联类和内部类扮演了Core的角色;之前提到的ServiceConcept约定了Service的扩展方式;本节以一个Service及其对应的I/O对象为例介绍CSU的实现。为了易于理解,将源码中用于实现CSU的部分摘要出来,忽略与CSU无关的代码,并做一些小幅度修改。
Core相关代码摘要:
class io_service
{
// 持有一个service_registry对象
service_registry * service_registry_;
}; // 返回ios中服务类型是Service的服务的引用
template <typename Service> Service& use_service(io_service& ios); // 给ios添加服务svc
template <typename Service> void add_service(io_service& ios, Service* svc); // 判断ios中是否有服务类型是Service的服务
template <typename Service> bool has_service(io_service& ios); // 所有Service的根基类
class io_service::service
{
}; // 用于组合多个Service
class service_registry
{
io_service::service * service_list_; private:
/// 以下三个函数是同名自由函数的真正实现
template <typename Service> Service& use_service();
template <typename Service> void add_service(Service* svc);
template <typename Service> bool has_service();
}; // 所有Service的直接父类,Type必须为Service自身类型。
template <typename Type>
class service_base
{
static service_id<Type> id;
};
Service,以deadline_timer_service为例:
// 定时器服务
template <typename TimeType,
typename TimeTraits = boost::asio::time_traits<TimeType> >
class deadline_timer_service
{
private:
typedef detail::deadline_timer_service<traits_type> service_impl_type; public:
typedef typename service_impl_type::implementation_type implementation_type; /// Construct a new timer service for the specified io_service.
explicit deadline_timer_service(boost::asio::io_service& io_service)
: boost::asio::detail::service_base<
deadline_timer_service<TimeType, TimeTraits> >(io_service),
service_impl_(io_service)
{
} /// Construct a new timer implementation.
void construct(implementation_type& impl)
{
service_impl_.construct(impl);
} /// Destroy a timer implementation.
void destroy(implementation_type& impl)
{
service_impl_.destroy(impl);
} /// Cancel any asynchronous wait operations associated with the timer.
std::size_t cancel(implementation_type& impl, boost::system::error_code& ec)
{
return service_impl_.cancel(impl, ec);
} /// Cancels one asynchronous wait operation associated with the timer.
std::size_t cancel_one(implementation_type& impl,
boost::system::error_code& ec)
{
return service_impl_.cancel_one(impl, ec);
} /// Get the expiry time for the timer as an absolute time.
time_type expires_at(const implementation_type& impl) const
{
return service_impl_.expires_at(impl);
} /// Set the expiry time for the timer as an absolute time.
std::size_t expires_at(implementation_type& impl,
const time_type& expiry_time, boost::system::error_code& ec)
{
return service_impl_.expires_at(impl, expiry_time, ec);
} /// Get the expiry time for the timer relative to now.
duration_type expires_from_now(const implementation_type& impl) const
{
return service_impl_.expires_from_now(impl);
} /// Set the expiry time for the timer relative to now.
std::size_t expires_from_now(implementation_type& impl,
const duration_type& expiry_time, boost::system::error_code& ec)
{
return service_impl_.expires_from_now(impl, expiry_time, ec);
} // Perform a blocking wait on the timer.
void wait(implementation_type& impl, boost::system::error_code& ec)
{
service_impl_.wait(impl, ec);
} // Start an asynchronous wait on the timer.
template <typename WaitHandler>
BOOST_ASIO_INITFN_RESULT_TYPE(WaitHandler,
void (boost::system::error_code))
async_wait(implementation_type& impl,
BOOST_ASIO_MOVE_ARG(WaitHandler) handler)
{
detail::async_result_init<
WaitHandler, void (boost::system::error_code)> init(
BOOST_ASIO_MOVE_CAST(WaitHandler)(handler)); service_impl_.async_wait(impl, init.handler); return init.result.get();
} private:
// Destroy all user-defined handler objects owned by the service.
void shutdown_service()
{
service_impl_.shutdown_service();
} // The platform-specific implementation.
service_impl_type service_impl_;
};
User相关代码,以basic_deadline_timer为例:
template <typename IoObjectService>
class basic_io_object
{
public:
typedef IoObjectService service_type;
typedef typename service_type::implementation_type implementation_type; boost::asio::io_service& get_io_service(); protected:
explicit basic_io_object(boost::asio::io_service& io_service)
: service_(&boost::asio::use_service<IoObjectService>(io_service))
{
service_->construct(implementation);
} ~basic_io_object()
{
service_->destroy(implementation);
} service_type& get_service()
{
return *service_;
} const service_type& get_service() const
{
return *service_;
} implementation_type& get_implementation()
{
return implementation;
} const implementation_type& get_implementation() const
{
return implementation;
} implementation_type implementation; private:
basic_io_object(const basic_io_object&);
void operator=(const basic_io_object&); IoObjectService* service_;
}; template <typename Time,
typename TimeTraits = boost::asio::time_traits<Time>,
typename TimerService = deadline_timer_service<Time, TimeTraits> >
class basic_deadline_timer
: public basic_io_object<TimerService>
{
public:
/// 三个构造函数均需要io_service&
explicit basic_deadline_timer(boost::asio::io_service& io_service);
basic_deadline_timer(boost::asio::io_service& io_service, const time_type& expiry_time);
basic_deadline_timer(boost::asio::io_service& io_service, const duration_type& expiry_time); ////////////////////////////////////////////////////
/// @{ 功能性接口
std::size_t cancel();
std::size_t cancel(boost::system::error_code& ec);
std::size_t cancel_one();
std::size_t cancel_one(boost::system::error_code& ec); time_type expires_at() const;
std::size_t expires_at(const time_type& expiry_time);
std::size_t expires_at(const time_type& expiry_time, boost::system::error_code& ec); duration_type expires_from_now() const;
std::size_t expires_from_now(const duration_type& expiry_time);
std::size_t expires_from_now(const duration_type& expiry_time, boost::system::error_code& ec); void wait();
void wait(boost::system::error_code& ec); template <typename WaitHandler>
BOOST_ASIO_INITFN_RESULT_TYPE(WaitHandler, void (boost::system::error_code))
async_wait(BOOST_ASIO_MOVE_ARG(WaitHandler) handler);
/// @}
/////////////////////////////////////////////////////
};
在basic_deadline_timer和其对应服务deadline_timer_service的源码中可以很清晰的看到,他们都有名为cancel/cancel_one/expires_at/expires_from_now/wait/async_wait的函数,这些是deadline_timer对外提供的功能接口;basic_deadline_timer类中的这些接口只是对deadline_timer_service中同名接口的封装。
在Asio的CSU架构中,用泛型编程的方式约束Service和User,使他们拥有极强的扩展性;用面向对象的手段联结Core-Service-User三大组件,从用户的角度看,产生类似于“高内聚”的效果,让用户可以以简单而统一的接口使用asio,不必自行处理高难度的泛型组件的组装工作。
由于本文会实时根据读者反馈的宝贵意见更新,为防其他读者看到过时的文章,因此本系列专题谢绝转载!
boost.asio源码剖析(五) ---- 泛型与面向对象的完美结合的更多相关文章
- boost.asio源码剖析
一. 前 言二. 架构浅析三. 流程分析 * 常见流程分析之一(Tcp异步连接) * 常见流程分析之二(Tcp异步接受连接) * 常见流程分析之三(Tcp异步读写数据) ...
- boost.asio源码剖析(一) ---- 前 言
* 前言 源码之前,了无秘密. ——侯捷 Boost库是一个可移植.提供源代码的C++库,作 ...
- boost.asio源码剖析(三) ---- 流程分析
* 常见流程分析之一(Tcp异步连接) 我们用一个简单的demo分析Tcp异步连接的流程: #include <iostream> #include <boost/asio.hpp& ...
- boost.asio源码剖析(四) ---- asio中的泛型概念(concepts)
* Protocol(通信协议) Protocol,是asio在网络编程方面最重要的一个concept.在第一章中的levelX类图中可以看到,所有提供网络相关功能的服务和I/O对象都需要Protoc ...
- boost.asio源码剖析(二) ---- 架构浅析
* 架构浅析 先来看一下asio的0层的组件图. (图1.0) io_object是I/O对象的集合,其中包含大家所熟悉的socket.deadline_tim ...
- boost.asio源码阅读(2) - task_io_service
1.0 task_io_service 在boost.asio源码阅读(1)中,代码已经查看到task_io_service中. 具体的操作调用void task_io_service::init_t ...
- Django Rest Framework源码剖析(五)-----解析器
一.简介 解析器顾名思义就是对请求体进行解析.为什么要有解析器?原因很简单,当后台和前端进行交互的时候数据类型不一定都是表单数据或者json,当然也有其他类型的数据格式,比如xml,所以需要解析这类数 ...
- boost.compressed_pair源码剖析
意义 当compressed_pair的某一个模板参数为一个空类的时候将对其进行“空基类优化”,这样可以使得compressed_pair占用的空间比std::pair的更小. 参考如下代码: #in ...
- boost.asio源码阅读(1) - 从chat_server开始
1. 关于示例代码 chat 先从简单的入手, 在如下路径:boost_1_63_0/libs/asio/example/cpp11/chat中找到chat_server.cpp 查看其成员, pri ...
随机推荐
- (转载)OC学习篇之---协议的概念和用法
在前一篇文章中我们介绍了OC中类的延展,这一篇文章我们在来看一下OC中协议的概念以及用法,协议也是OC中的一个重点,Foundation框架以及我们后面在写代码都会用到. OC中的协议就是相当于Jav ...
- 人们对Python在企业级开发中的10大误解
From : 人们对Python在企业级开发中的10大误解 在PayPal的编程文化中存在着大量的语言多元化.除了长期流行的C++和Java,越来越多的团队选择JavaScript和Scala,Bra ...
- 桶排序-Node.js-对象排序
const b = [{index:5,name:"s5"}, {index:2,name:"s2"}, {index:3,name:"s3" ...
- WinForms 使用Graphics绘制字体阴影
C#以两种方法实现文字阴影效果,同时还实现了简单的动画效果: 一种是对文本使用去锯齿的边缘处理,在两个不同的位置绘制文本,形成阴影: 另一个是以阴影为线条,构造影线画刷,先画背景再画前景,使用grap ...
- 轻松学习Linux之VI编辑器的使用
本文出自 "李晨光原创技术博客" 博客,谢绝转载!
- C#实现office文档转换为PDF或xps的一些方法( 转)
源博客http://blog.csdn.net/kable999/article/details/4786654 代码支持任意office格式 需要安装office 2007 还有一个office20 ...
- setInterval和setTimeout调用方法小知识科普
function a() { alert('hello'); } setInterval(a, ); setInterval(a(), ); setInterval(); setInterval(); ...
- apache与IIS端口冲突修改和需要使用 SSL 查看该资源”错误
改变Apache端口等配置修改方法 www.educity.cn 发布者:jsb200421 来源:网络转载 发布日期:2014年01月02日 如何改变Apache端口:找到Apache安装目录下co ...
- chrome emulator use-agent 设置 chrom模拟手机客户端
谷歌升级以后,发现找不到use-agent设置了 在Element 下点击ESC 出现console,再点击Emulation就出现了
- hdu 1171 Big Event in HDU(多重背包+二进制优化)
题目链接:hdu1171 思路:将多重背包转为成完全背包和01背包问题,转化为01背包是用二进制思想,即件数amount用分解成若干个件数的集合,这里面数字可以组合成任意小于等于amount的件数 比 ...