支持HW团队,就支付宝领取下面的红包吧!(2018年3月31前,就几毛,也会几块,可以和其他红包叠加使用),你领取消费,HW有奖励。红包使用无条件限制,有条件请注意是不是有病毒。

小伙伴们,给大家发红包喽!人人可领,领完就能用。祝大家领取的红包金额大大大!#吱口令#长按复制此消息,打开支付宝就能领取!er1OEj73Uj

登入 注册 | 验证
| 搜索
HelloWorld论坛 : > 计算机科学、技术、教学> 编程专题> c++库(STL、boost)> [原创]函数调度代替数据调度 boost::bind的应用
 
 
 
 
类别:c++ 阅读:6228 评论:0 时间:七月 24, 2012, 4:51 a.m. 关键字:bind boost 函数调度

 

望大家多支持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));

 

相关博文 首页 上页 6 7 8 9 10 11 下页 尾页 共11条
[挂载人]初学MPEG [审核人]初学MPEG

个人签名--------------------------------------------------------------------------------

Please Login (or Sign Up) to leave a comment