#pragma once // Usage: // // ACTIONS_LIST actionsList; // CLASS myClass; // DATA1 myData1; // DATA2 myData2; // // actionsList.Enqueue(myClass, &CLASS::myMethod1, myData1); // actionsList.Enqueue(myClass, &CLASS::myMethod2, myData2); // // actionsList.InvokeAll(); #include #include #include // Generalized actor type - a method of some class with one argument template struct ACTOR { using TYPE = void (ACTIVE_CLASS::*)(DATA_TYPE); }; // Abstract base action class for polymorphic action invocation class BASE_ACTION { public: virtual ~BASE_ACTION() {} virtual void Invoke() = 0; }; // Concrete generalized action type - an actor with it's data and owner template class ACTION : public BASE_ACTION { public: ACTION(ACTIVE_CLASS & ac, typename ACTOR::TYPE a, DATA_TYPE d) : activeClass(ac), actor(a), data(d) {} void Invoke() override { (activeClass.*actor)(data); } private: ACTION(const ACTION & rvalue); ACTION & operator=(const ACTION & rvalue); ACTIVE_CLASS & activeClass; typename ACTOR::TYPE actor; DATA_TYPE data; }; // A list of an actions // All methods are thread-safe class ACTIONS_LIST { public: ~ACTIONS_LIST() { std::lock_guard lock(m_mutex); for (auto action : m_list) delete action; } auto begin() { std::lock_guard lock(m_mutex); return m_list.begin(); } auto end() { std::lock_guard lock(m_mutex); return m_list.end(); } auto begin() const { std::lock_guard lock(m_mutex); return m_list.begin(); } auto end() const { std::lock_guard lock(m_mutex); return m_list.end(); } bool empty() const { std::lock_guard lock(m_mutex); return m_list.empty(); } size_t size() const { std::lock_guard lock(m_mutex); return m_list.size(); } void swap(ACTIONS_LIST & rhs) { std::lock_guard lock(m_mutex); m_list.swap(rhs.m_list); } // Add an action to list template void Enqueue(ACTIVE_CLASS & ac, typename ACTOR::TYPE a, DATA_TYPE d) { std::lock_guard lock(m_mutex); m_list.push_back(new ACTION(ac, a, d)); } // Invoke all actions in the list void InvokeAll() { std::lock_guard lock(m_mutex); for (auto action : m_list) action->Invoke(); } private: mutable std::mutex m_mutex; std::vector m_list; };