Solved

Why am i getting an error hete in the pthread_create()?

Posted on 2012-03-30
14
397 Views
Last Modified: 2012-04-04
I am trying to create a C++ thread class by wrapping the C pthreads.

--Pthread.h file

class Pthread
    {
        public:
           Pthread( pthread_attr_t* attr, void *arg);
           Pthread();
           virtual ~Pthread();
           int create();
           void join();
           void exit();

        private:
           void* run(void *threadid);

           pthread_t mPthread;
           pthread_attr_t  *mAttributes;
           void *mArguments;
    };

Then in my C++ .hh file I say  this...

 Pthread::Pthread( pthread_attr_t* attr, void *args)
    {
            mAttributes =  attr;
            mArguments = args;
    }

    Pthread::Pthread()
    {
    }

    Pthread::~Pthread()
    {
    }

    int Pthread::create()
    {
        return pthread_create( &mPthread, NULL, run, mArguments);
     
    }

    void Pthread::join()
    {
        pthread_join( mPthread, NULL);
    }

    void Pthread::exit()
    {
       int ex = 1;
       pthread_exit(&ex);
    }

    void* Pthread::run(void *threadid)
    {
       return NULL;
    }
}


int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
    void *(*start_routine)(void*), void *arg);


-prain

I am getting an error in line:

return pthread_create( &mPthread, NULL, run, mArguments);
     
in my function create()

The pthread_create in 'C' <phread.h> has the prototype.
0
Comment
Question by:prain
  • 5
  • 5
  • 4
14 Comments
 
LVL 31

Expert Comment

by:Zoppo
ID: 37787099
Hi prain,

the problem is you're passing a none-static member function, but pthread_create expects a global (or static member) function.

ZOPPO
0
 

Author Comment

by:prain
ID: 37787159
I changed the function to status like this:

static void* Pthread::run(void *threadid){}

(also in .h file). But I am getting this error....

Pthread.cpp:51: error: cannot declare member function ‘static void* Sst::Pthread::run(void*)’ to have static linkage

 Does this mean that I cannot have the function I want o execute for the thread inside the class?
0
 
LVL 31

Expert Comment

by:Zoppo
ID: 37787224
Yes, that's correct. The problem simply is that to be able to use a function pointer to a member function you need to have an object too. It's not possible to call a member function without an object.

IMO you have two possibilities:

1. Implement run as static function and pass a pointer to an object as argument (maybe you have to implement a class/struct if you need to pass other data, i.e. threadId). Then from the none-static member simply call that static function and pass this ass argument, i.e.:

static run( PThread* pThis )
{
 pThis->run();
}

int Pthread::create()
{
  return pthread_create( &mPthread, NULL, run, this );
}

2. If it's ok for you to use boost library () use some existing thread implementation like boost::thread - i.e. here you can see a sample how this is used: http://blog.emptycrate.com/node/277

ZOPPO
0
Announcing the Most Valuable Experts of 2016

MVEs are more concerned with the satisfaction of those they help than with the considerable points they can earn. They are the types of people you feel privileged to call colleagues. Join us in honoring this amazing group of Experts.

 
LVL 31

Accepted Solution

by:
Zoppo earned 100 total points
ID: 37787276
Sorry, I re-read the comment and found some maybe confusing statements:

To the question  Does this mean that I cannot have the function I want o execute for the thread inside the class? I wrote Yes, that's correct. With this I meant it's not possible for none-static members only, static member functions can be used.

The static run function I wrote should be declare in the class like
static void* run( void* pThis );

Open in new window

and implemented somehow like this:
void* Pthread::run( void* pThis )
{
 return static_cast< PThread* >( pThis )->run();
}

Open in new window


ZOPPO
0
 

Author Comment

by:prain
ID: 37788237
Ok. Complilation is working good. But I do not get the line

return static_cast< PThread* >( pThis )->run();


Do not understand why a point of the same function is returned after static_cast.

Can you pl. explain.
0
 
LVL 31

Expert Comment

by:Zoppo
ID: 37794657
It's not the same function run which is called here, it's the none-static void* PThread::run() member function called against the PThread object pointed to by pThis. The cast is needed since pThis is a void pointer.
0
 
LVL 33

Assisted Solution

by:sarabande
sarabande earned 50 total points
ID: 37797218
instead of providing a helper which does the cast you could have two member functions for 'run'. one is static and gets the Pthread* as void* argument, other is normal member function:

class Pthread
{
public: 
     static void threadRun(void * p)
     {
            Pthread pthis = (Pthread*)p;
            p->run();
    }
    void run()
    {
          // here add the implementation
    }
    bool start()
    {
           if (!pthread_create(&mPthread, NULL, Pthread::threadRun, this); 
    }
    ....

Open in new window


note, the mArguments was not passed to the thread but the 'this' instead. the static member function would cast the void* back to a pointer of Pthread and then call member function run. in run function you would have access to all members of the class. so you don't need the mArguments anymore.

Sara
0
 
LVL 33

Expert Comment

by:sarabande
ID: 37797226
start function should have been like

if (!pthread_create(&mPthread, NULL, Pthread::threadRun, this))
     return false;
return true;

Open in new window

0
 

Author Comment

by:prain
ID: 37797580
In this simple example, I expected the print statement Running..... priinting for ever.
But it is not hapenning. BTW I am working in a UNIX env.
--Thread.hh
 class Thread
    {
        public:
           
           Thread();
           virtual ~Thread();
           void initialize();
           bool isRunning() const;

        private :

        static void* threadRun(void * pThis);
        void run();
       
        pthread_t mThread;
        bool mIsRunning;
};


--Thread.cpp
#include "Thread.hh"
#include <pthread.h>
    Thread::Thread()
    {
     }

    Thread::~Thread()
    {
    }
 
    void Thread::initialize()
    {
        // Create thread attribute
        pthread_attr_t attr;
        pthread_attr_init(&attr);
        pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
 
        // Create thread
        int rc = pthread_create(&mThread, &attr,  &Thread::threadRun, (void*) this);
 
        // Destroy thread attribute
        pthread_attr_destroy(&attr);
        // check return code form thread create - this should throw exception
        if (rc != 0) {
            std::cout << "pthread_create failed" << std::endl;
        }

    }
   
    bool Thread::isRunning() const {
        return mIsRunning;
    }

 
    void* Thread::threadRun(void * pThis)
    {
         Thread* tThis = (Thread*) pThis;
        tThis->run();
    }
 

    void Thread::run() {

        mIsRunning = true;
 
        while (1) {
          std::cout << "Running...." << std::endl;
        }
    }

--Test Main
#include "Thread.hh"
#include <iostream>

// Main Function
int main ( int argc, int argv[] )
{
  Sst::Thread* aThread = new Sst::Thread();
  aThread->initialize();

  return 0;
}
0
 
LVL 33

Expert Comment

by:sarabande
ID: 37799932
you would need a loop in the main function as well cause if the main thread exits the worker thread would terminate either.

put a little sleep in all endless loops to let some cpu for other processes.

Sara
0
 

Author Comment

by:prain
ID: 37800836
Just thinking, doesn't the master (parent) thread must wait until the worker thread finishes?
0
 
LVL 33

Expert Comment

by:sarabande
ID: 37801099
you could do so by calling pthread_join after create (if i remember rightly). but the normal thing is that both threads run parallel such that you have real multi-tasking. or said differently: it makes not much sense to run a thread if other thread waits. then a simple call of the thread function is much easier.

Sara
0
 
LVL 33

Expert Comment

by:sarabande
ID: 37801425
instead of an infinite loop you could wait for user input (std::cin) or do a peek on std::cin. that way your program keeps responsive and the user could quit. in case of a user quit you would set a stopflag of your class object and wait until the thread has terminated. the thread would check periodically whether the stopflag is set and would terminate (break the infinite loop). that way the thread would be gently stopped and not killed what could make a difference if the thread uses resources which should be orderly freed.

Sara
0
 

Author Closing Comment

by:prain
ID: 37807993
Thanks guys.
I have another quesiton opened in boost:threads. Finally our company decided to go with
boost.

prain
0

Featured Post

Free Tool: Site Down Detector

Helpful to verify reports of your own downtime, or to double check a downed website you are trying to access.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
max float value 3 51
nested if statement in excel help 4 37
Are the two lines the same? If not what is the difference? 2 22
find Speed using GPS latitude & longitude 4 42
Container Orchestration platforms empower organizations to scale their apps at an exceptional rate. This is the reason numerous innovation-driven companies are moving apps to an appropriated datacenter wide platform that empowers them to scale at a …
Examines three attack vectors, specifically, the different types of malware used in malicious attacks, web application attacks, and finally, network based attacks.  Concludes by examining the means of securing and protecting critical systems and inf…
Video by: Grant
The goal of this video is to provide viewers with basic examples to understand and use while-loops in the C programming language.
The viewer will be introduced to the technique of using vectors in C++. The video will cover how to define a vector, store values in the vector and retrieve data from the values stored in the vector.

856 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question