Thread: Multithreading, tbb, local variable problem

  1. #1
    Registered User
    Join Date
    Feb 2009
    Posts
    40

    Multithreading, tbb, local variable problem

    Hi all,
    I Just have just getting started to use intels Threading Building Blocks, but it just took some minutes before I got some problem. If I am running the code below will m_type.size() always return 0 even if i am pushing new data in a second thread:

    Code:
    #include <string>
    #include <iostream>
    #include <boost/thread.hpp>
    #include "tbb/concurrent_vector.h"
    
    
    class Test
    {
    public:
    	Test(tbb::concurrent_vector<std::string> & t)
    		//: m_type(t) 
    	{
    	}
    	void worker()
    	{
    		std::cout << "Producing now..";
    		while(true)
    		{	
    			if(m_type.size() < 1000)
    			{
    				m_type.push_back(std::string("Mohaha"));
    				std::cout << "worker: size = " << m_type.size() << std::endl;
    			}
    		}
    	}
    
    	void consumer()
    	{
    		std::cout << "Consuming now..";
    		while(true)
    		{
    			std::cout << "Consumer: size = " << m_type.size() << std::endl;
    			if(m_type.size())
    			{
    				std::string message = m_type.back();
    				std::cout << "Message: " << message << std::endl;
    				if(m_type.size() > 100)
    				{
    					m_type.clear();
    				}
    			}
    		}
    	}
    private:
    	tbb::concurrent_vector<std::string> m_type;
    };
    
    
    int main(int argc, char** argv)
    {
    	tbb::concurrent_vector<std::string> vec;
    	Test test(vec);
    
    
    	boost::thread thread(boost::bind(&Test::worker, test));
    	boost::thread thread2(boost::bind(&Test::consumer, test));
    	thread2.join();
    	thread.join();
    }
    But if I am making m_type to a reference (&) will it work without problems.

    I know that local variables can be read into a processor cache and that is what I think happens, but how do I prevent it? And if it isn't the problem, what I am doing wrong then?

    I second question:
    Do any of you have any good multi threading links to share?


    Thanks in advance

  2. #2
    Registered User C_ntua's Avatar
    Join Date
    Jun 2008
    Posts
    1,853
    Can you post the exact output of the program?

  3. #3
    Registered User
    Join Date
    Feb 2009
    Posts
    40
    Exactly? No, it is different every time I run it of course.

    The program acts like it got 2 tbb::concurrent_vector<std::string> separated for each thread, even if it just got one. Even if the worker method pushes new data to the vector does the consumer never see it. It is like it is 2 different variables separated from each other. Worker thread says m_type.size() have size (x > 0) and consumer always 0. If I am in another way make m_type to a reference will it work, probably because the compiler cannot make some optimizes and if I am trying to make the variable of type volatile I just got compile errors.

    I have search little and I probably need a memory barrier that force the processor to clean its L1/L2 cache and register every time, but I always have used boost::mutex before this so I don't really know how I fix it. I could add a mutex (mutex force memory barrier as I know), but what should be the point to use a concurrent container then?

  4. #4
    Malum in se abachler's Avatar
    Join Date
    Apr 2007
    Posts
    3,195
    You need to use critical sections to prevent simultaneous access to a modifiable object.

  5. #5
    Registered User
    Join Date
    Feb 2009
    Posts
    40
    What do you mean? It is a concurrent container, it is thread safe to access from multiple threads, both read and write it says in the documentation.

  6. #6
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    Give Test a private copy constructor, and you'll see the problem (or not, given bind's error messages): Boost.Bind binds its arguments as copies. In other words, each of these threads has its private Test object, with its own private vector. You need to bind by reference, which you can achieve by using Boost's reference_wrapper:
    Code:
    	boost::thread thread(boost::bind(&Test::worker, boost::ref(test)));
    	boost::thread thread2(boost::bind(&Test::consumer, boost::ref(test)));
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

  7. #7
    Registered User
    Join Date
    Feb 2009
    Posts
    40
    Thanks CornedBee, I never thought about it

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Variable Allocation Problem
    By bavetta in forum C Programming
    Replies: 3
    Last Post: 11-14-2009, 12:52 AM
  2. Replies: 3
    Last Post: 10-13-2009, 08:49 AM
  3. Replies: 2
    Last Post: 10-10-2009, 10:38 PM
  4. Replies: 5
    Last Post: 08-14-2009, 03:15 AM
  5. Need some help...
    By darkconvoy in forum C Programming
    Replies: 32
    Last Post: 04-29-2008, 03:33 PM