Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

concurrent_vector invalid data

using : VC++ 2013

concurrency::concurrent_vector<datanode*> dtnodelst

Occasionally when I do dtnodelst->at(i) .... I am getting an invalid address (0XCDCD.. ofc) which shouldn't be the case cause after I do push back, I never delete or remove any of the itms ( even if I delete it should have returned the deleted old address... but I am not ever deleting so that is not even the case )

dtnodelst itm = new dtnodelst ();
....
dtnodelst->push_back(itm);

any ideas on what might be happening ?

p.s. I am using windows thread pool. some times .. I can do 8million inserts and find and everything goes fine .... but sometimes even 200 inserts and finds will fail. I am kind of lost. any help would be awesomely appreciated!!

thanks and best regards

actual code as an fyi

p.s. am I missing something or is it pain in the ass to past code with proper formatting ? I remember it being auto align before ... -_-

struct datanode {       
     volatile int nodeval;
     T val;
};
concurrency::concurrent_vector<datanode*> lst
inline T find(UINT32 key)
{
    for (int i = 0; i < lst->size(); i++)
    {
       datanode* nd = lst->at(i);
       //nd is invalid sometimes
       if (nd)  
       if (nd->nodeval == key)
       {
         return (nd->val);
       }
    }
    return NULL;
}
inline T insert_nonunique(UINT32 key, T val){
   datanode* itm = new datanode();
   itm->val = val;
   itm->nodeval = key;
   lst->push_back(itm);
   _updated(lst);                       
   return val;
}
like image 282
2340C Avatar asked Aug 01 '26 15:08

2340C


1 Answers

The problem is using of concurrent_vector::size() which is not fully thread-safe as you can get reference to not yet constructed elements (where memory contains garbage). Microsoft PPL library (which provides it in concurrency:: namespace) uses Intel TBB implementation of concurrent_vector and TBB Reference says:

size_type size() const | Returns: Number of elements in the vector. The result may include elements that are allocated but still under construction by concurrent calls to any of the growth methods.

Please see my blog for more explanation and possible solutions.

In TBB, the most reasonable solution is to use tbb::zero_allocator as underlying allocator of concurrent_vector in order to fill newly allocated memory with zeroes before size() will count it too.

concurrent_vector<datanode*, tbb::zero_allocator<datanode*> > lst;

Then, the condition if (nd) will filter out not-yet-ready elements.

like image 88
Anton Avatar answered Aug 03 '26 03:08

Anton



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!