threadChannel example confusing variable names

I am trying to understand the thread channel example but it is a bit confusing as there are some variables that have the same name.

in the ImgAnalysisThread.h file there is a declaration:

ofPixels pixels;

But in the threaded function another ofPixles object is created, also called pixels.

void ImgAnalysisThread::threadedFunction(){
    // wait until there's a new frame
    // this blocks the thread, so it doesn't use
    // the CPU at all, until a frame arrives.
    // also receive doesn't allocate or make any copies
    ofPixels pixels;
    while(toAnalyze.receive(pixels)){
        // we have a new frame, process it, the analysis
        // here is just a thresholding for the sake of
        // simplicity
        pixels.setImageType(OF_IMAGE_GRAYSCALE);
        for(auto & p: pixels){
            if(p > 80) p = 255;
            else p = 0;
        }

        // once processed send the result back to the
        // main thread. in c++11 we can move it to
        // avoid a copy
#if __cplusplus>=201103
        analyzed.send(std::move(pixels));
#else
        analyzed.send(pixels);
#endif
	}
}

As I am trying to build something this makes it hard to understand. Are the references to the object called pixels in the threaded function the local variable declared inside the function or to the variable declared in ImgAnalysisThread.h?

Hi, those two “pixels” are different objects, although because of how std::move works the pixels in the threaded function end up being the ones in the class variable. You can name these with different names, that does not matter, but it is important that you create that variable inside the threaded function, because then it will be moved and become invalid.

Cheers, I understood they were different objects. but the fact that they have the same name makes this example harder to understand. Am I right in understanding that all the “pixels” objects used in the threaded function are the locally declared variable? So it could be written like this:

void ImgAnalysisThread::threadedFunction(){
    // wait until there's a new frame
    // this blocks the thread, so it doesn't use
    // the CPU at all, until a frame arrives.
    // also receive doesn't allocate or make any copies
    ofPixels threadPixels;
    while(toAnalyze.receive(threadPixels)){
        // we have a new frame, process it, the analysis
        // here is just a thresholding for the sake of
        // simplicity
        threadPixels.setImageType(OF_IMAGE_GRAYSCALE);
        for(auto & p: threadPixels){
            if(p > 80) p = 255;
            else p = 0;
        }

        // once processed send the result back to the
        // main thread. in c++11 we can move it to
        // avoid a copy
#if __cplusplus>=201103
        analyzed.send(std::move(threadPixels));
#else
        analyzed.send(threadPixels);
#endif
	}
}

In the case of the original code, with 2 variables with the same name, how does the compiler know which one to use? If I rename the locally declared “pixels” to something else the application still works. (like below), and the locally declared ofPixels object is not used at all.

void ImgAnalysisThread::threadedFunction(){
    // wait until there's a new frame
    // this blocks the thread, so it doesn't use
    // the CPU at all, until a frame arrives.
    // also receive doesn't allocate or make any copies
    ofPixels pixels2;
    while(toAnalyze.receive(pixels)){
        // we have a new frame, process it, the analysis
        // here is just a thresholding for the sake of
        // simplicity
        pixels.setImageType(OF_IMAGE_GRAYSCALE);
        for(auto & p: pixels){
            if(p > 80) p = 255;
            else p = 0;
        }

        // once processed send the result back to the
        // main thread. in c++11 we can move it to
        // avoid a copy
#if __cplusplus>=201103
        analyzed.send(std::move(pixels));
#else
        analyzed.send(pixels);
#endif
	}
}

yes, you can write it like that.

because one is a class member and the other is the local variable. In case that you have two variables named the same the compiler assumes that you are refering to the local. If you want to refer to the class variable you would need to use this->. for example, inside the threadedFunction

ofPixels pixels;
pixels.setImage(....);// local variable, the one declared above
this->pixels.setImage(....);// class variable, declared in the header file.

yes, these are different objects. The thing is that when using std::move the compiler might swap the memory of the objects, in order to avoid copying but this might lead into having an unusable object after it is done.

Sure, this will work but it might lead into some threading issues as the class variable is accessed from different threads. The whole point of the threaded channel is to avoid threading issues with shared memory while still make it as optimized as possible.