cinatra源码学习一:client_factory.hpp学习

client_factory.hpp文件源码

#pragma once
#include "simple_client.hpp"

namespace cinatra {
	class client_factory {
	public:
		static client_factory& instance() {
			static client_factory instance;
			return instance;
		}

		template<typename...Args>
		auto new_client(Args&&... args) {
			return std::make_shared<simple_client>(ios_, std::forward<Args>(args)...);
		}

		void run() {
			ios_.run();
		}

		void stop() {
			ios_.stop();
		}

	private:
		client_factory() : work_(ios_) {
			thd_ = std::make_shared<std::thread>([this] {ios_.run(); });
		}

		~client_factory() { 
			ios_.stop(); 
			thd_->join();
		}

		client_factory(const client_factory&) = delete;
		client_factory& operator=(const client_factory&) = delete;
		client_factory(client_factory&&) = delete;
		client_factory& operator=(client_factory&&) = delete;

		boost::asio::io_service ios_;
		boost::asio::io_service::work work_;
		std::shared_ptr<std::thread> thd_;
	};

#ifdef CINATRA_ENABLE_SSL
	template<res_content_type CONTENT_TYPE = res_content_type::json, size_t TIMEOUT = 3000, http_method METHOD = POST>
	inline std::string send_msg(std::string ip, std::string api, std::string msg, boost::asio::ssl::context & context) {
		assert(!api.empty() && api[0] == '/');
		auto client = client_factory::instance().new_client(std::move(ip), "https", context);
		return client->send_msg<CONTENT_TYPE>(std::move(api), std::move(msg));
	}

	template<res_content_type CONTENT_TYPE = res_content_type::json, size_t TIMEOUT = 3000, http_method METHOD = POST>
	inline std::string send_msg(std::string ip, std::string port, std::string api, std::string msg, boost::asio::ssl::context & context) {
		assert(!api.empty() && api[0] == '/');
		auto client = client_factory::instance().new_client(std::move(ip), std::move(port), context);
		return client->send_msg<CONTENT_TYPE>(std::move(api), std::move(msg));
	}
#else
	template<res_content_type CONTENT_TYPE = res_content_type::json, size_t TIMEOUT = 3000, http_method METHOD = POST>
	inline std::string send_msg(std::string ip, std::string api, std::string msg) {
		assert(!api.empty() && api[0] == '/');
		auto client = client_factory::instance().new_client(std::move(ip), "http");
		return client->send_msg<CONTENT_TYPE>(std::move(api), std::move(msg));
	}

	template<res_content_type CONTENT_TYPE = res_content_type::json, size_t TIMEOUT = 3000, http_method METHOD = POST>
	inline std::string send_msg(std::string ip, std::string port, std::string api, std::string msg) {
		assert(!api.empty() && api[0] == '/');
		auto client = client_factory::instance().new_client(std::move(ip), std::move(port));
		return client->send_msg<CONTENT_TYPE>(std::move(api), std::move(msg));
	}
#endif
}

C++语法学习:

  • 命名空间cinatra下定义了一个类client_factory
  • template<typename…Args>是C++11开始有的语法,被其修饰的方法表示可以接受零个或者更多参数。
  • std::make_shared的函数声明如下:
    template <class T, class... Args>
    shared_ptr<T> make_shared (Args&&... args);
    
    该函数用来对类型为T的对象分配一片空间并将其封装成类对象,args是传递给该待被构造的对象的构造函数的形参,最终结果返回一个shared_ptr类对象,该类内部保存一直指针指向刚才传进来的内存空间,该类对象内部引用计数值为1。
    如以下源码所示:
    /*
    * 创建客户端对象
    */
    template<typename...Args>
    auto new_client(Args&&... args) {
    	return std::make_shared<simple_client>(ios_, std::forward<Args>(args)...);
    }
    
    new_client()函数返回了一个包含simple_client对象地址的shared_ptr<simple_client>对象。
  • delete关键字用来指定某个函数程序员不能显示调用
  • #ifdef CINATRA_ENABLE_SSL #else #endif 是条件编译语句:表示如果之前已经定义过CINATRA_ENABLE_SSL字段则编译“#ifdef CINATRA_ENABLE_SSL #else”之间的代码,否则编译“ #else #endif”之间的代码

源码学习:

cinatra::client_factory类图如下所示:

在这里插入图片描述
Boost.Asio是一个跨平台的C++库,该库主要用在网络和低层次的IO编程方面进行使用,该库作用是通过使用现代C++方法对外提供一致的异步通信模型。

关于boost::asio::io_service类介绍如下:
```cpp
namespace boost {
namespace asio {

#if !defined(BOOST_ASIO_NO_DEPRECATED)
/// Typedef for backwards compatibility.
typedef io_context io_service;
#endif // !defined(BOOST_ASIO_NO_DEPRECATED)

} // namespace asio
} // namespace boost
```

io_context的作用是为想要使用异步IO对象的用户提供核心的IO函数接口,包括:

  • boost::asio::ip::tcp::socket
  • boost::asio::ip::tcp::acceptor
  • boost::asio::ip::udp::socket
  • deadline_timer
    该类也提供开发者用来自定义实现异步service的接口。
    关于io_context的更多介绍详见:io_context介绍
关于boost::asio::io_context::work类介绍如下:

在这里插入图片描述
如上所示:该类主要用来告知io_context类work什么时候开始和结束。当work正在运行的时候确保io_context对象的run()方法不会退出,并且当所有的work都结束的时候才使run()退出执行。
关于std::shared_ptr<std::thread>的相关介绍:
C++11之后引入的线程库,此处主要将其封装在shared_ptr对象中进行管理。

io_context中两个关键函数:

io_context::run(); //Run the io_context object's event processing loop
io_context::stop();//Stop the io_context object's event processing loop.
std::shared_ptr<std::thread> thd_:管理线程对象

创建client_factory的时候就通过ios_对象创建了线程对象,并封装到shared_ptr对象中以初始化thd_成员变量,同时启动ios_对象的事件处理循环机制。
在对client_factory对象进行析构(空间回收)的时候结束ios_对象的事件处理循环机制,同时调用thd_的join()方法,join()方法的介绍如下所示:
在这里插入图片描述
如图中所示:
1.该方法当线程中所有的执行操作都执行完成的时候会向上(其调用者)返回。
2.当当前线程中的所有操作执行完成并向上(当前线程的调用者)返回时会同步状态信息,同时会对其调用者的执行进行block(锁住、阻塞)直到当前线程执行结束并向上返回时。
3.调用该函数后,线程对象会变成一个non-joinable的对象,之后就可以安全的销毁。

client_factory发送消息
  1. 通过CINATRA_ENABLE_SSL的定义来决定是使用“HTTP”还是“HTTPS”的方式进行消息的发送。
  2. 不管以“HTTP”还是“HTTPS”的方式都定义两个方法send_msg,第一个方法通过ip来构造客户端对象,发送api和msg;第二个方法通过ip和port来构造客户端对象,发送api和msg。

以上即为我对client_factory.hpp的学习结果,总结的有些混乱。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值