Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Move vector between threads

I have a thread that continuously collects data items with a public interface like this:

class MyThread {
public:
    class Item {
        // ...
    };

    startup();
    shutdown();

    bool hasItems() const;

    // retrieve collected items
    std::vector<Item>&& items();
private:
    std::mutex itemMutex;
    std::vector<Item> currentItems;
};

Retrieving the items should also clear the thread's item list. I return an rvalue so that the move constructor is invoked on the calling side. Of course, retrieving the items should be thread-safe, so the implementation looks like this:

std::vector<MyThread::Item>&& MyThread::items() {
    std::lock_guard<std::mutex> lock(itemMutex);
    return std::move(currentItems);
}

I think that the lock is released too early here: the function returns the rvalue'd vector, but a move constructor hasn't necessarily be called with it when the std::lock_guard is destroyed and releases the mutex. So from my understanding, this isn't thread-safe. Am I right? How can I make it thread-safe?

like image 334
flyx Avatar asked Jan 22 '14 10:01

flyx


Video Answer


1 Answers

You're right, it isn't threadsafe as the move will happen after the method returns, at which point the lock will have been released. To fix it just move the vector into a local variable and return that :

std::vector<MyThread::Item> MyThread::items() 
{
    std::lock_guard<std::mutex> lock(itemMutex);
    return std::vector<MyThread::Item>(std::move(currentItems));
}
like image 170
Sean Avatar answered Oct 01 '22 00:10

Sean