mercredi 7 novembre 2018

Manage the life time of static class variable using smart pointer C++

I do maintain a static variable called m_queue which holds the messages, which are pushed by the main thread, so the question is, when the worker thread gets killed by someway, how could I kill the message ptrs in the m_queue and release the memory using smart pointers? I know the answer partially, to use shared_ptr. Is it recommended to use shared_ptr for static variables? If so, how do I do that? Any help would be appreciated. Please do point out if there are any major flaws in the code.

typedef enum msg_type_t_ {
    MSG_SET,
    MSG_GET,
    MSG_NULL
} msg_type_t;

class msg_t {
public:
    std::string m_name;
    msg_type_t m_type;
    uint32_t m_id;
    msg_t(const std::string& name, const msg_type_t& type, uint32_t id) :
          m_name(name), m_type(type), m_id(id) {}
    ~msg_t()
    {
        std::cout << "Destructor called!" << std::endl;
    }
};
using msg_uptr_t = std::unique_ptr<msg_t>;

class workerThread {
private:
    std::string m_thread_name;
    std::thread* m_thread;
    std::condition_variable m_cond;
    std::mutex m_mtx;
    /* Message queue is shared amongst all the instances of the class */
    static std::queue<msg_uptr_t> m_queue;

public:
    /* Creating a new thread! */
    workerThread(const std::string& name)
    {
        m_thread_name = name;
        m_thread = new std::thread(&workerThread::thread_fn, this);
    }
    std::thread* getThread()
    {
        return m_thread;
    }
    const std::string& getThreadName()
    {
        return m_thread_name;
    }
    void thread_fn()
    {
        std::cout << "Created a new thread " << m_thread_name << std::endl;
        while(1) {
            msg_uptr_t msg_p;
            std::unique_lock<std::mutex> l(m_mtx);
            /* Wait until message queue is not empty!*/
            while(m_queue.empty()) {
                std::cout << "Waiting!" << std::endl;
                m_cond.wait(l,([this](){return !(m_queue).empty();}));
            }
            if(m_queue.empty()) {
                continue;
            }
            std::cout << "Message queue is not empty!, Continuing the processing!" << std::endl;
            std::cout << "Number of elements in the queue = " << m_queue.size() << std::endl;
            msg_p = std::move(m_queue.front());
            m_queue.pop();

            switch(msg_p->m_type) {
            case MSG_SET:
                std::cout << "Message Set Operation!" << std::endl;
                break;
            case MSG_GET:
                std::cout << "Message Get Operation!" << std::endl;
                break;
            case MSG_NULL:
                std::cout << "Null Operation!" << std::endl;
                break;
            default:
                std::cout << "Wrong Message type!" << std::endl;
                break;
            }
        }
    }
    void postMsg(msg_uptr_t msg_p)
    {
        std::cout << "Posting Message on to the queue!" << std::endl;
        std::cout << "Message Details!" << "Name : " << msg_p.get()->m_name<< std::endl;
        std::unique_lock<std::mutex> l{m_mtx};
        m_queue.push(std::move(msg_p));
        m_cond.notify_one();
    }
};
std::queue<msg_uptr_t> workerThread::m_queue;

Aucun commentaire:

Enregistrer un commentaire