- Conditional Variables and notify_all - 11 Updates
- locks and conditional variables: - 4 Updates
- Extracting the final 8 bits of a 64 bit integer. - 6 Updates
- What does this struct line do? - 4 Updates
| Doug Mika <dougmmika@gmail.com>: Jul 24 12:28PM -0700 Hi, I am trying to use two threads to solve the Fibanacci numbers (for educational purposes only). But why when in main() does my cvOne.notify_all() not notify my thread t1 that it may proceed past its wait()? (ie. why does the following program not proceed?) #include <iostream> #include <thread> #include <functional> #include <mutex> #include <condition_variable> using namespace std; void functionOne(); void functionTwo(); mutex mtx; condition_variable cvOne, cvTwo; long t1Value=1, t2Value=2; int main() { cout<<"Solution: "<<endl; thread t1(functionOne); thread t2(functionTwo); cvOne.notify_all(); t1.join(); t2.join(); cout<<" t1="<<t1Value<<endl; cout<<" t2="<<t2Value<<endl; return 0; } void functionOne(){ unique_lock<std::mutex> lck(mtx); while(t1Value<4000000){ cout<<"t1: inside while\n"; cvOne.wait(lck); cout<<"t1 is adding"<<endl; t1Value+=t2Value; cvTwo.notify_all(); } } void functionTwo(){ unique_lock<std::mutex> lck(mtx); while(t2Value<4000000){ cout<<"t2: inside while\n"; cvTwo.wait(lck); cout<<"t2 is adding"<<endl; t2Value+=t1Value; cvOne.notify_all(); } } |
| Melzzzzz <mel@zzzzz.com>: Jul 24 09:42PM +0200 On Fri, 24 Jul 2015 12:28:36 -0700 (PDT) > (for educational purposes only). But why when in main() does my > cvOne.notify_all() not notify my thread t1 that it may proceed past > its wait()? (ie. why does the following program not proceed?) Because both threads are waiting on condition. |
| Doug Mika <dougmmika@gmail.com>: Jul 24 12:48PM -0700 On Friday, July 24, 2015 at 2:43:04 PM UTC-5, Melzzzzz wrote: > > cvOne.notify_all() not notify my thread t1 that it may proceed past > > its wait()? (ie. why does the following program not proceed?) > Because both threads are waiting on condition. Yes, but thread 1 is waiting on condition variable cvOne (which I notify), and thread 2 is waiting on condition variable cvTwo (which thread 1 is to notify). Why doesn't thread 1 proceed if it's waiting on cvOne, and I notify cvOne in main? |
| Melzzzzz <mel@zzzzz.com>: Jul 24 09:57PM +0200 On Fri, 24 Jul 2015 12:48:55 -0700 (PDT) > notify), and thread 2 is waiting on condition variable cvTwo (which > thread 1 is to notify). Why doesn't thread 1 proceed if it's waiting > on cvOne, and I notify cvOne in main? Because there is no guarantee that you will be waiting on notify, that is, notify can be missed. |
| Doug Mika <dougmmika@gmail.com>: Jul 24 01:00PM -0700 On Friday, July 24, 2015 at 2:57:22 PM UTC-5, Melzzzzz wrote: > > on cvOne, and I notify cvOne in main? > Because there is no guarantee that you will be waiting on notify, that > is, notify can be missed. I don't understand? I wait on a conditional variable which I then notify with another thread. Shouldn't that cause the waiting thread to proceed? |
| Melzzzzz <mel@zzzzz.com>: Jul 24 10:03PM +0200 On Fri, 24 Jul 2015 13:00:38 -0700 (PDT) > I don't understand? I wait on a conditional variable which I then > notify with another thread. Shouldn't that cause the waiting thread > to proceed? Your mistake is that you wait unconditionally. That does not works. |
| Doug Mika <dougmmika@gmail.com>: Jul 24 01:14PM -0700 On Friday, July 24, 2015 at 3:03:51 PM UTC-5, Melzzzzz wrote: > > notify with another thread. Shouldn't that cause the waiting thread > > to proceed? > Your mistake is that you wait unconditionally. That does not works. I hate to say it, but I still don't think I get it. What would I have to change in the above code to make the threads calculate the Fibanacci series? |
| Melzzzzz <mel@zzzzz.com>: Jul 24 11:13PM +0200 On Fri, 24 Jul 2015 13:14:44 -0700 (PDT) > I hate to say it, but I still don't think I get it. What would I > have to change in the above code to make the threads calculate the > Fibanacci series? #include <iostream> #include <thread> #include <functional> #include <mutex> #include <condition_variable> using namespace std; void functionOne(); void functionTwo(); mutex mtx; condition_variable cv; long t1Value=1, t2Value=2; int main() { cout<<"Solution: "<<endl; thread t1(functionOne); thread t2(functionTwo); // cvOne.notify_all(); t1.join(); t2.join(); cout<<" t1="<<t1Value<<endl; cout<<" t2="<<t2Value<<endl; return 0; } bool added=false; void functionOne(){ unique_lock<std::mutex> lck(mtx); while(t1Value<4000000){ cout<<"t1: inside while\n"; cout<<"t1 is adding"<<endl; t1Value+=t2Value; added = true; cv.notify_one(); while(added)cv.wait(lck); } } void functionTwo(){ unique_lock<std::mutex> lck(mtx); while(t2Value<4000000){ cout<<"t2: inside while\n"; while(!added)cv.wait(lck); cout<<"t2 is adding"<<endl; t2Value+=t1Value; added = false; cv.notify_one(); } } |
| Melzzzzz <mel@zzzzz.com>: Jul 24 11:24PM +0200 On Fri, 24 Jul 2015 23:13:23 +0200 > > I hate to say it, but I still don't think I get it. What would I > > have to change in the above code to make the threads calculate the > > Fibanacci series? And if you want to harden it a bit: #include <iostream> #include <thread> #include <functional> #include <mutex> #include <condition_variable> using namespace std; void functionOne(); void functionTwo(); mutex mtx; condition_variable cv; long t1Value=1, t2Value=2; int main() { cout<<"Solution: "<<endl; thread t1(functionOne); thread t2(functionTwo); // cvOne.notify_all(); t1.join(); t2.join(); cout<<" t1="<<t1Value<<endl; cout<<" t2="<<t2Value<<endl; return 0; } bool added=false,exited=false; void functionOne(){ unique_lock<std::mutex> lck(mtx); while(t1Value<4000000 && !exited){ cout<<"t1: inside while\n"; cout<<"t1 is adding"<<endl; t1Value+=t2Value; added = true; cv.notify_one(); while(added && !exited)cv.wait(lck); } exited = true; } void functionTwo(){ unique_lock<std::mutex> lck(mtx); while(t2Value<4000000 && !exited){ cout<<"t2: inside while\n"; while(!added && !exited)cv.wait(lck); cout<<"t2 is adding"<<endl; t2Value+=t1Value; added = false; cv.notify_one(); } exited = true; } |
| Marcel Mueller <news.5.maazl@spamgourmet.org>: Jul 24 11:57PM +0200 On 24.07.15 21.28, Doug Mika wrote: > thread t1(functionOne); > thread t2(functionTwo); > cvOne.notify_all(); Here is a race condition. It is not ensured that t1 is already waiting for the condvar. > cvTwo.notify_all(); > } > } Marcel |
| Doug Mika <dougmmika@gmail.com>: Jul 24 03:15PM -0700 On Friday, July 24, 2015 at 2:28:53 PM UTC-5, Doug Mika wrote: > cvOne.notify_all(); > } > } Well, I figured out what the problem was with my original program, and I thought I'd post the reason why it failed. The main thread executed cvOne.notify_all() BEFORE thread t1 reached the point where it waits on the condition variable, that is, the notify was executed before even a condition variable was told to wait.;-) Thought I'd post for those interested. Ah, the simple mistakes. |
| Doug Mika <dougmmika@gmail.com>: Jul 24 12:17PM -0700 Hi to all, in the following program, would it be safe for me to remove the first line in the go() function (remove line: std::unique_lock<std::mutex> lck(mtx);)? Why do we need this line (ie why would we need to acquire the lock to change a boolean variable?) // condition_variable example #include <iostream> // std::cout #include <thread> // std::thread #include <mutex> // std::mutex, std::unique_lock #include <condition_variable> // std::condition_variable std::mutex mtx; std::condition_variable cv; bool ready = false; void print_id (int id) { std::unique_lock<std::mutex> lck(mtx); while (!ready) cv.wait(lck); // ... std::cout << "thread " << id << '\n'; } void go() { std::unique_lock<std::mutex> lck(mtx); ready = true; cv.notify_all(); } int main () { std::thread threads[10]; // spawn 10 threads: for (int i=0; i<10; ++i) threads[i] = std::thread(print_id,i); std::cout << "10 threads ready to race...\n"; go(); // go! for (auto& th : threads) th.join(); return 0; } |
| Melzzzzz <mel@zzzzz.com>: Jul 24 09:41PM +0200 On Fri, 24 Jul 2015 12:17:36 -0700 (PDT) > Hi to all, in the following program, would it be safe for me to > remove the first line in the go() function Yes. |
| "Chris M. Thomasson" <nospam@nospam.nospam>: Jul 24 02:28PM -0700 > > Hi to all, in the following program, would it be safe for me to > > remove the first line in the go() function > Yes. I think not, because a thread can miss a signal... Think about the following scenario: __________________________________________ void print_id (int id) { std::unique_lock<std::mutex> lck(mtx); while (!ready) { //HALT: cv.wait(lck); } // ... std::cout << "thread " << id << '\n'; } __________________________________________ If a thread stalls in HALT, and the flag is then changed to true and then a broadcast occurs, well, this thread will miss that broadcast. BAM! Deadlocked! ;^o |
| Melzzzzz <mel@zzzzz.com>: Jul 24 11:40PM +0200 On Fri, 24 Jul 2015 14:28:37 -0700 > will miss that broadcast. > BAM! Deadlocked! > ;^o Yes, I didn't thought about that, but in any way accesses to `ready` have to be protected by same mutex. |
| Paul <pepstein5@gmail.com>: Jul 24 09:45AM -0700 My code to extract the final 8 bits of a 64 bit integer is below: I can't believe there isn't something more elegant and concise, perhaps by using bitset? Any ideas? Or is the below just fine? Thanks, Paul const int bitShift = 8; auto extractFinalBits = [bitShift](uint64_t y)->uint8_t{int result = 0; for(int i = 0; i < bitShift; ++i) if( (1 << i ) & y) result += (1 << i); return result;}; |
| Victor Bazarov <v.bazarov@comcast.invalid>: Jul 24 01:06PM -0400 On 7/24/2015 12:45 PM, Paul wrote: > My code to extract the final 8 bits of a 64 bit integer is below: Which ones are "the final"? Lower or upper ones? > Paul > const int bitShift = 8; > auto extractFinalBits = [bitShift](uint64_t y)->uint8_t{int result = 0; for(int i = 0; i < bitShift; ++i) if( (1 << i ) & y) result += (1 << i); return result;}; Do you think it's possible for you to wrap your lines and indent so the code is actually readable? And what is your test? To post a question on code (whether it works or doesn't) you ought to post a complete (preferably compilable) program... Back to your question, doesn't shift to the right 56 bits, then bitwise AND with 0xff, work? uint8_t res = uint8_t((y >> 56) & 0xff); maybe? V -- I do not respond to top-posted replies, please don't ask |
| scott@slp53.sl.home (Scott Lurndal): Jul 24 05:56PM >Paul >const int bitShift = 8; > auto extractFinalBits = [bitShift](uint64_t y)->uint8_t{int result = 0; for(int i = 0; i < bitShift; ++i) if( (1 << i ) & y) result += (1 << i); return result;}; long long data64bit; least significant 8 bits = data64bit & 0xff; most significant 8 bits = data64bit >> 56; |
| Marcel Mueller <news.5.maazl@spamgourmet.org>: Jul 24 09:02PM +0200 On 24.07.15 19.56, Scott Lurndal wrote: > long long data64bit; > least significant 8 bits = data64bit & 0xff; > most significant 8 bits = data64bit >> 56; The latter might give unexpected results because of the signed shift if assigned to something with more than 8 bits. Marcel |
| Robert Wessel <robertwessel2@yahoo.com>: Jul 24 03:07PM -0500 On Fri, 24 Jul 2015 21:02:31 +0200, Marcel Mueller >> most significant 8 bits = data64bit >> 56; >The latter might give unexpected results because of the signed shift if >assigned to something with more than 8 bits. The OP's original code was shifting signed integers as well. |
| Victor Bazarov <v.bazarov@comcast.invalid>: Jul 24 04:52PM -0400 On 7/24/2015 4:07 PM, Robert Wessel wrote: >> The latter might give unexpected results because of the signed shift if >> assigned to something with more than 8 bits. > The OP's original code was shifting signed integers as well. And it likely had undefined behavior if the 'int' was smaller than 64 bits... V -- I do not respond to top-posted replies, please don't ask |
| Richard Damon <Richard@Damon-Family.org>: Jul 24 01:25AM -0400 On 7/23/15 4:13 PM, Ian Collins wrote: > for example where a struct and a function have the same name. > This example isn't one of them... Both "struct" and in my opinion the > use of std:: are superfluous in this case. The struct wouldn't be superfluous if the definition of std::tm hasn't been introduced yet (making it a forward declaration). |
| "Lőrinczy Zsigmond" <nospam@for.me>: Jul 24 08:44AM +0200 > The upshot is that code that includes e.g. <ctime> may work with one > compiler when using an unqualified name, but may fail to compile with > some other compiler, both standard-conforming. Well, let's not forget that C++ haven't reached mature status yet (its only 30 years old, after all), time will solve this question. |
| "Öö Tiib" <ootiib@hot.ee>: Jul 24 01:45AM -0700 On Friday, 24 July 2015 08:26:01 UTC+3, Richard Damon wrote: > > use of std:: are superfluous in this case. > The struct wouldn't be superfluous if the definition of std::tm hasn't > been introduced yet (making it a forward declaration). That is not a forward-declaration of 'std::tm' in C++. If it hasn't been introduced yet then the compiler should not parse it. Forward-declaration of 'std::tm' looks like that in C++: namespace std { struct tm; } std::tm* ptm; |
| woodbrian77@gmail.com: Jul 24 08:30AM -0700 On Thursday, July 23, 2015 at 6:45:22 PM UTC-5, Alf P. Steinbach wrote: > minimized by using the ".h" headers. It also yields less verbose code. > And it teaches one to generally avoid using the names defined by the C > library, for other things, i.e. treating them as reserved names. I took similar advice from you a few years ago and stopped using ctime and friends. I would write the code in question as: #include <time.h> ::tm* ptm = ::localtime(&tt); Brian Ebenezer Enterprises - With "friends" like Obama who needs enemies? http://webEbenezer.net |
| You received this digest because you're subscribed to updates for this group. You can change your settings on the group membership page. To unsubscribe from this group and stop receiving emails from it send an email to comp.lang.c+++unsubscribe@googlegroups.com. |
No comments:
Post a Comment