[原创]函数调度代替数据调度 boost::bind的应用
望大家多支持HelloWorld论坛,本人原创的不多,转载要注明出处哦!
一般我们的线程是这样运行的,有一个数据队列,一端放入数据,线程循环取数据,解析数据,执行操作。这样做有几个不方便的地方:
1》当这个操作需要额外的数据的时候,必须定义一个专属的数据结构,放入队列(也许以后可以解决)。
2》在线程解析,执行都是要人工预先声明的。每个类型的处理都要写明。
学习boost::bind之后,发现他可以打包函数。最主要的有点是,比如数据库查询,DO(DataBase db);这样一个函数调用。我们有存入学生,存入课程
比如:
存入学生 SaveSud(DataBase db, 学生姓名,性别,年龄等);
存入课程 SaveKC(DataBase db, 课程名,任课老师,课时等);
我们可以打包 Sud=boost::bind(SaveSud, _1, 学生姓名,性别,年龄等数据)
KC = boost::bind(SaveKC, _1, 课程名,任课老师,课时等数据)
我们每个线程有一个数据库对象DataBase
db(一般都这么设计,设计几个数据库线程,其他地方就没有数据库对象了,每个数据库创建一个数据库连接,原因是创建数据库连接很费时,然后把要处理的数据扔到数据库线程队列去),所以我们只要这样调用就可以了
Sub(db);
KC(db);
这样我们就不用为存入学生,存入课程预先设计专门的数据结构了(传数据入数据库线程)。
boost::bind 是如何实现的呢,网上有很多介绍。我不说了,语言功底差,也很难说清楚,说说如何实现吧。
队列还是数据队列,函数就是地址的数据。这里能够这样做要靠模板技术,大家看看我是怎么使用模板技术的。
先定义一个父类,数据库线程队列,就是这个父类的(智能)指针列表
class TaskOperation : public BlockClass { public: virtual long operator ()(DataBase db) { return 0; } //private: // TaskOperation(); // 默认构造 // TaskOperation(const TaskOperation&); //复制构造 // TaskOperation& operator= (const TaskOperation&); // 等于重载 };
下面是关键,定义一个模板子类
template <typename Handler> class TaskOperationBoost : public TaskOperation { public: TaskOperationBoost(Handler h) : m_handler(h) { } virtual long operator ()(DataBase db) { m_handler(db); return 0; } private: TaskOperationBoost(); // 默认构造 TaskOperationBoost(const TaskOperationBoost&); //复制构造 TaskOperationBoost& operator= (const TaskOperationBoost&); // 等于重载 Handler m_handler; };
这里使用了括号重载,其实使用普通的虚函数也是没关系的。
这下来就是打包函数,模板函数
template <typename Handler> void OnIdleDone(Handler h) { boost::shared_ptr<TaskOperationBoost<Handler> > ope(new TaskOperationBoost<Handler>(h)); // 接下来把这个对象放入数据库线程队列 ....... }
下面就是数据库线程了
int TaskDB::svc (void) { // 数据库线程启动 DataBase db(host, user, password, strDBName, port); while (true) { // 判断是否要退出线程 ...... //取数据 boost::shared_ptr<TaskOperation> pOperation = ...... if (pOperation) { (*pOperation)(db); } } // 数据库线程停止 return 0; }
这样就实现了函数调度,现在发现的问题是,数据调度的时候,队列里面有没有数据,线程都可以退出。函数调用,当每个函数的参数是指针,并且执行函数的时候,会销毁指针,那么线程就必须执行完队列里面的所有函数才可以退出。
望大家多多支持。
扩展一:一次执行一个函数或者多个函数,以两个为例,多个类似。因为有时候我们需要先后执行两个函数,对函数执行的顺序哟要求的时候
// 父类和上面一样,这里是没有数据库的情况 class TaskOperation : public BlockClass { public: virtual long operator ()(void) { return 0; } //private: // TaskOperation(); // 默认构造 // TaskOperation(const TaskOperation&); //复制构造 // TaskOperation& operator= (const TaskOperation&); // 等于重载 }; // 一次调用两个函数 template <typename Handler1, typename Handler> class TaskOperationBoost2 : public TaskOperation { public: TaskOperationBoost2(Handler1 h1, Handler h) : m_handler1(h1) , m_handler(h) { } virtual long operator ()(void) { m_handler1(); m_handler(); return 0; } private: TaskOperationBoost2(); // 默认构造 TaskOperationBoost2(const TaskOperationBoost2&); //复制构造 TaskOperationBoost2& operator= (const TaskOperationBoost2&); // 等于重载 Handler1 m_handler1; Handler m_handler; }; // 打包两个函数 template <typename Handler1, typename Handler> void OnIdleDone2(Handler1 h1, Handler h) { boost::shared_ptr<TaskOperationBoost2<Handler1, Handler> > ope(new TaskOperationBoost2<Handler1, Handler>(h1,h)); // 接下来把这个对象放入数据库线程队列 ....... } // 处理线程差不多,自己去完成。
扩展二:定时器调用
有时候,我们希望写一个函数,然后定时去调用它(一次,或者多次),但是每次写都要写定时器代码,能不能就一个函数调用搞定呢,能,当然能咯,哈哈,请看代码(基于boost)
// 父类,iTime是当前时间,秒数,函数可用,可不用 class Operation { public: virtual long operator ()(long iTime) { return -1; } //private: // Operation(); // 默认构造 // Operation(const Operation&); //复制构造 // Operation& operator= (const Operation&); // 等于重载 }; // 模板子类 template <typename Handler> class OperationBoost : public Operation { public: OperationBoost(Handler h) : m_handler(h) { } virtual long operator ()(long iTime) { return m_handler(iTime); } private: OperationBoost(); // 默认构造 OperationBoost(const OperationBoost&); //复制构造 OperationBoost& operator= (const OperationBoost&); // 等于重载 Handler m_handler; }; //定时处理,定时函数返回零,表示继续定时 inline void DoTimer(const boost::system::error_code& error, boost::shared_ptr<boost::asio::deadline_timer> pTimer, long iTime, boost::shared_ptr<Operation> ope) { if(!error) { if ((*ope)(GetTime()) == 0) { pTimer->expires_from_now(boost::posix_time::seconds(iTime)); pTimer->async_wait(boost::bind(DoTimer, boost::asio::placeholders::error, pTimer, iTime, ope)); } } else { } return ; } // 函数打包,get_io_service()得到boost::asio::io_service,需要外部实现 template <typename Handler> void OnHWNetTime(long iTime, Handler h) { boost::shared_ptr<OperationBoost<Handler> > ope(new OperationBoost<Handler>(h)); boost::shared_ptr<boost::asio::deadline_timer> pTimer; pTimer.reset(new boost::asio::deadline_timer(get_io_service(), boost::posix_time::seconds(iTime))); pTimer->async_wait(boost::bind(DoTimer, boost::asio::placeholders::error, pTimer, iTime, boost::dynamic_pointer_cast<Operation>(ope))); } // 应用,比如,我有如下函数 long OnTimeA(){......} long OnTimeB(long iTime){......} //我们这样调用(1秒一次的话) OnHWNetTime(1, boost::bind(OnTimeA)); OnHWNetTime(1, boost::bind(OnTimeB, _1));