1

I made a generic safe thread queue- QueueTS And I have a class named PackagedEvent. I want to make a vector of queues. Each queue stores PackagedEvent. But its not possible to push a new queue to the vector and I dont understand why. The compiler says:

1>C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.26.28801\include\xmemory(671,82): error C2280: 'ds::QueueTS<smartH::PackagedEvent>::QueueTS(const ds::QueueTS<smartH::PackagedEvent> &)': attempting to reference a deleted function
1>C:\me\studies\CPP\my_code\debug1\debug1\queueTS.hpp(30): message : compiler has generated 'ds::QueueTS<smartH::PackagedEvent>::QueueTS' here
1>C:\me\studies\CPP\my_code\debug1\debug1\queueTS.hpp(30,1): message : 'ds::QueueTS<smartH::PackagedEvent>::QueueTS(const ds::QueueTS<smartH::PackagedEvent> &)': function was implicitly deleted because a data member invokes a deleted or inaccessible function 'std::mutex::mutex(const std::mutex &)'
1>C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.26.28801\include\mutex(92,5): message : 'std::mutex::mutex(const std::mutex &)': function was explicitly deleted
1>C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.26.28801\include\vector(682): message : see reference to function template instantiation 'void std::_Default_allocator_traits<_Alloc>::construct<_Ty,_Ty>(_Alloc &,_Objty *const ,_Ty &&)' being compiled
1>        with
1>        [
1>            _Alloc=std::allocator<ds::QueueTS<smartH::PackagedEvent>>,
1>            _Ty=ds::QueueTS<smartH::PackagedEvent>,
1>            _Objty=ds::QueueTS<smartH::PackagedEvent>
1>        ]
1>C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.26.28801\include\vector(687): message : see reference to function template instantiation 'void std::_Default_allocator_traits<_Alloc>::construct<_Ty,_Ty>(_Alloc &,_Objty *const ,_Ty &&)' being compiled
1>        with
1>        [
1>            _Alloc=std::allocator<ds::QueueTS<smartH::PackagedEvent>>,
1>            _Ty=ds::QueueTS<smartH::PackagedEvent>,
1>            _Objty=ds::QueueTS<smartH::PackagedEvent>
1>        ]
1>C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.26.28801\include\vector(700): message : see reference to function template instantiation 'void std::vector<ds::QueueTS<smartH::PackagedEvent>,std::allocator<ds::QueueTS<smartH::PackagedEvent>>>::_Emplace_back_with_unused_capacity<_Ty>(_Ty &&)' being compiled
1>        with
1>        [
1>            _Ty=ds::QueueTS<smartH::PackagedEvent>
1>        ]

int main()
{
    vector<QueueTS< PackagedEvent>> vec;

    vec.push_back(QueueTS< PackagedEvent>());
    return 1;
}
class PackagedEvent
    {
    private:
        shared_ptr<Event> m_eventPtr;
        size_t m_destination;
    public:
        PackagedEvent();
        PackagedEvent(const shared_ptr<Event>& _event, const size_t& _destination);
        shared_ptr<Event> getEventPtr() const;
        size_t getDestination() const;
        void setEventPtr(const shared_ptr<Event>& _event);
        void setDestination(const size_t& _destination);
    };
template <typename T>
    class QueueTS
    {
    public:
        QueueTS();
        ~QueueTS() = default;
        int enqueue(const T& _t);
        int dequeue(T& _ptrT);
        void stop();
        int size();
    private:

        queue<T> m_mainQueue;
        mutex m_mutex;
        condition_variable m_cv;
        bool m_power;
    }; //QueueTS
Oz Harary
  • 15
  • 6
  • What is the full error message and the MSVC++ version? – Tumbleweed53 Dec 03 '20 at 16:15
  • Compiling the given code I receive 17 errors. That's a few too many for me. I recommend crafting a [mre]. If that doesn't allow you to find and fix the error, edit the question and add the MRE.. – user4581301 Dec 03 '20 at 16:16
  • There are many messages, I cannot copy all of them cause its out of limits – Oz Harary Dec 03 '20 at 16:18
  • Your vector creates copies of queues. Can you copy ‘QueueTS’? – Vlad Feinstein Dec 03 '20 at 16:18
  • I didnt write copy c'tor cause I thought the defult c'tor would be enough – Oz Harary Dec 03 '20 at 16:22
  • I added a few more messages. Its still not all – Oz Harary Dec 03 '20 at 16:25
  • You don't want to have many errors. Errors have an annoying habit of ganging up on you. Resolve the problem of the class not being copy-able before proceeding. Mutexes, for obvious reasons, cannot be copied, and `vector` does **a lot** of copying. – user4581301 Dec 03 '20 at 16:26
  • `1>C:\me\studies\CPP\my_code\debug1\debug1\queueTS.hpp(30,1): message : 'ds::QueueTS::QueueTS(const ds::QueueTS &)': function was implicitly deleted because a data member invokes a deleted or inaccessible function 'std::mutex::mutex(const std::mutex &)'` tells you straight-up that the default copy constructor is insufficient. You'll need move construction and move assignment to make this sucker work. Looking for good question that covers this because moving a mutex is not trivial. – user4581301 Dec 03 '20 at 16:31
  • Ok I understand. So maybe its better to use an array instead of vector – Oz Harary Dec 03 '20 at 16:34
  • Here we go: [How should I deal with mutexes in movable types in C++?](https://stackoverflow.com/questions/29986208/how-should-i-deal-with-mutexes-in-movable-types-in-c). If possible take Rusty's advice and just don't go there. – user4581301 Dec 03 '20 at 16:35
  • If you know the sizes in advance and that size won't change, you can `reserve` storage and `emplace_back` and possibly avoid the problem. – user4581301 Dec 03 '20 at 16:37
  • Yeh in this case the size is fixed :) – Oz Harary Dec 03 '20 at 16:39

1 Answers1

1

push_back makes a copy when pushing into a vector, but your QueueTS isn't copyable (it's default copy-c'tor is automatically deleted because std::mutex isn't copyable).

One solution is to make QueueTS copyable by adding a copy constructor and a copy assignment operator. For example:

class QueueTS
{
public:
    // . . .
    QueueTS(QueueTS const& q) {
        (*this) = q;
    }
    QueueTS& operator=(QueueTS const& q) {
        std::lock_guard lock(q.m_mutex);
        m_mainQueue = q.m_mainQueue;
        m_power = q.m_power;
        return *this;
    }
    // . . .
private:
    // . . .
    mutable mutex m_mutex; // make the mutex mutable so it can be accessed via const-ref's

Another (better) solution is to make it movable, but an even better solution is to avoid copying in the first place by using e.g. a vector of pointers to QueueTS (vector<unique_ptr<QueueTS>>) or an std::list with in-place construction.

rustyx
  • 80,671
  • 25
  • 200
  • 267