c++11 - C++: Queue wrapper issues with templates -
short question: obvious mistake (misunderstanding?) making use of std::is_pointer and/or std::is_array within safequeue::clear()? intent check queue of pointers, check if pointers happen unsigned char* or char* arrays.
this in c++11, wrapping std::queue class bring approaching thread safety.
#ifndef safequeue_h #define safequeue_h #include <queue> #include <mutex> #include <type_traits> template <typename t> class safequeue { public: safequeue() = default; // default ctor safequeue(const safequeue&) = delete; // disable copy safequeue& operator=(const safequeue&) = delete; // disable assignment bool empty() const { std::unique_lock<std::mutex> ulock(m_mutex); return m_queue.empty(); } t& front() // never called without empty() or size() > 0 check { std::unique_lock<std::mutex> lock(m_mutex); if(!m_queue.empty()) { return m_queue.front(); } } void clear() { std::unique_lock<std::mutex> lock(m_mutex); if(m_queue.empty()) { return; } // quick exit bool ispointers = (std::is_pointer<t>::value) ? true : false; // returns true on class objects if(ispointers) { //bool isarray = std::is_array<t>::value ? true : false; // returns true on class objects bool isarray = (std::is_same<unsigned char*, t>::value || std::is_same<char*, t>::value) ? true : false; // returns true while(!m_queue.empty()) { if(isarray) { delete[] m_queue.front(); m_queue.front() = nullptr; } else { delete[] m_queue.front(); m_queue.front() = nullptr; } m_queue.pop(); } } else { std::queue<t>().swap(m_queue); } } void pop() { std::unique_lock<std::mutex> lock(m_mutex); if(!m_queue.empty()) { m_queue.pop(); } } unsigned int size() const { std::unique_lock<std::mutex> lock(m_mutex); return m_queue.size(); } void push(const t& item) { std::unique_lock<std::mutex> lock(m_mutex); m_queue.push(item); } protected: mutable std::mutex m_mutex; std::queue<t> m_queue; }; #endif // safequeue_h
all branches compiled if control false.
you getting build breaks because t=int, delete[] called on int not legal c++.
the way fix problem not store arrays of raw char*, instead smart pointers std::unique_ptr<char[]> or std::unique_ptr<unsigned char[]> in queue.
you can type trait:
template<class t> struct queued_type{ using type=t; using extracted_type=t&; static extracted_type extract(type& out){ return out; } static type& box(t& in){ return in; } }; template<class t> struct queued_type<t*>{ using type=std::unique_ptr<t[]>; using extracted_type=type; static extracted_type extract(type& out){ return out.release(); } static type box(type& in){ return type(in); } }; template<class t>using queued_type_t=typename queued_type<t>::type; now store std::queue<queued_type_t<t>>. push m_queue.push(queued_type<t>::box(in));, front queued_type<t>::extract(m_queue.front()) , returns typename queued_type<t>::extracted_type.
and clear std::queue<queued_type_t<t>>{}.swap(m_queue); no logic.
Comments
Post a Comment