Friday, July 24, 2015

Digest for comp.lang.c++@googlegroups.com - 25 updates in 4 topics

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: