Commit a633388177049e700950fb1ff74b18be2ba27ec8
1 parent
40f8e5e5
quick hack to get all threads to work
Showing
7 changed files
with
32 additions
and
3 deletions
client.cpp
| ... | ... | @@ -66,6 +66,13 @@ void Client::writeMqttPacket(const MqttPacket &packet) |
| 66 | 66 | wwi += packet.getSize(); |
| 67 | 67 | } |
| 68 | 68 | |
| 69 | +// Not sure if this is the method I want to use | |
| 70 | +void Client::writeMqttPacketLocked(const MqttPacket &packet) | |
| 71 | +{ | |
| 72 | + std::lock_guard<std::mutex> lock(writeBufMutex); | |
| 73 | + writeMqttPacket(packet); | |
| 74 | +} | |
| 75 | + | |
| 69 | 76 | // Ping responses are always the same, so hardcoding it for optimization. |
| 70 | 77 | void Client::writePingResp() |
| 71 | 78 | { | ... | ... |
client.h
| ... | ... | @@ -4,6 +4,7 @@ |
| 4 | 4 | #include <fcntl.h> |
| 5 | 5 | #include <unistd.h> |
| 6 | 6 | #include <vector> |
| 7 | +#include <mutex> | |
| 7 | 8 | |
| 8 | 9 | #include "forward_declarations.h" |
| 9 | 10 | |
| ... | ... | @@ -11,6 +12,7 @@ |
| 11 | 12 | #include "mqttpacket.h" |
| 12 | 13 | #include "exceptions.h" |
| 13 | 14 | |
| 15 | + | |
| 14 | 16 | #define CLIENT_BUFFER_SIZE 1024 |
| 15 | 17 | #define MQTT_HEADER_LENGH 2 |
| 16 | 18 | |
| ... | ... | @@ -35,6 +37,7 @@ class Client |
| 35 | 37 | uint16_t keepalive = 0; |
| 36 | 38 | |
| 37 | 39 | ThreadData_p threadData; |
| 40 | + std::mutex writeBufMutex; | |
| 38 | 41 | |
| 39 | 42 | size_t getReadBufBytesUsed() |
| 40 | 43 | { |
| ... | ... | @@ -96,6 +99,7 @@ public: |
| 96 | 99 | |
| 97 | 100 | void writePingResp(); |
| 98 | 101 | void writeMqttPacket(const MqttPacket &packet); |
| 102 | + void writeMqttPacketLocked(const MqttPacket &packet); | |
| 99 | 103 | bool writeBufIntoFd(); |
| 100 | 104 | |
| 101 | 105 | std::string repr(); | ... | ... |
main.cpp
| ... | ... | @@ -36,7 +36,8 @@ void do_thread_work(ThreadData *threadData) |
| 36 | 36 | { |
| 37 | 37 | for (Client_p client : threadData->getReadyForDequeueing()) |
| 38 | 38 | { |
| 39 | - client->queuedMessagesToBuffer(); | |
| 39 | + //client->queuedMessagesToBuffer(); | |
| 40 | + client->writeBufIntoFd(); | |
| 40 | 41 | } |
| 41 | 42 | threadData->clearReadyForDequeueing(); |
| 42 | 43 | eventfd_value = 0; | ... | ... |
subscriptionstore.cpp
| ... | ... | @@ -7,22 +7,27 @@ SubscriptionStore::SubscriptionStore() |
| 7 | 7 | |
| 8 | 8 | void SubscriptionStore::addSubscription(Client_p &client, std::string &topic) |
| 9 | 9 | { |
| 10 | + std::lock_guard<std::mutex> lock(subscriptionsMutex); | |
| 10 | 11 | this->subscriptions[topic].push_back(client); |
| 11 | 12 | } |
| 12 | 13 | |
| 13 | 14 | void SubscriptionStore::queueAtClientsTemp(std::string &topic, const MqttPacket &packet, const Client_p &sender) |
| 14 | 15 | { |
| 16 | + // TODO: temp. I want to work with read copies of the subscription store, to avoid frequent lock contention. | |
| 17 | + std::lock_guard<std::mutex> lock(subscriptionsMutex); | |
| 18 | + | |
| 15 | 19 | for(Client_p &client : subscriptions[topic]) |
| 16 | 20 | { |
| 17 | 21 | if (client->getThreadData()->threadnr == sender->getThreadData()->threadnr) |
| 18 | 22 | { |
| 19 | - client->writeMqttPacket(packet); | |
| 23 | + client->writeMqttPacket(packet); // TODO: with my current hack way, this is wrong. Not using a lock only works with my previous idea of queueing. | |
| 20 | 24 | client->writeBufIntoFd(); |
| 21 | 25 | } |
| 22 | 26 | else |
| 23 | 27 | { |
| 24 | - client->queueMessage(packet); | |
| 28 | + client->writeMqttPacketLocked(packet); | |
| 25 | 29 | client->getThreadData()->addToReadyForDequeuing(client); |
| 30 | + client->getThreadData()->wakeUpThread(); | |
| 26 | 31 | } |
| 27 | 32 | } |
| 28 | 33 | } | ... | ... |
subscriptionstore.h
| ... | ... | @@ -3,6 +3,7 @@ |
| 3 | 3 | |
| 4 | 4 | #include <unordered_map> |
| 5 | 5 | #include <list> |
| 6 | +#include <mutex> | |
| 6 | 7 | |
| 7 | 8 | #include "forward_declarations.h" |
| 8 | 9 | |
| ... | ... | @@ -11,6 +12,7 @@ |
| 11 | 12 | class SubscriptionStore |
| 12 | 13 | { |
| 13 | 14 | std::unordered_map<std::string, std::list<Client_p>> subscriptions; |
| 15 | + std::mutex subscriptionsMutex; | |
| 14 | 16 | public: |
| 15 | 17 | SubscriptionStore(); |
| 16 | 18 | ... | ... |
threaddata.cpp
| ... | ... | @@ -7,6 +7,12 @@ ThreadData::ThreadData(int threadnr, std::shared_ptr<SubscriptionStore> &subscri |
| 7 | 7 | { |
| 8 | 8 | epollfd = check<std::runtime_error>(epoll_create(999)); |
| 9 | 9 | event_fd = eventfd(0, EFD_NONBLOCK); |
| 10 | + | |
| 11 | + struct epoll_event ev; | |
| 12 | + memset(&ev, 0, sizeof (struct epoll_event)); | |
| 13 | + ev.data.fd = event_fd; | |
| 14 | + ev.events = EPOLLIN; | |
| 15 | + check<std::runtime_error>(epoll_ctl(epollfd, EPOLL_CTL_ADD, event_fd, &ev)); | |
| 10 | 16 | } |
| 11 | 17 | |
| 12 | 18 | void ThreadData::giveClient(Client_p client) |
| ... | ... | @@ -44,11 +50,13 @@ void ThreadData::wakeUpThread() |
| 44 | 50 | |
| 45 | 51 | void ThreadData::addToReadyForDequeuing(Client_p &client) |
| 46 | 52 | { |
| 53 | + std::lock_guard<std::mutex> lock(readForDequeuingMutex); | |
| 47 | 54 | this->readyForDequeueing.insert(client); |
| 48 | 55 | } |
| 49 | 56 | |
| 50 | 57 | void ThreadData::clearReadyForDequeueing() |
| 51 | 58 | { |
| 59 | + std::lock_guard<std::mutex> lock(readForDequeuingMutex); | |
| 52 | 60 | this->readyForDequeueing.clear(); |
| 53 | 61 | } |
| 54 | 62 | ... | ... |
threaddata.h
| ... | ... | @@ -8,6 +8,7 @@ |
| 8 | 8 | #include <map> |
| 9 | 9 | #include <unordered_set> |
| 10 | 10 | #include <unordered_map> |
| 11 | +#include <mutex> | |
| 11 | 12 | |
| 12 | 13 | #include "forward_declarations.h" |
| 13 | 14 | |
| ... | ... | @@ -22,6 +23,7 @@ class ThreadData |
| 22 | 23 | std::unordered_map<int, Client_p> clients_by_fd; |
| 23 | 24 | std::shared_ptr<SubscriptionStore> subscriptionStore; |
| 24 | 25 | std::unordered_set<Client_p> readyForDequeueing; |
| 26 | + std::mutex readForDequeuingMutex; | |
| 25 | 27 | |
| 26 | 28 | public: |
| 27 | 29 | std::thread thread; | ... | ... |