简单够用的设计

   在前面的几篇博客中,我探讨过消息队列的设计和定时器的设计,可以说在这方面下了很多功夫,做了很多参考,当然也写了很多测试。

      就拿消息队列来说吧,为了更好的吞吐量,更加快速的相应,我再减少加锁粒度,减少加锁频率方面做了不少工作;曾经设计了一个三个队列作为缓冲的TripleList(参考博文消息队列),原理为:一个读队列,一个写队列,一个缓冲队列,三个队列分别用数组形式体现,枷锁只要保证缓冲队列一致既可,即写队列向缓冲队列提交数据的时候,需要枷锁,读队列再向缓冲队列交换数据的时候,需要枷锁!可是在消息很少的时候,需要主动的将写队列同步到缓冲队列中;后来利用条件变量和读写锁相结合做了一个基于条件变量的消息队列,效率也不错,只不过需要在读取的时候比较麻烦,需要做一次一毫秒延迟的同步。

      昨天忽然心血来潮,决定从新设计,只要保证性能,并且使用简单,于是消息队列编程了这个样子:

#ifndef DUPLEXQUEUE_H_
#define DUPLEXQUEUE_H_

#include <pthread.h>

#include <list>

#include "Mutex.h"

typedef void* CommonItem;

class DuplexQueue
{
public:
    DuplexQueue();

    virtual ~DuplexQueue();

    int append(CommonItem item);

    std::list<CommonItem>* serial_read(std::list<CommonItem>* list);

private:
    std::list<CommonItem> _write_list;
    Mutex _write_mutex;
};

#endif /* DUPLEXQUEUE_H_ */

#include <DuplexQueue.h>

DuplexQueue::DuplexQueue()
{
    this->_write_list.clear();
}

DuplexQueue::~DuplexQueue()
{

}

int DuplexQueue::append(CommonItem item)
{
    Auto_Mutex  auto_mutex(this->_write_mutex);
    this->_write_list.push_back(item);
    return 0;
}

std::list<CommonItem>* DuplexQueue::serial_read(std::list<CommonItem>* list)
{
    Auto_Mutex auto_mutex(this->_write_mutex);
    std::swap(this->_write_list,*list);
    return list;
}

     其实只需要不足百余行代码就足以实现一个性能不错的消息队列,而且在使用上也很简单,不必担心写同步问题,不必担心读同步。使用方法:

std::list<void*> list_to_process;

    this->_recv_db_msgqueue->serial_read(&list_to_process);
    JUDGE_RETURN(!list_to_process.empty(),0);

    for(std::list<void*>::iterator iter = list_to_process.begin();iter != list_to_process.end();
            iter ++)
    {
        //do something
    }

     当然这个只是作为一个1:N的设计,如果需要可以将writelist作为交换switchlist,做成m:n的设计;将自己的writelist追加到switchlist中,只要追加的时候加锁就可以保证同步的问题!

 

     我们再看下定时器的设计,在两篇博客里面有体现,一篇是定时器的设计,另一篇是stl优先级队列,前者在效率上存在一定的问题,因为每次都是遍历定时器。后者在效率上不存在问题,只是在删除上存在诸多不足,删除要遍历所有。参考了陈硕老师的设计,并且灵活运用了std::set,将定时器设计成这样子:

     首先是Timer的设计:

#ifndef TIMER_H_
#define TIMER_H_

#include "GameDefine.h"

using namespace std;

class Timer
{
public:

    Timer();

    virtual ~Timer();

    virtual VOID open(int sec);

    /**
     * Call to change the timer's interval.
     * @a sec represents the new interval
     */
    virtual int schedule_timer(INT sec,INT usec = 0);

    // 重新设置计时器
    virtual VOID set_timer(INT sec);

    VOID register_timer();

    VOID cancel_timer();

    /**
     * Called when timer expires.  @a current_time represents the current
     * time that the Event_Handler was selected for timeout
     * dispatching and @a act is the asynchronous completion token that
     * was passed in when <schedule_timer> was invoked.
     */
    virtual INT handle_timeout(const LONG ¤t_time,const VOID *act = 0);

    bool operator < (Timer _timer)
    {
        return this->_expires_time < _timer._expires_time;
    }

    bool operator == (Timer _timer)
    {
        return _timer._expires_time == this->_expires_time;
    }

    LONG interval()
    {
        return this->_interval;
    }

    LONG get_expires_time()
    {
        return this->_expires_time;
    }

    VOID set_expires_time(LONG usec)
    {
        this->_expires_time = usec;
    }

    BOOL valid() const
    {
        return this->_valid;
    }

private:

    LONG _interval;
    LONG _now;
    LONG _expires_time;

    BOOL _valid;        // 是否有效

};

#endif /* TIMER_H_ */

Timer::Timer()
{
    this->_valid = false;
}

Timer::~Timer()
{

}

VOID Timer::open(int sec)
{

}

VOID Timer::set_timer(INT sec)
{

}

int Timer::schedule_timer(INT sec,INT usec)
{
    this->_now = get_os_system_time();
    this->_interval = sec * 1000;
    this->_expires_time = _now + _interval;
    return 0;
}

INT Timer::handle_timeout(const LONG ¤t_time,const VOID *act )
{
    return 0;
}

VOID Timer::register_timer()
{
    this->_valid = true;
}

VOID Timer::cancel_timer()
{
    this->_valid = false;
}

     TimerQueue的设计:

#ifndef TIMERQUEUE_H_
#define TIMERQUEUE_H_

#include <set>
class Timer;

class TimerQueue
{
public:
    typedef std::pair<long,Timer*> ACTIVETIMER;
    TimerQueue();
    virtual ~TimerQueue();

    virtual int add_timer(Timer* timer);
    virtual int cancel_timer(Timer* timer);
    virtual std::vector<ACTIVETIMER> process_expire();

private:
    std::set<ACTIVETIMER> _timer_queue;
};

#endif /* TIMERQUEUE_H_ */

#include "Timer.h"
#include <TimerQueue.h>
#include "GameUtil.h"
#include "GameStruct.h"

TimerQueue::TimerQueue()
{

}

TimerQueue::~TimerQueue()
{

}

int TimerQueue::add_timer(Timer* timer)
{
    JUDGE_RETURN(timer!=NULL,-1);
    this->_timer_queue.insert(std::make_pair(timer->get_expires_time(),timer));
    return 0;
}

int TimerQueue::cancel_timer(Timer* timer)
{
    JUDGE_RETURN(timer!=NULL,-1);
    ACTIVETIMER antry(timer->get_expires_time(),timer);

    std::set<ACTIVETIMER>::iterator iter = this->_timer_queue.find(antry);
    if(iter != this->_timer_queue.end())
    {
        this->_timer_queue.erase(iter);
    }
    return 0;
}

std::vector<TimerQueue::ACTIVETIMER> TimerQueue::process_expire()
{
    long now = get_os_system_time();
    std::vector<ACTIVETIMER> expired;
    ACTIVETIMER antry(now,NULL);
    std::set<ACTIVETIMER>::iterator end = this->_timer_queue.upper_bound(antry);

    std::copy(this->_timer_queue.begin(),end,back_inserter(expired));
    this->_timer_queue.erase(this->_timer_queue.begin(),end);

    return expired;
}

     测试代码:

TimerQueue _queue;

class TestTimer : public Timer
{
public:
    virtual INT handle_timeout(const LONG ¤t_time,const VOID *act = 0)
    {
        printf("interval:%d,timer expired\n",(int)this->interval());
        return this->schedule_timer(this->interval()/1000,0);
    }
};

int main(int argc,char** argv)
{
    TestTimer timer[100];
    for(int i = 1;i<100 ;i++)
    {
        timer[i].schedule_timer(i,0);
        _queue.add_timer(&timer[i]);
    }
    while(true)
    {
        std::vector<TimerQueue::ACTIVETIMER> expired = _queue.process_expire();
        for(std::vector<TimerQueue::ACTIVETIMER>::iterator iter = expired.begin();
                iter != expired.end();
                iter ++)
        {
            iter->second->handle_timeout(0,NULL);
            _queue.add_timer(iter->second);
        }
    }
        return 0;
}

   这个定时器的设计不仅解决了性能的问题,再使用起来也比较方便。

     

     在设计一些基础组件的时候,确实是不应该因为性能作为第一标准,而是应该将易用考虑进来。比如很多选择linux+C++作为服务器的设计,可是有没有考虑过开发的需求,难道每个开发者都要用一台win作为办公机器,再用一个linux作为开发机器? 为什么不退而求其次,用java考虑;或者将Xmanager和虚拟机引入,这样保证保证一台电脑一个员工办公开发两不误,而且保证了成本!

时间: 2024-08-31 11:32:01

简单够用的设计的相关文章

利用简单的线条设计充满典雅风格的封面

[译者的话] 如何仅仅利用简单的线条设计一个充满典雅风格的封面?在版面上如何放置多张图片?在一张大图片上加上多个说明文字区域,出来的效果永远吸引人.如何将你公司枯燥的产品名称变得更加吸引?如何通过矩形区域元素来制作一个漂亮的网页?让我们一起继续杂谈! 原文出处:www.bamagazine.com 图片:线条构成文件 用线条(技术上说,是一条线)描绘的元素可以传达出非常漂亮或电子信息感的印象,它可以将复杂的图片简化,并将本来平淡的元素变得有趣.对于一些原来缺乏冲击力的图片,这样处理是一种非常不错

交互设计分析:紧紧围绕简单进行交互设计

文章描述:交互设计分析:紧紧围绕简单进行交互设计. 交互设计是近几年流行的一个词语.现在市场上有许多资料来介绍什么是交互设计,如何做交互设计等.从场景,任务,用户,操作等分析.但由于受实际情况的限制,往往不能很深入.所以笔者结合实际工作体验与大家分享下,具体做设计时候是怎么考虑的.如果要说什么是一个好的交互设计,个人浅见就是简单.本文以下内容都是围绕简单2字进行展开. 简单在本文中包括认知和操作两个部分: 1. 认知主要是指人的思维过程,本文中主要说明用户是如何做决定的: 2. 操作在本文中说明

流程图-简单算法分析与设计问题求解

问题描述 简单算法分析与设计问题求解 解决方案 第一题, 本质就是求最短路径, 可以参考Dijkstra算法来解决这道题 第二题, 就是背包问题, 只是换了个题目形式, 你可以参考背包问题, 和这道题是一样的...

arm-基于ARM7简单示波器的设计 求大神给个keil程序和protuse仿真电路

问题描述 基于ARM7简单示波器的设计 求大神给个keil程序和protuse仿真电路 四. 正弦波示波器:在**LPC2138** AD0端输入一个**0-3V/200Hz**的正弦波,采**100点**,将波形显示在LCD上,采样频率可以调节.完成相关硬件的设计与制作,显示器**12864点阵型LCD**.扩充:显示当前采样频率,峰峰值,有效值.LPC2138 AD0 解决方案 http://www.pudn.com/downloads367/sourcecode/embedded/deta

代码-一个很简单的界面设计问题。不知道具体的界面逻辑。

问题描述 一个很简单的界面设计问题.不知道具体的界面逻辑. 要求当点击下面的四个按钮时弹出新窗口(我用的push),但是push出来的默认带leftitem返回嘛,可是我的不带.不知道是不是viewcontroller写的逻辑问题. 我是把rootviewcontroller设置成UINavigationController,appdelegate代码如下 - (BOOL)application:(UIApplication *)application didFinishLaunchingWit

八个简单的图片设计技巧

译者的话:如何让一张普通的图片变得更加有力量?如何有意识地引导读者的眼睛去到图片的某一区域? 如何更加有效地传达你的对象?八个简单的设计技巧,让你轻松容易完成任务.在图片创造焦点,也让你的图片获得了新生. 原文出处:www.bamagazine.com 一:模糊背景

移动设备上简单交互的设计解决方案和展示

用户访问移动网站不仅仅是为了浏览内容,而是要做成事情.以订机票为例,用户经常在航空公司的移动网站上做的事有:查询航班状态.查询特定航班.搜索并预定机票.那么移动互联网用户界面设计是怎样支持任务完成呢?在移动网站上传达信息和展示交互状态的最优方式又是怎样?带着寻找移动设备简单交互的最有设计方案的目的,我以查询航班状态为例来进行研究.希望我的分析能对这个主题有所贡献. 交互:查询航班状态 旅行者可以通过确定出发日期,或者是输入航班号,或者是出发城市和到达城市或是机场来查询到航班状态.听起来够简单,对

3个简单的UI设计技巧

  我将为大家带来3种非常简单实用的UI设计技巧,这些技术和处理像素有关,只是简单地操作像素来使你的UI设计变得突出,但现在很多现代的设计潮流都经常使用这些技术,它确实有着不错的效果.它为设计带来了更加立体和触手可及的感觉. 1.像素阴影 像素阴影的UI设计技术实现起来非常简单,就是为图像增加一个像素的硬边投影.简单来说,就是在Photoshop的图层混合选项里选择投影,并将尺寸(Size)设为0,将距离(Distance)设为1px.由于只有1个像素的阴影,设计上不会给人过度使用的感觉. 2.

如何进行简单的网站设计

  首先我们要清楚一点,的网站设计并不难,当然看你出于什么目的,好多网络新手认为建站是一件挺复杂,需要很多技术的事.其实,想做完全属于自己的网站很简单,不需要学asp.php之类玩意,也不需要会dreamwear这个害死初学者的东西. 想做自己的网站,就需要了解以下概念:空间.域名.ftp.独立建站程序.模板和网站的区别. 如果拿建网站和租个临街商铺做生意来比较:空间就是租的店铺.域名就是档位号.独立建站程序是内部装修 构架--卖衣服的店子和卖化妆品的店子的装修是不一样的. 在网络繁华的时代,现