Using a private method for threading

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • Xx r3negade
    New Member
    • Apr 2008
    • 39

    Using a private method for threading

    Consider this:

    I have the class foo, with the public method thread(), and the private method bar()

    In the thread() method, I would like to create a new thread, using pthread_create( ), that points to bar().

    Could someone tell me how to do this? I have the following code:

    Code:
    #include <iostream>
    #include <pthread.h>
    
    using namespace std;
    
    class foo
    {
      public:
        foo()
        {
        }
    
        void thread()
        {
            void* g;
            g = this->bar;
            pthread_t thread1;
            char* whatever = "hello";
    
            pthread_create( &thread1,
                            NULL,
                            &g,
                            static_cast<void*>(whatever)
                            );
        }
    
      private:
        void* bar(void* arg)
        {
            cout << "Whatever" << endl;
        }
    };
    
    int main()
    {
        foo New;
        New.thread();
        return 0;
    }
    I get the following error message (line 16):
    argument of type ‘void* (foo::)(void*)’ does not match ‘void*’
  • TamusJRoyce
    New Member
    • Apr 2008
    • 108

    #2
    help on pthreads...

    I meant to pm instead of msg here and am new to the board. It's interesting... thanks for asking about this. I'm curious too.
    Last edited by TamusJRoyce; Apr 17 '08, 06:12 AM. Reason: Irrelevent to question asked

    Comment

    • gpraghuram
      Recognized Expert Top Contributor
      • Mar 2007
      • 1275

      #3
      You should pass the address of a static function for pthread_create and this->bar is invalid to access a function in a class
      Like this
      static void* bar(void* arg)

      Raghuram
      Last edited by gpraghuram; Apr 17 '08, 06:10 AM. Reason: Added code

      Comment

      • TamusJRoyce
        New Member
        • Apr 2008
        • 108

        #4
        Excellent Example - Runable

        But making this->bar() static removes it from being part of the class, and makes it to be like a function within a namespace of that class. You need a way to pass "this" to your new static function to be used to make the thread so it may call this->bar();

        Code:
        // pthreadsclass.h  (everything in header for 
        //   example)
        
        #ifndef MYPTHREADSCLASS_H
          #define MYPTHREADSCLASS_H
        
        #include <pthread.h>
        
        /** Change code how you see fit.  Code usable by 
         *    anyone.  If you try to copywrite it as your own,
         *    keeping others from using it as well, code is 
         *    GPL-3 to begin with.  Else it's your code to use,
         *    edit, manipulate, add to, remove from, and/or change 
         *    as his/hers/your own code.  */
        class MyPThread
        {
          // Keeps track if thread is suppose to be running...
          bool threadIsRunning;
        
          // Keeps track of the thread
          pthread_t threadHandle;
        
          // This is our most important function.  It takes "this" 
          //    object as input (to be set when thread made).
          //    This function is the thread which loops "void update()"
          static void *updateThread(void *input)
          {
            // May need dynamic_ or static_ cast
            MyPThread *myPThread = (MyPThread *)input;
        
            if (myPThread) // Always check to see if pointer !NULL
            { // Makes sure thread is set to run while looping
              while (myPThread->isThreadRunning())
              {
                myPThread->update(); // Loops, running class' 
                                                    //   update() method
              } // End while
            } // End if
        
            pthread_exit(NULL);
          } // End updatThread() Callback Function
          
        public:
          // CONSTRUCTORS //
          /** Default constructor.  Thread is made by calling
           *    <CODE>startThread()</CODE> */
          MyPThread()
          {
            threadHandle = (pthread_t)0;
          } // End MyPThread() Constructor
        
          MyPThread(const MyPThread &thread)
          {
            if (this != &thread)
            {
              // Nothing to really copy... expand if you need it to.
              threadHandle = (pthread_t)0;
            } // End if
          } // End MyPThread() Copy Constructor
        
          // DESTRUCTOR //
          /** Destructor.*/
          ~MyPThread()
          {
            // Called automatically when object
            //   goes out of scope.  Makes sure
            //   thread gets stopped.
            stopThread();
          } // End ~MyPThread() Destructor   
         
          // INQUIRERS //
          bool isThreadRunning() const
          {
            return(threadIsRunning);
          } // End isThreadRunning() Method
        
          /** Makes and starts the thread.  */
          int startThread()
          {
            if (threadIsRunning)
            {
              return(1); // Failure
            } // End if
        
            /* From https://computing.llnl.gov/tutorials/pthreads/
             *   tutorial.  Look at there site to see if and how you
             *   may use this block of code...  */
            pthread_attr_t attr;      // Holds attributes for thread
            pthread_attr_init(&attr); // Initializes attr to default attrib.'s of thread
            pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); //Adds Joinable
        
            threadIsRunning = true;
            int iret1 = pthread_create(&threadHandle, &attr, updateThread, (void *)this);
            pthread_attr_destroy(&attr);
            if (iret1)
            {
              threadIsRunning = false;
              return(iret1); // Returns pthread_create's error if one found.
            } // End if
        
            return(0); // Return success
          } // End startThread() Method
        
          virtual int stopThread()
          {
            if (!threadIsRunning) // Returns error if pthread is not running
            {
              return(1);
            } // End if
        
            int iret1 = pthread_cancel(threadHandle);
            if (iret1)
            {
              return(iret1);
            } // End if
        
            threadHandle = (pthread_t)0;
            threadIsRunning = false;
            return(0);
          } // End stopThread() Method
        
        protected:
          /** Loops continually within a thread. */ 
          virtual void update()
          {
            // Do stuff you want it too here
          } // End update() Method
        
        }; // End MyPThread() class
        
        #endif
        Code:
        // main.cpp
        
        #include <iostream>
        
        using namespace std;
        
        
        // Don't have to worry what's in header.
        //   Just that it's there (hopefully no prob.
        //   or else it's fun to study)
        #include "pthreadclass.h"
        
        /** : public MyPThread makes this class
         *    have functions: bool isThreadRunning(), 
         *    void startThread(),  and void endThread().
         *    You have to have a method called
         *    "void update() {  // stuff  } */
        class FooClass : public MyPThread
        {
          int foo;
        
          // update() is my "generic" updating function.
          //   feel free to change the code in the header
          //   to reflect the function being bob! : D
          inline void bob()
          {
            cout << "foo # is: " << foo 
                    << ", and Bob is soooo cool. " << endl;
          } // End bob() Method
        
          /** Required method.  Must be implemented.
           *    but when start() is ran, code is looped
           *    about 100 times a minute within a
           *    thread*/
          void update()
          {
            bob();
          } // End update() Method
        public:
          /** Normal constructor except : MyPThread()
           *    added. */
          FooClass() : MyPThread()
          {
            foo = 1;
          } // End FooClass
        
          /** Starts the thread */
          void start()
          {
            startThread();
          } // End start() Method 
        
          /** Stops the thread */
          void stop()
          {
            stopThread();
          } // End stop() Method
        };
        
        // Caution:  Hit Ctrl+C to exit looping.
        int main()
        {
          FooClass fooClass;
        
          // Should make output be repeated
          //   a lot of times...
          fooClass.start();
        
          // Waits for user input
          int waitForInput;
          cin >> waitForInput;
        
          // Probably won't work because data will
          //   be repeating too fast to input data.
          fooClass.stop();
        
          return(0);
        } // End main() Function
        //Sorry it's so long. But linking the static function updateThread() to how you use it in the class and keeping it private can be hard unless all the code is given in a plain, viewable format. Class theads is a feature which is much easier to implement in Java, but thankfully more powerfull in c++.

        //Just don't forget to expand your thread's stack size to be large enough to hold your void update() function (I believe it's needed, but not sure). I've not found out how to do this yet. Also adding low level timer (using clock.h or otherwise) so the work update() does doesn't end up being done excessively (100 times a second).

        //There are also an excellent set of algorithms which can increase and decrease how fast void update() is being called by the object itself updating how many times a second it's being called. Search "Java's graphic threads and timing" on how to do this.
        Last edited by TamusJRoyce; Apr 17 '08, 07:43 AM. Reason: Code Change

        Comment

        • Xx r3negade
          New Member
          • Apr 2008
          • 39

          #5
          Okay, I have this, and it works...
          Code:
          #include <iostream>
          #include <pthread.h>
          
          using namespace std;
          
          class foo
          {
              static void* staticFunc( void* obj )
              {
                  foo* thisObj = static_cast<foo*>(obj);
                  thisObj->privateFunc();
              }
            public:
              foo()
              {
              }
          
              void thread()
              {
                  pthread_t thread1;
          
                  pthread_create( &thread1,
                                  NULL,
                                  staticFunc,
                                  this
                                  );
              }
            private:
              void privateFunc()
              {
                  cout << "In private function!  Woot!" << endl;
              }
          };
          
          int main()
          {
              foo New;
              New.thread();
              return 0;
          }
          Would it be possible to pass a second parameter in staticFunc() that determines which method will be accessed?

          Comment

          • gpraghuram
            Recognized Expert Top Contributor
            • Mar 2007
            • 1275

            #6
            Originally posted by Xx r3negade
            Okay, I have this, and it works...
            Code:
            #include <iostream>
            #include <pthread.h>
            
            using namespace std;
            
            class foo
            {
                static void* staticFunc( void* obj )
                {
                    foo* thisObj = static_cast<foo*>(obj);
                    thisObj->privateFunc();
                }
              public:
                foo()
                {
                }
            
                void thread()
                {
                    pthread_t thread1;
            
                    pthread_create( &thread1,
                                    NULL,
                                    staticFunc,
                                    this
                                    );
                }
              private:
                void privateFunc()
                {
                    cout << "In private function!  Woot!" << endl;
                }
            };
            
            int main()
            {
                foo New;
                New.thread();
                return 0;
            }
            Would it be possible to pass a second parameter in staticFunc() that determines which method will be accessed?

            pthread_create takesa function pointer which has this definition
            void *fun(void*)
            If you want to pass more than one paramter then define a structure and then add the members which you require.
            After that pass the structure as a argument to the thread function

            Thanks
            Raghuram

            Comment

            • TamusJRoyce
              New Member
              • Apr 2008
              • 108

              #7
              I'm curious how the second parameter you wish to pass would determine which method you want to call... Just for the sake of learning how to do this myself : )

              But gpraghuram's correct. Or you could choose to keep the data, which determines which method you want to call, as a private variable in class foo. Set it through a public function, then use it when you run thread();

              Code:
              // Could be a class instead, functioning like a class...
              struct threadParam { // (struct is a class defaultly public)
                foo *thisToRunThreadFuncIn;
              
                // Other parameters to determine which method to run
              }; // End threadParam struct
              Then cast the obj as threadParam.
              Last edited by TamusJRoyce; Apr 18 '08, 04:32 AM. Reason: spacing

              Comment

              Working...