using namespace std;
using namespace muduo;
ChatService* ChatService::instance(){
static ChatService service;
return &service;
}
//注册消息以及对应的回调操作
ChatService::ChatService(){
_msgHanderMap.insert({LOGIN_TYPE,std::bind(&ChatService::login,this,_1,_2,_3)});
_msgHanderMap.insert({REG_TYPE,std::bind(&ChatService::reg,this,_1,_2,_3)});
···
}
//获取存储消息id和对应的处理方法
MsgHandler ChatService::getHandle(int msgid){
//日志记录
auto it = _msgHanderMap.find(msgid);
if(it == _msgHanderMap.end()){
//返回一个lambda表达式,返回一个默认的空处理器,防止业务挂掉,后可做平滑升级处理
return [=](const TcpConnectionPtr &conn,json &js,Timestamp time){
LOG_ERROR<<“msgid:”<<msgid<<“can not find handle!”;
};
}
else{
return _msgHanderMap[msgid];
}
}
void ChatService::login(const TcpConnectionPtr &conn,json &js,Timestamp time){
int id = js[“id”].get();
string pwd = js[“password”];
User user = _usermodel.query(id);
if (user.getID() == id && user.getpassword() == pwd)
{
if (user.getstate() == “online”)
{
// 该用户已经登录,不允许重复登录
json response;
response[“msgid”] = LOGIN_MSG_ACK;
response[“errno”] = 2;
response[“errmsg”] = “this account is using, input another!”;
conn->send(response.dump());
}
else
{
//添加作用域,限制锁的粒度
{
lock_guard lock(_connMutex);
//记录用户连接
_userConnMap.insert({id,conn});
}
// 登录成功,更新用户状态信息 state offline=>online
user.setstate(“online”);
_usermodel.updateState(user); // !!! Single stepping until exit from function _IO_default_xsputn,
json response;
response[“msgid”] = LOGIN_MSG_ACK;
response[“errno”] = 0;
response[“id”] = user.getID();
response[“name”] = user.getname();
//查询用户是否有离线消息
vector vecofflinemsg = _offlineMsgmodel.query(id);
if(!vecofflinemsg.empty()){
response[“offlinemsg”] = vecofflinemsg;
//清空离线消息
_offlineMsgmodel.remove(id);
}
vector uservec = _friendmodel.query(id);
if(!uservec.empty()){
vector vecfriend;
for(User &user:uservec){
json js;
js[“id”] = user.getID();
js[“name”] = user.getname();
js[“state”] = user.getstate();
vecfriend.push_back(js.dump());
}
response[“friends”] = vecfriend;
}
conn->send(response.dump());
}
}
else
{
// 该用户不存在,用户存在但是密码错误,登录失败
json response;
response[“msgid”] = LOGIN_MSG_ACK;
response[“errno”] = 1;
response[“errmsg”] = “id or password is invalid!”;
conn->send(response.dump());
}
}
void ChatService::reset(){
//把所有online状态的用户转为offline
_usermodel.resetstate();
}
为什么要设置单例
难道单例就只能拿来保证对象的单一性吗?
如果是为了保证对象的单一性,那取对象的时候就应该上个锁了,甚至是像“懒汉”那样上两个锁了。
在网络模块儿中,是这么写的:
void ChatServer::onMessage(const TcpConnectionPtr &conn, Buffer *buff, Timestamp time){
···
//通过msgid获取业务回调,进行网络模块和任务模块之间的解耦合
auto msgHandler = ChatService::instance()->getHandle(js[“msgid”].get());
//回调消息绑定好的事件处理器,执行相应的业务处理
msgHandler(conn,js,time);
···
就取个任务的事情,任务取完就甩手给channel去办事儿了。
难道每次我来取个任务还要 new 一下吗?
那为什么不在ChatServer里面放一个Chatservice chatservice_
对象呢?
那为什么就非要加上这么一层耦合呢?
MsgHandler 的设计
//通过msgid获取业务回调,进行网络模块和任务模块之间的解耦合
auto msgHandler = ChatService::instance()->getHandle(js[“msgid”].get());
//回调消息绑定好的事件处理器,执行相应的业务处理
msgHandler(conn,js,time);
_msgHanderMap.insert({LOGIN_TYPE,std::bind(&ChatService::login,this,_1,_2,_3)});
_msgHanderMap.insert({REG_TYPE,std::bind(&ChatService::reg,this,_1,_2,_3)});
//获取存储消息id和对应的处理方法
MsgHandler ChatService::getHandle(int msgid)
{
auto it = _msgHanderMap.find(msgid);
if(it == _msgHanderMap.end()){
//返回一个lambda表达式,返回一个默认的空处理器,防止业务挂掉,后可做平滑升级处理
return [=](const TcpConnectionPtr &conn,json &js,Timestamp time){
LOG_ERROR<<“msgid:”<<msgid<<“can not find handle!”;
};
}
else{
return _msgHanderMap[msgid];
最后
很多程序员,整天沉浸在业务代码的 CRUD 中,业务中没有大量数据做并发,缺少实战经验,对并发仅仅停留在了解,做不到精通,所以总是与大厂擦肩而过。
我把私藏的这套并发体系的笔记和思维脑图分享出来,理论知识与项目实战的结合,我觉得只要你肯花时间用心学完这些,一定可以快速掌握并发编程。
不管是查缺补漏还是深度学习都能有非常不错的成效,需要的话记得帮忙点个赞支持一下
整理不易,觉得有帮助的朋友可以帮忙点赞分享支持一下小编~