代码拉取完成,页面将自动刷新
#ifndef __M_MATCHER_M__
#define __M_MATCHER_M__
#include "util.hpp"
#include "online.hpp"
#include "db.hpp"
#include "room.hpp"
#include <list>
#include <mutex>
#include <condition_variable>
template <class T>
class match_queue
{
private:
// 这里挖煤使用的是链表,不用队列,因为挖煤存在删除中间元素的可能
std::list<T> _list;
// 实现线程安全
std::mutex _mutex;
// 设置条件变量的目的是为阻塞消费者,当队列中元素<2阻塞
std::condition_variable _cond;
public:
// 获取元素
int size()
{
std::unique_lock<std::mutex> lock(_mutex);
return _list.size();
}
// 判断是否为空
bool empty()
{
std::unique_lock<std::mutex> lock(_mutex);
return _list.empty();
}
// 阻塞线程
void wait()
{
std::unique_lock<std::mutex> lock(_mutex);
_cond.wait(lock);
}
// 队列入数据并且唤醒线程
void push(const T &data)
{
std::unique_lock<std::mutex> lock(_mutex);
_list.push_back(data);
_cond.notify_all();
}
// 出队列
bool pop(T &data)
{
std::unique_lock<std::mutex> lock(_mutex);
if (_list.empty() == true)
{
return false;
}
data = _list.front();
_list.pop_front();
return true;
}
// 移除指定数据
void remove(T &data)
{
std::unique_lock<std::mutex> lock(_mutex);
_list.remove(data);
}
};
// 匹配
class match
{
private:
// 普通队列
match_queue<uint64_t> _q_normal;
// 高手队列
match_queue<uint64_t> _q_high;
// 大神队列
match_queue<uint64_t> _q_super;
// 对应三个线程管理队列
std::thread _th_normal;
std::thread _th_high;
std::thread _th_super;
// 房间管理,数据库和用户在线管理句柄
room_manager *_rm;
user_table *_ut;
online_manager *_om;
private:
void handle_match(match_queue<uint64_t> &mq)
{
while (1)
{
// 1、判断队列人数<2,阻塞等待
while (mq.size() < 2)
{
mq.wait();
}
// 2、人数够2人,出队列
uint64_t uid1, uid2;
bool ret = mq.pop(uid1);
if (ret == false)
{
continue;
}
ret = mq.pop(uid2);
if (ret == false)
{
this->add(uid1);
continue;
}
// 3、检验是否有玩家掉线,如果有一人掉线将其中一个人重新加入到队列中
wsserver_t::connection_ptr conn1 = _om->get_conn_from_hall(uid1);
if (conn1.get() == nullptr)
{
this->add(uid2);
continue;
}
wsserver_t::connection_ptr conn2 = _om->get_conn_from_hall(uid2);
if (conn2.get() == nullptr)
{
this->add(uid1);
continue;
}
// 4、为两个玩家创建房间,并将玩家加入房间中
room_ptr rp = _rm->create_room(uid1, uid2);
if (rp.get() == nullptr)
{
this->add(uid1);
this->add(uid2);
continue;
}
// 5、对玩家进行响应
Json::Value resp;
resp["optype"] = "match_success";
resp["result"] = true;
std::string body;
json_util::serialize(resp, body);
conn1->send(body);
conn2->send(body);
}
}
void th_normal_entry() { return handle_match(_q_normal); }
void th_high_entry() { return handle_match(_q_high); }
void th_super_entry() { return handle_match(_q_super); }
public:
match(room_manager *rm, user_table *ut, online_manager *om)
: _rm(rm), _ut(ut), _om(om),
_th_normal(std::thread(&match::th_normal_entry, this)),
_th_high(std::thread(&match::th_high_entry, this)),
_th_super(std::thread(&match::th_super_entry, this))
{
DLOG("游戏匹配模块初始化完毕....");
}
bool add(uint64_t uid)
{
// 根据不同天梯分数,入不同队列
// 1、获取用户信息,通过ID
Json::Value user;
bool ret = _ut->select_by_id(uid, user);
if (ret == false)
{
DLOG("获取玩家:%d 信息失败!!", uid);
return false;
}
int score = user["score"].asInt();
// 2、添加入指定队列
if (score < 2000)
{
_q_normal.push(uid);
}
else if (score > 2000 && score < 3000)
{
_q_high.push(uid);
}
else
{
_q_super.push(uid);
}
return true;
}
bool del(uint64_t uid)
{
Json::Value user;
bool ret = _ut->select_by_id(uid, user);
if (ret == false)
{
DLOG("获取玩家:%d 信息失败!!", uid);
return false;
}
int score = user["score"].asInt();
// 2. 添加到指定的队列中
if (score < 2000)
{
_q_normal.remove(uid);
}
else if (score >= 2000 && score < 3000)
{
_q_high.remove(uid);
}
else
{
_q_super.remove(uid);
}
return true;
}
};
#endif
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。