f



Threads and Object Methods

Why can't the threads library handle object methods that are not static
to the class


such as 	std::thread paint(read_chunk);
			paint.detach();


where read_chunk is an method of an object of class Images.

| gcc -M *.cpp >make.deps
|| g++   -Wall -ggdb  -pg -pthread -o png_proj.o -c png_proj.cpp
|| png_proj.cpp: In member function ‘void png_proj::Image::read_chunk()’:
png_proj.cpp|160 col 32| error: invalid use of non-static member function
‘void png_proj::Image::read_chunk()’
||     std::thread paint(read_chunk);
||                                 ^
png_proj.cpp|109 col 7| note: declared here
||   void Image::read_chunk (  )
0
ruben
12/18/2016 9:48:58 AM
comp.lang.c++ 49423 articles. 7 followers. Post Follow

9 Replies
721 Views

Similar Articles

[PageSpeed] 7

On Sunday, 18 December 2016 11:49:07 UTC+2, ruben safir  wrote:
> Why can't the threads library handle object methods that are not static
> to the class
> 
> 
> such as 	std::thread paint(read_chunk);
> 			paint.detach();
> 
> 
> where read_chunk is an method of an object of class Images.

Again some voodoo trying-out nonsense that we can't even 
copy-paste and run? :-/ The 'std::thread' *can* use non-static
methods. However the caller has to supply arguments (starting 
from 'this') to it.

    #include <thread>
    #include <iostream>

    struct Reader 
    {
        void read_chunk()
        {
            std::cout << "quod erat demonstrandum" << std::endl;
        }
    };

    int main()
    {
        std::thread paint(&Reader::read_chunk, Reader());
        paint.join();
    }

See? It is easy peasy.
0
UTF
12/18/2016 11:09:04 AM
On 12/18/2016 06:09 AM, Öö Tiib wrote:
> On Sunday, 18 December 2016 11:49:07 UTC+2, ruben safir  wrote:
>> Why can't the threads library handle object methods that are not static
>> to the class
>>
>>
>> such as 	std::thread paint(read_chunk);
>> 			paint.detach();
>>
>>
>> where read_chunk is an method of an object of class Images.
> 
> Again some voodoo trying-out nonsense that we can't even 
> copy-paste and run? :-/ The 'std::thread' *can* use non-static
> methods. However the caller has to supply arguments (starting 
> from 'this') to it.
> 
>     #include <thread>
>     #include <iostream>
> 
>     struct Reader 
>     {
>         void read_chunk()
>         {
>             std::cout << "quod erat demonstrandum" << std::endl;
>         }
>     };
> 
>     int main()
>     {
>         std::thread paint(&Reader::read_chunk, Reader());
>         paint.join();
>     }
> 
> See? It is easy peasy.
> 

if you call it like that it loses its context of the object that
instantated it which, especially in this case, it needs  in order to do
its job.
0
ruben
12/18/2016 2:36:24 PM
On Sunday, 18 December 2016 16:36:32 UTC+2, ruben safir  wrote:
> On 12/18/2016 06:09 AM, =C3=96=C3=B6 Tiib wrote:
> > On Sunday, 18 December 2016 11:49:07 UTC+2, ruben safir  wrote:
> >> Why can't the threads library handle object methods that are not stati=
c
> >> to the class
> >>
> >>
> >> such as 	std::thread paint(read_chunk);
> >> 			paint.detach();
> >>
> >>
> >> where read_chunk is an method of an object of class Images.
> >=20
> > Again some voodoo trying-out nonsense that we can't even=20
> > copy-paste and run? :-/ The 'std::thread' *can* use non-static
> > methods. However the caller has to supply arguments (starting=20
> > from 'this') to it.
> >=20
> >     #include <thread>
> >     #include <iostream>
> >=20
> >     struct Reader=20
> >     {
> >         void read_chunk()
> >         {
> >             std::cout << "quod erat demonstrandum" << std::endl;
> >         }
> >     };
> >=20
> >     int main()
> >     {
> >         std::thread paint(&Reader::read_chunk, Reader());
> >         paint.join();
> >     }
> >=20
> > See? It is easy peasy.
> >=20
>=20
> if you call it like that it loses its context of the object that
> instantated it which, especially in this case, it needs  in order to do
> its job.

Reading comprehension problem detected.  Nah, just drop programming.
There are easier jobs. Programming is not for you, sorry.
0
UTF
12/18/2016 3:54:04 PM
On 12/18/2016 10:54 AM, Öö Tiib wrote:
>> if you call it like that it loses its context of the object that
>> instantated it which, especially in this case, it needs  in order to do
>> its job.
> Reading comprehension problem detected.  Nah, just drop programming.
> There are easier jobs. Programming is not for you, sorry.


there is a big difference between

CLASS::Method

and

object->method
which can be
this->method

0
ruben
12/18/2016 4:08:00 PM
On Sunday, 18 December 2016 18:08:09 UTC+2, ruben safir  wrote:
> On 12/18/2016 10:54 AM, =C3=96=C3=B6 Tiib wrote:
> >> if you call it like that it loses its context of the object that
> >> instantated it which, especially in this case, it needs  in order to d=
o
> >> its job.
> > Reading comprehension problem detected.  Nah, just drop programming.
> > There are easier jobs. Programming is not for you, sorry.
>=20
>=20
> there is a big difference between
>=20
> CLASS::Method
>=20
> and
>=20
> object->method
> which can be
> this->method

Large difference. That '::NAMESPACE::CLASS::method' is member funtion's
fully qualified name and so can be used as expression of that type.
That 'pointer->method' however is a sub-fragment of some expression and
means nothing on its own.=20
Note that you still fail to post coherent questions what about it
does confuse you.
0
UTF
12/18/2016 5:01:09 PM
On 18/12/2016 14:36, ruben safir wrote:
> On 12/18/2016 06:09 AM, Öö Tiib wrote:
>> On Sunday, 18 December 2016 11:49:07 UTC+2, ruben safir  wrote:
>>> Why can't the threads library handle object methods that are not static
>>> to the class
>>>
>>>
>>> such as 	std::thread paint(read_chunk);
>>> 			paint.detach();
>>>
>>>
>>> where read_chunk is an method of an object of class Images.
>>
>> Again some voodoo trying-out nonsense that we can't even
>> copy-paste and run? :-/ The 'std::thread' *can* use non-static
>> methods. However the caller has to supply arguments (starting
>> from 'this') to it.
>>
>>     #include <thread>
>>     #include <iostream>
>>
>>     struct Reader
>>     {
>>         void read_chunk()
>>         {
>>             std::cout << "quod erat demonstrandum" << std::endl;
>>         }
>>     };
>>
>>     int main()
>>     {
>>         std::thread paint(&Reader::read_chunk, Reader());
>>         paint.join();
>>     }
>>
>> See? It is easy peasy.
>>
>
> if you call it like that it loses its context of the object that
> instantated it which, especially in this case, it needs  in order to do
> its job.
>
You're missing the second parameter to the function. Perhaps if he'd written

	Reader foo;
	std::thread paint(&reader::read_chunk, &foo);

it would have made more sense to you. You can pass args to the function, 
which may include a pointer to an object of the type. I prefer to pass a 
pointer to a static member function for the first parameter which takes 
a pointer to an object of the class and invokes a corresponding 
non-static member.

Andy

0
Vir
12/18/2016 9:40:31 PM
On 12/18/2016 04:40 PM, Vir Campestris wrote:
> You're missing the second parameter to the function. Perhaps if he'd
> written
> 
>     Reader foo;
>     std::thread paint(&reader::read_chunk, &foo);
> 
> it would have made more sense to you. You can pass args to the function,
> which may include a pointer to an object of the type. I prefer to pass a
> pointer to a static member function for the first parameter which takes
> a pointer to an object of the class and invokes a corresponding
> non-static member.
> 
> Andy


Not really.  There are data members of the object that are dynamically altered 
and stored in the private encapsulation of the object which a a method handles 
inside the thread.  read_chunk is a member of the Image class and it is 
assigned indexes within a block of memory, and a chunk of raw data.  It 
interprets the block of memory and writes to the block of memory which is 
private to an instance of Image.  The idea was to create a number of threads 
that write to the block, each in its assigned area, simultaneously in parallel.  

read_chunk looks like this

void Image::read_chunk (  )
		{
			CHUNKY * new_chunk = set_chunk();//the chunk construction call is within
          std::cout << "Type "  << new_chunk->type() << std::endl;
          std::cout << "Length "  << new_chunk->length() << std::endl;
          std::cout << "CRC "  << new_chunk->cr() << std::endl;
          
	  if(new_chunk->type() == "IHDR")
	   {
             std::cout << "we have a header chunk " << std::endl;
             IHDR * head = new IHDR;
             unsigned char * cur = new_chunk->data(); //NOTE:: cur is now point at the new heap for in CHNUNK and not the index for the file
             head->width = ntohl( *(reinterpret_cast<int32_t *>(cur ) ) );
             cur += 4;
             head->height = ntohl( *(reinterpret_cast<int32_t *>( cur  ) ) );
             cur += 4;
             head->depth = *( reinterpret_cast<int8_t *>( cur  ) );
             cur++;
             head->color_type = *( reinterpret_cast<int8_t *>( cur  ) );
             cur++;
             head->compress = *( reinterpret_cast<int8_t *>( cur  ) );
             cur++;
             head->filter = *( reinterpret_cast<int8_t *>( cur  ) );
             cur++;
             head->interlace = *( reinterpret_cast<int8_t *>( cur  ) );
             cur++;
 
             canvas_size = static_cast<long int>(head->height) * static_cast<long int>(head->width) * blank_canvas_psize(*head);
             canvas = new unsigned char[ canvas_size ];
             std::cout << "Canvas made: " << static_cast<long int>(head->height) * static_cast<long int>(head->width) * blank_canvas_psize(*head) << " bytes" << std::endl;
             //char tmp;
             //std::cin >> tmp;
          }

          if(new_chunk->type() == "IDAT")
           {
             //confusion here.  Do we want to create a new data array on the heap to pass through to the images for placement on canvas?
             //No.  Not needed.  Use the CHUNKY object instead. It already has the data array. Have the chunky obj schedule itself for 
	     //copy to the canvas
	    set_canvas(*new_chunk); //SET MUTEX LOCK and assign canvas index to a CHUNKY object
           }
			 
	  if(new_chunk->type() == "IEND")
	   {
		std::cout << "we have a IEND chunk " << std::endl;
			//set_index(get_index() + 12 + new_chunk->length() ) ;
		return;
	    }
	std::thread ctch = getNext(); //calls this method in recursion
	ctch.join(); //I want this to be detached
	//read_chunk();
	return ;
	}		/* -----  end of method Image::read_chunk  ----- */


0
ruben
12/19/2016 2:15:11 AM
On 12/18/2016 09:15 PM, ruben safir wrote:
> On 12/18/2016 04:40 PM, Vir Campestris wrote:
>> You're missing the second parameter to the function. Perhaps if he'd
>> written
>>
>>     Reader foo;
>>     std::thread paint(&reader::read_chunk, &foo);
>>
>> it would have made more sense to you. You can pass args to the function,
>> which may include a pointer to an object of the type. I prefer to pass a
>> pointer to a static member function for the first parameter which takes
>> a pointer to an object of the class and invokes a corresponding
>> non-static member.
>>
>> Andy
> 
> 
> Not really.  There are data members of the object that are dynamically altered 
> and stored in the private encapsulation of the object which a a method handles 
> inside the thread.  read_chunk is a member of the Image class and it is 
> assigned indexes within a block of memory, and a chunk of raw data.  It 
> interprets the block of memory and writes to the block of memory which is 
> private to an instance of Image.  The idea was to create a number of threads 
> that write to the block, each in its assigned area, simultaneously in parallel.  
> 
> read_chunk looks like this
> 
> void Image::read_chunk (  )
> 		{
> 			CHUNKY * new_chunk = set_chunk();//the chunk construction call is within
>           std::cout << "Type "  << new_chunk->type() << std::endl;
>           std::cout << "Length "  << new_chunk->length() << std::endl;
>           std::cout << "CRC "  << new_chunk->cr() << std::endl;
>           
> 	  if(new_chunk->type() == "IHDR")
> 	   {
>              std::cout << "we have a header chunk " << std::endl;
>              IHDR * head = new IHDR;
>              unsigned char * cur = new_chunk->data(); //NOTE:: cur is now point at the new heap for in CHNUNK and not the index for the file
>              head->width = ntohl( *(reinterpret_cast<int32_t *>(cur ) ) );
>              cur += 4;
>              head->height = ntohl( *(reinterpret_cast<int32_t *>( cur  ) ) );
>              cur += 4;
>              head->depth = *( reinterpret_cast<int8_t *>( cur  ) );
>              cur++;
>              head->color_type = *( reinterpret_cast<int8_t *>( cur  ) );
>              cur++;
>              head->compress = *( reinterpret_cast<int8_t *>( cur  ) );
>              cur++;
>              head->filter = *( reinterpret_cast<int8_t *>( cur  ) );
>              cur++;
>              head->interlace = *( reinterpret_cast<int8_t *>( cur  ) );
>              cur++;
>  
>              canvas_size = static_cast<long int>(head->height) * static_cast<long int>(head->width) * blank_canvas_psize(*head);
>              canvas = new unsigned char[ canvas_size ];
>              std::cout << "Canvas made: " << static_cast<long int>(head->height) * static_cast<long int>(head->width) * blank_canvas_psize(*head) << " bytes" << std::endl;
>              //char tmp;
>              //std::cin >> tmp;
>           }
> 
>           if(new_chunk->type() == "IDAT")
>            {
>              //confusion here.  Do we want to create a new data array on the heap to pass through to the images for placement on canvas?
>              //No.  Not needed.  Use the CHUNKY object instead. It already has the data array. Have the chunky obj schedule itself for 
> 	     //copy to the canvas
> 	    set_canvas(*new_chunk); //SET MUTEX LOCK and assign canvas index to a CHUNKY object
>            }
> 			 
> 	  if(new_chunk->type() == "IEND")
> 	   {
> 		std::cout << "we have a IEND chunk " << std::endl;
> 			//set_index(get_index() + 12 + new_chunk->length() ) ;
> 		return;
> 	    }
> 	std::thread ctch = getNext(); //calls this method in recursion
> 	ctch.join(); //I want this to be detached
> 	//read_chunk();
> 	return ;
> 	}		/* -----  end of method Image::read_chunk  ----- */
> 
> 


and I had to use a lamda for the thread

	std::thread Image::getNext ()
		{
			std::cout << std::endl << "getNext" << std::endl;
//			next_index();
			std::thread paint( [this]{ read_chunk(); } ); 
			std::cout << std::endl << "**created thread**" << paint.get_id() <<  std::endl;
			return paint;
		}		/* -----  end of method Image::getNext  ----- */


0
ruben
12/19/2016 2:23:30 AM
ruben safir <ruben@mrbrklyn.com> writes:
>On 12/18/2016 04:40 PM, Vir Campestris wrote:
>> You're missing the second parameter to the function. Perhaps if he'd
>> written
>> 
>>     Reader foo;
>>     std::thread paint(&reader::read_chunk, &foo);
>> 
>> it would have made more sense to you. You can pass args to the function,
>> which may include a pointer to an object of the type. I prefer to pass a
>> pointer to a static member function for the first parameter which takes
>> a pointer to an object of the class and invokes a corresponding
>> non-static member.
>> 
>> Andy
>
>
>Not really. 

Yes, really.

Have a static method in class reader as your thread entry point
taking a single void * argument.  Pass the object pointer as the
argument.   In the static method, you can cast the argument to
a pointer to reader and use that to access object data directly
or as Tiib points out, use it to invoke a member function.
0
scott
12/19/2016 2:30:16 PM
Reply: