// This autogenerated skeleton file illustrates how to build a server.
// You should copy it to another filename to avoid overwriting it.
#include "match_server/Match.h"
#include <thrift/protocol/TBinaryProtocol.h>
#include <thrift/server/TSimpleServer.h>
#include <thrift/transport/TServerSocket.h>
#include <thrift/transport/TBufferTransports.h>
#include <iostream>
using namespace ::apache::thrift;
using namespace ::apache::thrift::protocol;
using namespace ::apache::thrift::transport;
using namespace ::apache::thrift::server;
using namespace ::match_service;
using namespace std;
class MatchHandler : virtual public MatchIf {
public:
MatchHandler() {
// Your initialization goes here
}
int32_t add_user(const User& user, const std::string& info) {
// Your implementation goes here
printf("add_user\n");
return 0;
}
int32_t remove_user(const User& user, const std::string& info) {
// Your implementation goes here
printf("remove_user\n");
return 0;
}
};
int main(int argc, char **argv) {
int port = 9090;
::std::shared_ptr<MatchHandler> handler(new MatchHandler());
::std::shared_ptr<TProcessor> processor(new MatchProcessor(handler));
::std::shared_ptr<TServerTransport> serverTransport(new TServerSocket(port));
::std::shared_ptr<TTransportFactory> transportFactory(new TBufferedTransportFactory());
::std::shared_ptr<TProtocolFactory> protocolFactory(new TBinaryProtocolFactory());
TSimpleServer server(processor, serverTransport, transportFactory, protocolFactory);
cout << "Start Match Server" << endl;
server.serve();
return 0;
}
以上是服务端函数,serve是生成者,不断生产数据,我们要实现一个消费者,不断去消费数据。二者之间的通讯使用消息队列实现,这里可以用C++ queue加锁和条件变量,手写实现。任务以及消息队列的定义如下:
struct Task
{
User user;
string type;
};
struct MessageQueue
{
queue<Task> q;
mutex m;
condition_variable cv;
}message_queue;
对于serve接口,将task入队。同时记得加锁以及唤醒线程
class MatchHandler : virtual public MatchIf {
public:
MatchHandler() {
// Your implementation goes here
printf("add_user\n");
unique_lock<mutex> lck(message_queue.m);
message_queue.q.push({user, "add"});
message_queue.cv.notify_all();
return 0;
}
// Your implementation goes here
printf("remove_user\n");
unique_lock<mutex> lck(message_queue.m);
message_queue.q.push({user, "remove"});
message_queue.cv.notify_all();
return 0;
}
};
消费者线程的逻辑如下:
void consume_task()
{
while (true)
{
unique_lock<mutex> lck(message_queue.m);
if (message_queue.q.empty())
{
message_queue.cv.wait(lck);
}
else
{
auto task = message_queue.q.front();
message_queue.q.pop();
lck.unlock();
if (task.type == "add") pool.add(task.user);
else if (task.type == "remove") pool.remove(task.user);
pool.match();
}
}
}
在通过创建一个匹配池来做匹配操作。对于匹配操作,我们先实现一个naive的版本。
class Pool
{
public:
void save_result(int a, int b)
{
printf("Match Result: %d %d\n", a, b);
}
void match()
{
while (users.size() > 1)
{
auto a = users[0], b = users[1];
users.erase(users.begin());
users.erase(users.begin());
save_result(a.id, b.id);
}
}
void add(User user)
{
users.push_back(user);
}
void remove(User user)
{
for (uint32_t i = 0; i < users.size(); i ++ )
if (users[i].id == user.id)
{
users.erase(users.begin() + i);
break;
}
}
private:
vector<User> users;
}pool;