0

I have a project where we want to provide to use threads to speed up everything. We want to be able to call this function in individual threads:

Request& Filter::processRequest(Request& req)

Therefore I packed the function in lambda expression to have access to the return value.

I now get the following runtime error:

  glibc detected ... double free or corruption (!prev): ...

When I uncomment the line where I add the thread to the group everything works fine.

boost::thread_group thread;
for (std::set<boost::shared_ptr<Filter> >::iterator i = sources_.begin();
    i != sources_.end(); ++i) {
         Request ret
         thread.add_thread(new boost::thread(boost::lambda::var(ret) = 
            (*i)->processRequest(req)));
         req+=ret;
         ...
}
thread.join_all();

What can be the reason for this runtime error. Or is there another way to put this function in individual threads?

tune2fs
  • 7,605
  • 5
  • 41
  • 57
  • What do you expect `boost::lambda::var(ret) = (*i)->processRequest(req)` to do? You are in a loop adding N threads...so where are the N stable "ret" places to store the results by reference? – HostileFork says dont trust SE Oct 31 '11 at 20:01
  • I added in the code above what I want to do with ret. I want to add it up to the req. I thought a copy of ret is put in every thread or is this assumption wrong? – tune2fs Oct 31 '11 at 20:05
  • 1
    I'm not really a `boost::lambda` user and I've only tinkered with `boost::thread` a little, so I don't actually know much about your approach (though it strikes me as "no way that can work"). If you fire off an asynchronous task you cannot use its result without some sort of assurance that it has finished its computation. And the documentation suggest that `boost::lambda::var` takes an argument by reference (if it "copied" it, how would the caller connect to the copy?)...so you really only have one `Request ret;` which is "alive" per iteration of the loop. – HostileFork says dont trust SE Oct 31 '11 at 20:13
  • I fear I have to redesign my program to void functions. Thanks for the reply. I hope there might be some other suggestions otherwise I will close this question. – tune2fs Oct 31 '11 at 20:15

1 Answers1

1

If this sort of technique were to work at all, you would need multiple ret values that you could stably reference (one for each thread of execution). And you'd have to wait until after your thread join completed until you used those values.

A simple modification you can try would just be to make a vector outside of the loop of vector<Request> retValues...and then add an element to the vector each time you add_thread and pass a reference to that element. Then if you wait until after the join to use the values, perhaps it would work?

boost::thread_group thread;
vector<Request> retValues;
for (std::set<boost::shared_ptr<Filter> >::iterator i = sources_.begin();
    i != sources_.end(); ++i) {
         retValues.push_back(0);
         thread.add_thread(new boost::thread(
            boost::lambda::var(retValues.back()) = 
            (*i)->processRequest(req)));
         ...
}
thread.join_all();
// retValues safe to use here...

(Note: Using boost::lambda is probably not necessary; you can use boost::bind to connect to a worker class that stores the result:

Getting return value from a boost::threaded member function?

...but really, no matter what you'll need a separate variable per thread to store the result...whose lifetime lasts long enough for the thread to be able to write to it.)

Community
  • 1
  • 1
  • I do not think that deriving from `boost::thread` is a good idea, as it has no virtual destructor. Or did I get this wrong? – tune2fs Oct 31 '11 at 21:58
  • Hm, looks like you're right. Weird. I guess it's quite different from QThread...let me look at it again... http://doc.qt.nokia.com/latest/qthread.html#details – HostileFork says dont trust SE Oct 31 '11 at 22:22
  • Thanks for the reply. I will give it a try. I will also have a look at QThreads. – tune2fs Oct 31 '11 at 23:04
  • I'm in the Qt-universe for the most part, so I enjoy it...looking further at `boost::thread` I'm remembering now you couldn't derive from them. :-/ Anyway if you're ever interested in messing around with the Qt examples, the fastest way is with Qt Creator...single push-button cloning of the samples into a new environment and easy builds: http://qt.nokia.com/products/developer-tools/ – HostileFork says dont trust SE Oct 31 '11 at 23:10