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