[thread] basic mutex problem

Hi Boost.Thread maintainer(s)/expert(s)/user(s) like me, I'm having an issue with boost::mutex. I'm not really an expert in concurrency, and there's something wrong with my thread_db library, so I'm having some trouble debugging (for now). I tend to think it's something in my code, but I thought maybe someone on the list would take a look at it. The code is pretty minimal, but let me know if I should reduce it further. I'm leaving out the #includes, because I'm pretty sure those are ok: using namespace std; using namespace boost::phoenix; namespace phoenix_args = boost::phoenix::arg_names; namespace posix_time = boost::posix_time; boost::mutex g_mutex; struct random_activity_planner { random_activity_planner(vector<activity>& a, posix_time::ptime o) : activities(a) , origin(o) {} void operator()() { g_mutex.lock(); posix_time::ptime start(origin + posix_time::seconds(rand() % 1000)); posix_time::ptime end(start + posix_time::seconds(rand() % 1000)); activities.push_back(activity(start, end)); g_mutex.unlock(); } vector<activity>& activities; const posix_time::ptime& origin; }; int main(int argc, char** argv) { if(argc != 2) return 1; size_t activity_count = boost::lexical_cast<size_t>(argv[1]); vector<activity> activities; boost::thread_group random_activity_planners; posix_time::ptime origin(posix_time::second_clock::universal_time()); srand(time(NULL)); for(size_t i = 0; i < activity_count; ++i) { random_activity_planners.create_thread(random_activity_planner(activities, origin)); } random_activity_planners.join_all(); cout << "all activities: " << endl; for_each(activities.begin() , activities.end() , cout << phoenix_args::_1 << endl); vector<activity> schedule; greedy_activity_selector(activities.begin() , activities.end() , back_inserter(schedule)); cout << "scheduled activities: " << endl; for_each(schedule.begin() , schedule.end() , cout << phoenix_args::_1 << endl); return 0; } [END] The problem is that the last "activity" is not being pushed onto the shared vector in the . I'm sure there are some stylistic problems with the code, but its purpose is just to demonstrate an algorithm. At the following for_each() call: for_each(activities.begin() , activities.end() , cout << phoenix_args::_1 << endl); I find out, via a gregorian::bad_year exception, that the final activity has not been initialized. I have omitted the definition for activity, but it's pretty simple. It has only one member (a posix_time::duration that defaults to neg_infin => pos_infin ), which is why I suspect that the final call to random_activity_selector::operator() is not completing before the for_each() call that succeeds it in the source. I thought that join_all() would prevent this from happening. Is there something wrong with my code? I left some stuff out, because I didn't want to inundate the reader with irrelevant details, so please let me know if I left out anything crucial. Also, I am aware that I don't need to be using threads here, but I am, and I don't understand why it's not working. Thanks! Greg

On Fri, Aug 12, 2011 at 3:15 PM, Christian Holmquist <c.holmquist@gmail.com> wrote:
Also, I am aware that I don't need to be using threads here, but I am, and I don't understand why it's not working.
Does the code do the right thing if you remove the threads and just call random_activity_planner(activities,origin)(); directly?
Hi Christian, Thanks for the quick response! I tried that and it behaves as expected if I remove the uses of boost::thread_group. That is, the container grows to activity_count elements and they are all properly initialized with random elements. Greg
- Christian _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

What do I see is that you hold const reference to ptime in random_activity_planner, but pass it by value to ctor. This isn't correct, as const reference prolongs life of ctor parameter only until ctor body end. Try changing either of these places (hold by value or pass by cref). Looks like when you don't threads stack place where copied ptime lived isn't reused, but with threads it is rewritten. 2011/8/13 Greg Rubino <bibil.thaysose@gmail.com>
On Fri, Aug 12, 2011 at 3:15 PM, Christian Holmquist <c.holmquist@gmail.com> wrote:
Also, I am aware that I don't need to be using threads here, but I am, and I don't understand why it's not working.
Does the code do the right thing if you remove the threads and just call random_activity_planner(activities,origin)(); directly?
Hi Christian,
Thanks for the quick response! I tried that and it behaves as expected if I remove the uses of boost::thread_group. That is, the container grows to activity_count elements and they are all properly initialized with random elements.
Greg
- Christian _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

2011/8/13 Юрій Зубрицький <mt.wizard@gmail.com>:
What do I see is that you hold const reference to ptime in random_activity_planner, but pass it by value to ctor. This isn't correct, as const reference prolongs life of ctor parameter only until ctor body end. Try changing either of these places (hold by value or pass by cref). Looks like when you don't threads stack place where copied ptime lived isn't reused, but with threads it is rewritten.
Aha, my mistake! Thanks for pointing that out! I think I'd rather pass by ref, I will try it soon. Thanks again, Greg
2011/8/13 Greg Rubino <bibil.thaysose@gmail.com>
On Fri, Aug 12, 2011 at 3:15 PM, Christian Holmquist <c.holmquist@gmail.com> wrote:
Also, I am aware that I don't need to be using threads here, but I am, and I don't understand why it's not working.
Does the code do the right thing if you remove the threads and just call random_activity_planner(activities,origin)(); directly?
Hi Christian,
Thanks for the quick response! I tried that and it behaves as expected if I remove the uses of boost::thread_group. That is, the container grows to activity_count elements and they are all properly initialized with random elements.
Greg
- Christian _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

On Sat, Aug 13, 2011 at 9:53 AM, Greg Rubino <bibil.thaysose@gmail.com> wrote:
2011/8/13 Юрій Зубрицький <mt.wizard@gmail.com>:
What do I see is that you hold const reference to ptime in random_activity_planner, but pass it by value to ctor. This isn't correct, as const reference prolongs life of ctor parameter only until ctor body end. Try changing either of these places (hold by value or pass by cref). Looks like when you don't threads stack place where copied ptime lived isn't reused, but with threads it is rewritten.
Aha, my mistake! Thanks for pointing that out! I think I'd rather pass by ref, I will try it soon.
Yep, that worked... How embarrassing... Thanks again!
Thanks again,
Greg
2011/8/13 Greg Rubino <bibil.thaysose@gmail.com>
On Fri, Aug 12, 2011 at 3:15 PM, Christian Holmquist <c.holmquist@gmail.com> wrote:
Also, I am aware that I don't need to be using threads here, but I am, and I don't understand why it's not working.
Does the code do the right thing if you remove the threads and just call random_activity_planner(activities,origin)(); directly?
Hi Christian,
Thanks for the quick response! I tried that and it behaves as expected if I remove the uses of boost::thread_group. That is, the container grows to activity_count elements and they are all properly initialized with random elements.
Greg
- Christian _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

On 08/12/2011 07:59 PM, Greg Rubino wrote:
struct random_activity_planner {
random_activity_planner(vector<activity>& a, posix_time::ptime o) : activities(a) , origin(o) {}
void operator()() {
g_mutex.lock(); posix_time::ptime start(origin + posix_time::seconds(rand() % 1000)); posix_time::ptime end(start + posix_time::seconds(rand() % 1000)); activities.push_back(activity(start, end)); g_mutex.unlock();
}
vector<activity>& activities; const posix_time::ptime& origin;
};
You store a dangling reference to a temporary object in the random_activity_planner::origin. Thus the result of operator() is undefined.
participants (4)
-
Andrey Semashev
-
Christian Holmquist
-
Greg Rubino
-
Юрій Зубрицький