boost.asio源码剖析(五) ---- 泛型与面向对象的完美结合

时间:2023-03-09 08:02:44
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,不必自行处理高难度的泛型组件的组装工作。

由于本文会实时根据读者反馈的宝贵意见更新,为防其他读者看到过时的文章,因此本系列专题谢绝转载!