Re: Question on C++ Thread Class and inheritance/polymorphism with POSIX pthread

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Chris M. Thomasson

    #1

    Re: Question on C++ Thread Class and inheritance/polymorphism with POSIX pthread

    FWIW, here is a quick example (in the form of a fully compliable program
    with error checking omitted) of how I use POSIX threads within a C++
    environment:
    _______________ _______________ _______________ _______________ _____
    /* Simple Thread Object
    _______________ _______________ _______________ _______________ __*/
    #include <pthread.h>


    extern "C" void* thread_entry(vo id*);

    class thread_base {
    pthread_t m_tid;
    friend void* thread_entry(vo id*);
    virtual void on_thread_entry () = 0;

    public:
    virtual ~thread_base() = 0;

    void thread_run() {
    pthread_create( &m_tid, NULL, thread_entry, this);
    }

    void thread_join() {
    pthread_join(m_ tid, NULL);
    }
    };

    thread_base::~t hread_base() {}

    void* thread_entry(vo id* state) {
    reinterpret_cas t<thread_base*> (state)->on_thread_entr y();
    return 0;
    }

    template<typena me T>
    struct thread : public T {
    thread() : T() {
    this->thread_run() ;
    }

    ~thread() {
    this->thread_join( );
    }

    template<typena me T_p1>
    thread(T_p1 p1) : T(p1) {
    this->thread_run() ;
    }

    template<typena me T_p1, typename T_p2>
    thread(T_p1 p1, T_p2 p2) : T(p1, p2) {
    this->thread_run() ;
    }

    // [and on and on for for params...]
    };




    /* Simple Usage Example
    _______________ _______________ _______________ _______________ __*/
    #include <string>
    #include <cstdio>


    class worker : public thread_base {
    std::string const m_name;

    void on_thread_entry () {
    std::printf("(% p)->worker(%s)::on _thread_entry() \n",
    (void*)this, m_name.c_str()) ;
    }

    public:
    worker(std::str ing const& name)
    : m_name(name) {
    std::printf("(% p)->worker(%s)::my _thread()\n",
    (void*)this, m_name.c_str()) ;
    }

    ~worker() {
    std::printf("(% p)->worker(%s)::~m y_thread()\n",
    (void*)this, m_name.c_str()) ;
    }
    };


    int main(void) {
    {
    thread<workerwo rkers[] = {
    "Chris",
    "John",
    "Jane",
    "Steve",
    "Richard",
    "Lisa"
    };

    worker another_worker( "Jeff");
    another_worker. thread_run();
    another_worker. thread_join();
    }

    std::puts("\n\n \n_____________ _____\nhit <ENTERto exit...");
    std::fflush(std out);
    std::getchar();
    return 0;
    }
    _______________ _______________ _______________ _______________ _____




    IMVHO, this is very straight forward and works well. In fact, I think I like
    it better than the Boost method... Humm... Well, what do you all think about
    the design? Is it crap?

  • Szabolcs Ferenczi

    #2
    Re: Question on C++ Thread Class and inheritance/polymorphism withPOSIX pthread

    On Oct 29, 12:07 am, "Chris M. Thomasson" <n...@spam.inva lidwrote:
    FWIW, here is a quick example (in the form of a fully compliable program
    with error checking omitted) of how I use POSIX threads within a C++
    environment:
    _______________ _______________ _______________ _______________ _____
    /* Simple Thread Object
    _______________ _______________ _______________ _______________ __*/
    #include <pthread.h>
    >
    extern "C" void* thread_entry(vo id*);
    >
    class thread_base {
      pthread_t m_tid;
      friend void* thread_entry(vo id*);
      virtual void on_thread_entry () = 0;
    >
    public:
      virtual ~thread_base() = 0;
    >
      void thread_run() {
        pthread_create( &m_tid, NULL, thread_entry, this);
      }
    >
      void thread_join() {
        pthread_join(m_ tid, NULL);
      }
    >
    };
    >
    thread_base::~t hread_base() {}
    >
    void* thread_entry(vo id* state) {
      reinterpret_cas t<thread_base*> (state)->on_thread_entr y();
      return 0;
    >
    }
    >
    template<typena me T>
    struct thread : public T {
      thread() : T() {
        this->thread_run() ;
      }
    >
      ~thread() {
        this->thread_join( );
      }
    >
      template<typena me T_p1>
      thread(T_p1 p1) : T(p1) {
        this->thread_run() ;
      }
    >
      template<typena me T_p1, typename T_p2>
      thread(T_p1 p1, T_p2 p2) : T(p1, p2) {
        this->thread_run() ;
      }
    >
      // [and on and on for for params...]
    >
    };
    >
    /* Simple Usage Example
    _______________ _______________ _______________ _______________ __*/
    #include <string>
    #include <cstdio>
    >
    class worker : public thread_base {
      std::string const m_name;
    >
      void on_thread_entry () {
        std::printf("(% p)->worker(%s)::on _thread_entry() \n",
          (void*)this, m_name.c_str()) ;
      }
    >
    public:
      worker(std::str ing const& name)
        : m_name(name) {
        std::printf("(% p)->worker(%s)::my _thread()\n",
          (void*)this, m_name.c_str()) ;
      }
    >
      ~worker() {
        std::printf("(% p)->worker(%s)::~m y_thread()\n",
         (void*)this, m_name.c_str()) ;
      }
    >
    };
    >
    int main(void) {
      {
        thread<workerwo rkers[] = {
          "Chris",
          "John",
          "Jane",
          "Steve",
          "Richard",
          "Lisa"
        };
    >
        worker another_worker( "Jeff");
        another_worker. thread_run();
        another_worker. thread_join();
      }
    >
      std::puts("\n\n \n_____________ _____\nhit <ENTERto exit...");
      std::fflush(std out);
      std::getchar();
      return 0;}
    >
    _______________ _______________ _______________ _______________ _____
    >
    IMVHO, this is very straight forward and works well. In fact, I think I like
    it better than the Boost method... Humm... Well, what do you all think about
    the design? Is it crap?
    The active object concept is much better than the Boost thread and I
    have suggested it earlier that the C++0x committee should consider
    this pattern, i.e. active object, as a high level wrapper construction
    next to their high level wrapper wait/2 on the condition variable:

    <quote from="

    ">
    I do think it has advantages over Boost's method. One such advantage
    is the RAII nature of it.

    Furthermore, I think it should be taken in into the C++0x standard on
    the similar grounds as they provide higher level condition variable
    wait API as well:

    <quote>
    template <class Predicate>
    void wait(unique_loc k<mutex>& lock, Predicate pred);
    Effects:
    As if:
    while (!pred())
    wait(lock);
    </quote>

    </quote>

    Another remark: Why do you not keep to the terminology we have come up
    with earlier? It is for an active object and not for any plain thread.
    See:

    "What's the connection between objects and threads?"


    What is the difference between:

    worker another_worker( "XY");
    another_worker. thread_run();
    another_worker. thread_join();

    and

    ActiveObject<wo rkeranother_wor ker("XY");

    Well, the difference is that the wrapper takes care of the low level
    details of starting and stopping the thread. As a bonus, it is
    impossible to miss to join the thread. In other frameworks they tend
    to call it the fork-join style.

    So, you might consider this patch for clarity:

    34,35c34,35
    < struct ActiveObject : public T {
    < ActiveObject() : T() {
    ---
    struct thread : public T {
    thread() : T() {
    39c39
    < ~ActiveObject() {
    ---
    ~thread() {
    44c44
    < ActiveObject(T_ p1 p1) : T(p1) {
    ---
    thread(T_p1 p1) : T(p1) {
    49c49
    < ActiveObject(T_ p1 p1, T_p2 p2) : T(p1, p2) {
    ---
    thread(T_p1 p1, T_p2 p2) : T(p1, p2) {
    86c86
    < ActiveObject<wo rkerworkers[] = {
    ---
    thread<workerwo rkers[] = {
    I believe that the program will be clearer and more readable if you
    keep to the terminology that reflects the active object. It is not a
    good idea to overload the term `thread' since it will just cause some
    more confusion.

    Best Regards,
    Szabolcs

    Comment

    Working...