future
This commit is contained in:
@@ -14,11 +14,6 @@ public:
|
|||||||
|
|
||||||
template<typename _Callable>
|
template<typename _Callable>
|
||||||
void init(_Callable _IOCPClient) {
|
void init(_Callable _IOCPClient) {
|
||||||
roomNames_ = std::future<std::unordered_map<Snowflake, std::string>>();
|
|
||||||
findRoomId_ = std::future<std::unordered_map<std::string, Snowflake>>();
|
|
||||||
userNames_ = std::future<std::unordered_map<Snowflake, std::string>>();
|
|
||||||
findUserId_ = std::future<std::unordered_map<std::string, Snowflake>>();
|
|
||||||
|
|
||||||
auto config = ConfigManager::load();
|
auto config = ConfigManager::load();
|
||||||
log::setDefaultLogger(config.logLevel, config.logFileName, config.logfileSize, config.logfileCount);
|
log::setDefaultLogger(config.logLevel, config.logFileName, config.logfileSize, config.logfileCount);
|
||||||
threadPool_.init(0);
|
threadPool_.init(0);
|
||||||
@@ -102,11 +97,11 @@ private:
|
|||||||
std::queue<std::string> messageQueue_;
|
std::queue<std::string> messageQueue_;
|
||||||
std::vector<std::string> messageHistory_;
|
std::vector<std::string> messageHistory_;
|
||||||
|
|
||||||
std::future<std::unordered_map<Snowflake, std::string>> roomNames_;
|
std::unordered_map<Snowflake, std::string> roomNames_;
|
||||||
std::future<std::unordered_map<std::string, Snowflake>> findRoomId_;
|
std::unordered_map<std::string, Snowflake> findRoomId_;
|
||||||
|
|
||||||
std::future<std::unordered_map<Snowflake, std::string>> userNames_;
|
std::unordered_map<Snowflake, std::string> userNames_;
|
||||||
std::future<std::unordered_map<std::string, Snowflake>> findUserId_;
|
std::unordered_map<std::string, Snowflake> findUserId_;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -181,34 +181,11 @@ void ClientManager::processRoomExitResponsePacket(RoomExitResponsePacket roomExi
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ClientManager::processUsersListResponsePacket(UsersListResponsePacket usersListResponsePacket, Chattr::IOCPPASSINDATA* data) {
|
void ClientManager::processUsersListResponsePacket(UsersListResponsePacket usersListResponsePacket, Chattr::IOCPPASSINDATA* data) {
|
||||||
std::unordered_map<Snowflake, std::string> userNames;
|
|
||||||
|
|
||||||
if (userNames_.valid() && userNames_.wait_for(std::chrono::seconds(0)) == std::future_status::ready)
|
|
||||||
userNames = userNames_.get();
|
|
||||||
else
|
|
||||||
userNames = std::unordered_map<Snowflake, std::string>();
|
|
||||||
|
|
||||||
auto userNamesPromise = std::promise<std::unordered_map<Snowflake, std::string>>();
|
|
||||||
userNames_ = userNamesPromise.get_future();
|
|
||||||
|
|
||||||
std::unordered_map<std::string, Snowflake> findUserId;
|
|
||||||
|
|
||||||
if (findUserId_.valid() && findUserId_.wait_for(std::chrono::seconds(0)) == std::future_status::ready)
|
|
||||||
findUserId = findUserId_.get();
|
|
||||||
else
|
|
||||||
findUserId = std::unordered_map<std::string, Snowflake>();
|
|
||||||
|
|
||||||
auto findUserIdPromise = std::promise<std::unordered_map<std::string, Snowflake>>();
|
|
||||||
findUserId_ = findUserIdPromise.get_future();
|
|
||||||
|
|
||||||
Snowflake userId;
|
Snowflake userId;
|
||||||
::memcpy(&userId.snowflake, usersListResponsePacket.__data.userId, sizeof(Snowflake));
|
::memcpy(&userId.snowflake, usersListResponsePacket.__data.userId, sizeof(Snowflake));
|
||||||
std::string userName((char*)usersListResponsePacket.__data.name, usersListResponsePacket.__data.packetLength - (sizeof(std::uint16_t) * 7));
|
std::string userName((char*)usersListResponsePacket.__data.name, usersListResponsePacket.__data.packetLength - (sizeof(std::uint16_t) * 7));
|
||||||
userNames[userId] = userName;
|
userNames_[userId] = userName;
|
||||||
findUserId[userName] = userId;
|
findUserId_[userName] = userId;
|
||||||
|
|
||||||
userNamesPromise.set_value(userNames);
|
|
||||||
findUserIdPromise.set_value(findUserId);
|
|
||||||
|
|
||||||
spdlog::info("{}", userName);
|
spdlog::info("{}", userName);
|
||||||
}
|
}
|
||||||
@@ -216,8 +193,7 @@ void ClientManager::processUsersListResponsePacket(UsersListResponsePacket users
|
|||||||
void ClientManager::processDataPostPacket(DataPostPacket dataPostPacket, IOCPPASSINDATA* data) {
|
void ClientManager::processDataPostPacket(DataPostPacket dataPostPacket, IOCPPASSINDATA* data) {
|
||||||
Snowflake sentUserId;
|
Snowflake sentUserId;
|
||||||
::memcpy(&sentUserId.snowflake, dataPostPacket.__data.destId, sizeof(Snowflake));
|
::memcpy(&sentUserId.snowflake, dataPostPacket.__data.destId, sizeof(Snowflake));
|
||||||
auto UNames = userNames_.get();
|
std::string sentUserName = userNames_[sentUserId];
|
||||||
std::string sentUserName = UNames[sentUserId];
|
|
||||||
std::string message((char*)dataPostPacket.__data.data, dataPostPacket.__data.packetLength - (sizeof(std::uint16_t) * 5));
|
std::string message((char*)dataPostPacket.__data.data, dataPostPacket.__data.packetLength - (sizeof(std::uint16_t) * 5));
|
||||||
|
|
||||||
spdlog::info("[{}] {}", sentUserName, message); // todo: pass data to main thread
|
spdlog::info("[{}] {}", sentUserName, message); // todo: pass data to main thread
|
||||||
@@ -324,8 +300,7 @@ void ClientManager::run() {
|
|||||||
|
|
||||||
std::unique_lock<std::mutex> lock2(screenMutex_);
|
std::unique_lock<std::mutex> lock2(screenMutex_);
|
||||||
if (inRoom_) {
|
if (inRoom_) {
|
||||||
auto RNames = roomNames_.get();
|
std::cout << "[" + nickname + "@" + roomNames_[myRoomID_] + "]" + " ";
|
||||||
std::cout << "[" + nickname + "@" + RNames[myRoomID_] + "]" + " ";
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
std::cout << "[" + nickname + "]" + " ";
|
std::cout << "[" + nickname + "]" + " ";
|
||||||
@@ -339,20 +314,18 @@ void ClientManager::run() {
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (tokens[0] == "/w") {
|
if (tokens[0] == "/w") {
|
||||||
auto findUserId = findUserId_.get();
|
if (findUserId_.find(tokens[1]) == findUserId_.end()) {
|
||||||
|
|
||||||
if (findUserId.find(tokens[1]) == findUserId.end()) {
|
|
||||||
resourceMutex_.lock();
|
resourceMutex_.lock();
|
||||||
messageQueue_.push("User not found");
|
messageQueue_.push("User not found");
|
||||||
resourceMutex_.unlock();
|
resourceMutex_.unlock();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
Snowflake destId = findUserId[tokens[1]];
|
Snowflake destId = findUserId_[tokens[1]];
|
||||||
|
|
||||||
std::string message;
|
std::string message;
|
||||||
for (int i = 2; i < tokens.size(); i++)
|
for (int i = 2; i < tokens.size(); i++)
|
||||||
message += tokens[i];
|
message += tokens[i] + " ";
|
||||||
|
|
||||||
sendMessage(destId, message);
|
sendMessage(destId, message);
|
||||||
}
|
}
|
||||||
@@ -360,20 +333,14 @@ void ClientManager::run() {
|
|||||||
std::string roomName;
|
std::string roomName;
|
||||||
for (int i = 1; i < tokens.size(); i++)
|
for (int i = 1; i < tokens.size(); i++)
|
||||||
roomName += tokens[i];
|
roomName += tokens[i];
|
||||||
if (findRoomId_.wait_for(std::chrono::seconds(0)) != std::future_status::ready) {
|
|
||||||
resourceMutex_.lock();
|
if (findRoomId_.find(roomName) == findRoomId_.end()) {
|
||||||
messageQueue_.push("Request room list first");
|
|
||||||
resourceMutex_.unlock();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
auto findRoomId = findRoomId_.get();
|
|
||||||
if (findRoomId.find(roomName) == findRoomId.end()) {
|
|
||||||
resourceMutex_.lock();
|
resourceMutex_.lock();
|
||||||
messageQueue_.push("Room not found");
|
messageQueue_.push("Room not found");
|
||||||
resourceMutex_.unlock();
|
resourceMutex_.unlock();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
joinRoom(myID_, findRoomId[roomName]);
|
joinRoom(myID_, findRoomId_[roomName]);
|
||||||
}
|
}
|
||||||
else if (tokens[0] == "/leave") {
|
else if (tokens[0] == "/leave") {
|
||||||
if (!inRoom_) {
|
if (!inRoom_) {
|
||||||
|
|||||||
@@ -15,6 +15,8 @@ IOCP::~IOCP() {
|
|||||||
|
|
||||||
void IOCP::destruct() {
|
void IOCP::destruct() {
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
|
uint64_t u = 1;
|
||||||
|
::write(epollDetroyerFd_, &u, sizeof(uint64_t));
|
||||||
close(epollfd_);
|
close(epollfd_);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,8 +32,11 @@ int TCPSocket::connect(Address& serveraddr) {
|
|||||||
|
|
||||||
int TCPSocket::recv(void *__restrict __buf, size_t __n, int __flags) {
|
int TCPSocket::recv(void *__restrict __buf, size_t __n, int __flags) {
|
||||||
int retVal = ::recv(sock, (char *)__buf, __n, __flags);
|
int retVal = ::recv(sock, (char *)__buf, __n, __flags);
|
||||||
if (retVal == SOCKET_ERROR)
|
if (retVal == SOCKET_ERROR) {
|
||||||
|
if (errno == EAGAIN || errno == EWOULDBLOCK)
|
||||||
|
return retVal;
|
||||||
log::error("recv()");
|
log::error("recv()");
|
||||||
|
}
|
||||||
return retVal;
|
return retVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -141,6 +141,10 @@ public:
|
|||||||
redSize = ptr->socket->recv(ptr->buf + totalRedSize, dataLength + headerSize - totalRedSize, 0);
|
redSize = ptr->socket->recv(ptr->buf + totalRedSize, dataLength + headerSize - totalRedSize, 0);
|
||||||
|
|
||||||
if (redSize == SOCKET_ERROR) {
|
if (redSize == SOCKET_ERROR) {
|
||||||
|
if (errno == EAGAIN || errno == EWOULDBLOCK) {
|
||||||
|
spdlog::trace("No data to read on {}", tid);
|
||||||
|
return;
|
||||||
|
}
|
||||||
spdlog::error("recv() [{}]", strerror(errno));
|
spdlog::error("recv() [{}]", strerror(errno));
|
||||||
::epoll_ctl(epollfd, EPOLL_CTL_DEL, ptr->socket->sock, NULL);
|
::epoll_ctl(epollfd, EPOLL_CTL_DEL, ptr->socket->sock, NULL);
|
||||||
delete ptr;
|
delete ptr;
|
||||||
@@ -169,10 +173,14 @@ public:
|
|||||||
IOCPPASSINDATA* rootIocpData = (IOCPPASSINDATA*)event.data.ptr;
|
IOCPPASSINDATA* rootIocpData = (IOCPPASSINDATA*)event.data.ptr;
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(rootIocpData->socket->writeMutex);
|
std::lock_guard<std::mutex> lock(rootIocpData->socket->writeMutex);
|
||||||
auto queue = rootIocpData->sendQueue;
|
while (!rootIocpData->sendQueue->empty()) {
|
||||||
while (!queue->empty()) {
|
IOCPPASSINDATA* data = rootIocpData->sendQueue->front();
|
||||||
IOCPPASSINDATA* data = queue->front();
|
rootIocpData->sendQueue->pop();
|
||||||
queue->pop();
|
|
||||||
|
if (data == nullptr) {
|
||||||
|
spdlog::error("invalid call on {}", tid);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
int packetSize = data->wsabuf.len;
|
int packetSize = data->wsabuf.len;
|
||||||
int totalSentSize = 0;
|
int totalSentSize = 0;
|
||||||
@@ -184,6 +192,10 @@ public:
|
|||||||
sentSize = data->socket->send(data->buf + totalSentSize, packetSize - totalSentSize, 0);
|
sentSize = data->socket->send(data->buf + totalSentSize, packetSize - totalSentSize, 0);
|
||||||
|
|
||||||
if (sentSize == SOCKET_ERROR) {
|
if (sentSize == SOCKET_ERROR) {
|
||||||
|
if (errno == EAGAIN || errno == EWOULDBLOCK) {
|
||||||
|
spdlog::warn("buffer full");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
spdlog::error("send() [{}]", strerror(errno));
|
spdlog::error("send() [{}]", strerror(errno));
|
||||||
::epoll_ctl(epollfd, EPOLL_CTL_DEL, data->socket->sock, NULL);
|
::epoll_ctl(epollfd, EPOLL_CTL_DEL, data->socket->sock, NULL);
|
||||||
delete data;
|
delete data;
|
||||||
@@ -199,8 +211,7 @@ public:
|
|||||||
struct epoll_event events[FD_SETSIZE];
|
struct epoll_event events[FD_SETSIZE];
|
||||||
pthread_t tid = pthread_self();
|
pthread_t tid = pthread_self();
|
||||||
|
|
||||||
spdlog::trace("epoll waiting on {}", tid);
|
int nready = ::epoll_wait(epollfd, events, FD_SETSIZE, -1);
|
||||||
int nready = ::epoll_wait(epollfd, events, FD_SETSIZE, 1000);
|
|
||||||
|
|
||||||
for (int i=0; i<nready; i++) {
|
for (int i=0; i<nready; i++) {
|
||||||
struct epoll_event current_event = events[i];
|
struct epoll_event current_event = events[i];
|
||||||
@@ -232,6 +243,8 @@ public:
|
|||||||
log::critical("CreateIoCompletionPort()");
|
log::critical("CreateIoCompletionPort()");
|
||||||
#elif __linux__
|
#elif __linux__
|
||||||
epollfd_ = ::epoll_create(1);
|
epollfd_ = ::epoll_create(1);
|
||||||
|
epollDetroyerFd_ = ::eventfd(0, EFD_NONBLOCK);
|
||||||
|
::epoll_ctl(epollfd_, EPOLL_CTL_ADD, epollDetroyerFd_, NULL);
|
||||||
#endif
|
#endif
|
||||||
auto boundFunc = [callback = std::move(callback)](ThreadPool* __IOCPThread, IOCPPASSINDATA* data) mutable {
|
auto boundFunc = [callback = std::move(callback)](ThreadPool* __IOCPThread, IOCPPASSINDATA* data) mutable {
|
||||||
callback(__IOCPThread, data);
|
callback(__IOCPThread, data);
|
||||||
@@ -270,6 +283,7 @@ private:
|
|||||||
HANDLE completionPort_ = INVALID_HANDLE_VALUE;
|
HANDLE completionPort_ = INVALID_HANDLE_VALUE;
|
||||||
#elif __linux__
|
#elif __linux__
|
||||||
int epollfd_ = -1;
|
int epollfd_ = -1;
|
||||||
|
int epollDetroyerFd_ = -1;
|
||||||
std::unordered_map<std::shared_ptr<TCPSocket>, std::mutex> writeMutex;
|
std::unordered_map<std::shared_ptr<TCPSocket>, std::mutex> writeMutex;
|
||||||
std::unordered_map<std::shared_ptr<TCPSocket>, std::queue<IOCPPASSINDATA*>> writeBuffer;
|
std::unordered_map<std::shared_ptr<TCPSocket>, std::queue<IOCPPASSINDATA*>> writeBuffer;
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
|
#include <sys/eventfd.h>
|
||||||
#define SOCKET int
|
#define SOCKET int
|
||||||
#define INVALID_SOCKET -1
|
#define INVALID_SOCKET -1
|
||||||
#define SOCKET_ERROR -1
|
#define SOCKET_ERROR -1
|
||||||
|
|||||||
Reference in New Issue
Block a user