竞赛模式

1.模式介绍

角色:多个竞赛者,一个裁判
动机:多个竞赛者进行同样的事情(竞赛项目),选出最早完成的参赛者。
实现:
.支持排名和选拔两种赛制
.隐式裁判
.选拔不支持多选(只支持选择最快的)
应用: 
  .本地服务器直接连接时,如果托管服务器有2个ISP,则访问者可以从这2个ISP选择一个较快的网络连接。

  .可应用于并行应用情形,如加载托管机构证书时利用此模式可提高启动速度

 

2.实现

     typedef int (*GAME_TASK_FUNC)(void *arg); ///< 比赛任务函数

    class CGame;
    class CPlayer {
        friend class CGame;
        friend DWORD WINAPI player_entry_func(void *arg);

        CGame *game_;
        int i_id_; ///< 内部编号

        void *arg_; ///< 任务函数参数

        HANDLE fini_signal_; ///< 任务完成信号
        HANDLE thr_handle_;        ///<  线程句柄

        int result_; ///< 任务执行结果

        int rank_;///< 名次: 0-无名次
        int run();///< 比赛开始
    public:
        CPlayer(void *arg);
        ~CPlayer();
        CGame* get_game() { return game_; }
        ///< 参加比赛
        void join(CGame *game) { game_ = game; }
        ///< 预备
        int ready();
        ///< (中途)结束
        void exit();
        ///< 比赛完成
        void notify_fini(); ///< 比赛完成通知

        int get_iid() const { return i_id_; }
        int get_rank() const { return rank_; }
        void* get_arg() const { return arg_; }
    };

    /// 竞赛项目
    class CGame {
        friend class CPlayer;
        friend DWORD WINAPI player_entry_func(void *arg);
    public:
        enum GAME_TYPE { GT_RANKD=1,GT_CTB}; ///< 比赛类型:排名,选拔
    private:
        GAME_TASK_FUNC task_func_;///< 比赛项目任务

        HANDLE signal_; ///< 发令(比赛开始信号)
        int type_; ///< 1-排名(所有选手完成的顺序) 2-选拔(选择最快的一个)

        vector<CPlayer*> players_;

        int rank_count_;  ///< 当前名次
        CRITICAL_SECTION lock_; ///< rank_count_锁

        void rank(int iid); ///< 某个选手完成项目后定名次
    public:
        CGame();
        virtual ~CGame();
        void set_type(int type) { type_ = type;}
        void set_task(GAME_TASK_FUNC fp) { task_func_ = fp; }
        void add_player(CPlayer *player); ///< 加入选手
        size_t get_player_num() const { return players_.size();}
        CPlayer* get_player(size_t index) { return players_[index];}

        int start(); ///< 比赛开始
        void report(); ///< 报告比赛结果

        CPlayer* find(int rank,int result); ///< 查询名次
    };
    template <class  T> int HoldGame(short game_type,GAME_TASK_FUNC fp,T *player_info,size_t player_num) {
        CGame *game = new CGame;
        game->set_type(game_type);
        game->set_task(fp);
        for (int i=0;i<player_num;i++) {
            T *playinfo = &player_info[i];
            CPlayer *player = new CPlayer(playinfo);
            game->add_player(player);
        }
        game->start();

        CPlayer *winner = game->find(1,0);
        int winner_index = winner==0 ? -1 : winner->get_iid();
        delete game;

        return winner_index;
    }

 

 

3.应用示例

以下示例应用竞赛模式在多ISP时选择网络。

.TestNetSpeed是竞赛任务函数:执行连接,发送消息并获取一个响应消息

.TestSpeed是实现多ISP选择的执行函数

 

 

#include "compete.h"

using namespace sens;

 

int TestNetSpeed(void *arg) {
    SvcEntry *entry = (SvcEntry*)arg;
    const char *bind_addr = CAPPlugin::instance()->central_server_.sw_bind_ip_.empty() ? 0 : CAPPlugin::instance()->central_server_.sw_bind_ip_.c_str();
    SOCKET handle = Connect(entry,bind_addr);
    if (handle==INVALID_SOCKET)
        return -1;
    CMsg *req = new CMsg;
    req->SetMsgType(MT_REQUEST);
    req->SetMsgID(312);
    req->AddParam("bp",(long)clock());
    if (Send(handle,req)) {
        return -1;
    }
    CMsg *ans = 0;
    if (Recv(handle,&ans)) {
        return -2;
    }
    ans->Release();

    return 0;
}

int TestSpeed(SvcEntry *entry_list,short entry_num) {
    return HoldGame<SvcEntry>(2,TestNetSpped,entry_list,entry_num);
}

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值