What's the connection between objects and threads?

Discussion in 'C++' started by darren, May 17, 2008.

  1. darren

    darren Guest

    Hi

    I have to write a multi-threaded program. I decided to take an OO
    approach to it. I had the idea to wrap up all of the thread functions
    in a mix-in class called Threadable. Then when an object should run
    in its own thread, it should implement this mix-in class. Does this
    sound like plausible design decision?

    I'm surprised that C++ doesn't have such functionality, say in its
    STL. This absence of a thread/object relationship in C++ leads me to
    believe that my idea isn't a very good one.

    I would appreciate your insights. thanks
     
    darren, May 17, 2008
    #1
    1. Advertising

  2. darren wrote:
    > Hi
    >
    > I have to write a multi-threaded program. I decided to take an OO
    > approach to it. I had the idea to wrap up all of the thread functions
    > in a mix-in class called Threadable. Then when an object should run
    > in its own thread, it should implement this mix-in class. Does this
    > sound like plausible design decision?
    >
    > I'm surprised that C++ doesn't have such functionality, say in its
    > STL. This absence of a thread/object relationship in C++ leads me to
    > believe that my idea isn't a very good one.


    The next revision of the C++ standard does in fact have thread support.

    The threading concepts in the next revision will probably work with what
    you describe but there is a few newer concepts - one is called a "future".

    In the meantime, there are some alternative libraries - boost implements
    many of the standard's new features already as well as other like
    commonc++ and Austria c++ also have cross platform threading support for
    C++.

    In most of my newer projects, I use thread pools which is very different
    to threads.
     
    Gianni Mariani, May 17, 2008
    #2
    1. Advertising

  3. On May 17, 10:20 pm, darren <> wrote:

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

    Good question. In C++ there is no connection between objects and
    threads since there are no threads in C++.

    C++ does not have the notion of the process or the thread of
    computation at the language level. On the other hand, C++ does have
    the notion of the object at the language level. It is an object-
    oriented programming language but not a concurrent object-oriented
    one. The bad news is that it is not going to be one either.

    The good news is that you can introduce threads of computation into a C
    ++ program via some libraries. The coming C++0x would even include
    such a library, though.

    So, you can take any concurrency libraries to mix threads into an
    object-oriented program in C++. Objects and threads of computation are
    usually orthogonal to each other. Objects are (passive) data
    structures and, on the other hand, threads of computation are rather
    activities with their own program counters in your program.

    You can keep them separate as was done in the first class-based
    concurrent programming language, Concurrent Pascal, or you can combine
    them together as was done, for instance, in an early language proposal
    called Distributed Processes (DP).

    > I had the idea to wrap up all of the thread functions
    > in a mix-in class called Threadable."


    What do you mean by "thread functions"?

    > Does this
    > sound like plausible design decision?


    It looks like you have the approach in mind where the objects are data
    structures (passive elements) and the threads of computation (active
    elements) are orthogonal to each other. In this case you could keep
    them separate and do not intermix them, it would not be a good idea.
    Although, if you must use any lower level library (such as Pthread),
    it is a good idea to build your own higher level abstractions, I
    think.

    In this case it is very important to make a difference between the
    objects which are meant to be used exclusively from one thread of
    computation only and between the objects which are to be shared among
    many threads. The shared objects must be protected so that they could
    be accessed by the threads in a mutually exclusive way only (see the
    Monitor concept).

    Best Regards,
    Szabolcs
     
    Szabolcs Ferenczi, May 17, 2008
    #3
  4. darren

    darren Guest

    Thanks for the responses everybody.

    I have actually heard of Boost. I saw it in another post on this user
    group about threads. My dilemma is that for this project, we were
    specifically told that we must use the pthread library and our
    deliverable must only be source code and a Makefile.

    Doest Boost use pthread library calls in its implementation, or are
    they up to something else? Maybe I'll email my prof and ask if using
    Boost is permitted.

    As for my current idea:

    I planned to write a class called myThreads which would wrap up calls
    to the pthread library, like pthread_create. Then anytime i need a
    thread I'll instantiate one of these objects. I was thinking that in
    one of these 'myThread" constructors, a new thread would be created
    and ran. Again, i'm new to thread programming, so i dont know if this
    will work or not.

    there was also mention about threadpools. Our instructor said this may
    be a good way to implement our project. How are they significantly
    different than concepts of thread programming (as somebody here
    mentioned they were).

    thanks again.
     
    darren, May 18, 2008
    #4
  5. darren

    darren Guest

    On May 17, 8:35 pm, "Chris Thomasson" <> wrote:
    > "darren" <> wrote in message
    >
    > news:...
    >
    > > Thanks for the responses everybody.

    >
    > > I have actually heard of Boost. I saw it in another post on this user
    > > group about threads. My dilemma is that for this project, we were
    > > specifically told that we must use the pthread library and our
    > > deliverable must only be source code and a Makefile.

    >
    > > Doest Boost use pthread library calls in its implementation, or are
    > > they up to something else? Maybe I'll email my prof and ask if using
    > > Boost is permitted.

    >
    > > As for my current idea:

    >
    > > I planned to write a class called myThreads which would wrap up calls
    > > to the pthread library, like pthread_create. Then anytime i need a
    > > thread I'll instantiate one of these objects. I was thinking that in
    > > one of these 'myThread" constructors, a new thread would be created
    > > and ran. Again, i'm new to thread programming, so i dont know if this
    > > will work or not.

    >
    > [...]
    >
    > You don't generally want to create threads in constructors because of a
    > possible race-condition. Think of starting a thread in an object's
    > constructor which starts to run and operate on it _before_ its ctor has
    > finished... Anyway:
    >
    > http://groups.google.com/group/comp.programming.threads/browse_frm/th...
    > (please read all!)
    >
    > Here is some very simple source-code that might help you:
    > ____________________________________________________________________
    >
    > /* VERY Simple Thread Library Code
    > ______________________________________________________________*/
    > #include <pthread.h>
    >
    > class thread_base;
    > extern "C" void* thread_base_entry(void*);
    > static void thread_create(thread_base* const);
    > static void thread_join(thread_base* const);
    >
    > class thread_base {
    > pthread_t m_id;
    > friend void* thread_base_entry(void*);
    > friend void thread_create(thread_base* const);
    > friend void thread_join(thread_base* const);
    > virtual void on_thread_entry() = 0;
    > public:
    > virtual ~thread_base() throw() = 0;
    >
    > };
    >
    > thread_base::~thread_base() throw() {}
    >
    > void* thread_base_entry(void* state) {
    > reinterpret_cast<thread_base*>(state)->on_thread_entry();
    > return 0;
    >
    > }
    >
    > void thread_create(thread_base* const _this) {
    > int const status = pthread_create(&_this->m_id, NULL,
    > thread_base_entry, _this);
    > if (status) {
    > throw int(status);
    > }
    >
    > }
    >
    > void thread_join(thread_base* const _this) {
    > int const status = pthread_join(_this->m_id, NULL);
    > if (status) {
    > throw int(status);
    > }
    >
    > }
    >
    > /* Very Simple Application Code
    > ______________________________________________________________*/
    > #include <cstdio>
    >
    > class my_thread : public thread_base {
    > public:
    > my_thread() {
    > std::printf("(%p)-my_thread::my_thread()\n",
    > reinterpret_cast<void*>(this));
    > }
    >
    > ~my_thread() throw() {
    > std::printf("(%p)-my_thread::~my_thread() throw()\n",
    > reinterpret_cast<void*>(this));
    > }
    >
    > private:
    > void on_thread_entry() {
    > std::printf("void (%p)-my_thread::eek:n_thread_entry()\n",
    > reinterpret_cast<void*>(this));
    > }
    >
    > };
    >
    > #define RUN_DEPTH() 10
    > #define THREAD_DEPTH() 32
    > int main() {
    > int runs = 0;
    > for (; runs < RUN_DEPTH(); ++runs) {
    > int i = 0;
    > my_thread threads[THREAD_DEPTH()];
    >
    > try {
    > for (; i < THREAD_DEPTH(); ++i) {
    > thread_create(&threads);
    > }
    > } catch (int const& e) {
    > std::printf("thread_create throws status %d!\n", e);
    > }
    >
    > for (--i; i > -1; --i) {
    > try {
    > thread_join(&threads);
    > } catch (int const& e) {
    > std::printf("thread_join throws status %d!\n", e);
    > }
    > }
    > }
    >
    > /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
    > std::puts("\n\n____________________________________________\n\
    > Press <ENTER> to exit...");
    > std::getchar();
    > return 0;
    >
    > }
    >
    > ____________________________________________________________________
    >
    > Any questions?


    hi Chris. Thanks for the reply and the sample code. I'll have to
    spend some time understanding it. For starters why do you have this
    ection:

    > class thread_base;
    > extern "C" void* thread_base_entry(void*);
    > static void thread_create(thread_base* const);
    > static void thread_join(thread_base* const);


    I've never seen code like this. are the parameters taking pointers to
    a class??? it seems like thread_create is declared twoice, once as
    friend and once not...

    I've also never seen extern C before, i'll have to look up what that
    is.

    thanks again.
     
    darren, May 18, 2008
    #5
  6. darren

    ManicQin Guest

    On May 18, 3:24 am, darren <> wrote:
    > Thanks for the responses everybody.
    >
    > I have actually heard of Boost. I saw it in another post on this user
    > group about threads. My dilemma is that for this project, we were
    > specifically told that we must use the pthread library and our
    > deliverable must only be source code and a Makefile.
    >
    > Doest Boost use pthread library calls in its implementation, or are
    > they up to something else? Maybe I'll email my prof and ask if using
    > Boost is permitted.
    >
    > As for my current idea:
    >
    > I planned to write a class called myThreads which would wrap up calls
    > to the pthread library, like pthread_create. Then anytime i need a
    > thread I'll instantiate one of these objects. I was thinking that in
    > one of these 'myThread" constructors, a new thread would be created
    > and ran. Again, i'm new to thread programming, so i dont know if this
    > will work or not.
    >
    > there was also mention about threadpools. Our instructor said this may
    > be a good way to implement our project. How are they significantly
    > different than concepts of thread programming (as somebody here
    > mentioned they were).
    >
    > thanks again.


    At the company that I'm working we work the way you suggested
    (which could be imply that YOU DONT WANT TO USE IT! ;) )
    but it works fine and most of the times it's transparent.

    My problem with thread pools (and I'll be happy if someone contradicts
    me)
    is that until .Net did'nt introduce thread pools I have'nt heared
    about it
    and it makes me worried that maybe it's a bit platform specific.
    (But if you dont care than it's great method to ease your work)

    If you could shed some light on your project maybe people could
    give a more precise counsel on the MT method you should use...
     
    ManicQin, May 18, 2008
    #6
  7. darren

    darren Guest

    On May 18, 1:13 am, ManicQin <> wrote:
    > On May 18, 3:24 am, darren <> wrote:
    >
    >
    >
    > > Thanks for the responses everybody.

    >
    > > I have actually heard of Boost. I saw it in another post on this user
    > > group about threads. My dilemma is that for this project, we were
    > > specifically told that we must use the pthread library and our
    > > deliverable must only be source code and a Makefile.

    >
    > > Doest Boost use pthread library calls in its implementation, or are
    > > they up to something else? Maybe I'll email my prof and ask if using
    > > Boost is permitted.

    >
    > > As for my current idea:

    >
    > > I planned to write a class called myThreads which would wrap up calls
    > > to the pthread library, like pthread_create. Then anytime i need a
    > > thread I'll instantiate one of these objects. I was thinking that in
    > > one of these 'myThread" constructors, a new thread would be created
    > > and ran. Again, i'm new to thread programming, so i dont know if this
    > > will work or not.

    >
    > > there was also mention about threadpools. Our instructor said this may
    > > be a good way to implement our project. How are they significantly
    > > different than concepts of thread programming (as somebody here
    > > mentioned they were).

    >
    > > thanks again.

    >
    > At the company that I'm working we work the way you suggested
    > (which could be imply that YOU DONT WANT TO USE IT! ;) )
    > but it works fine and most of the times it's transparent.
    >
    > My problem with thread pools (and I'll be happy if someone contradicts
    > me)
    > is that until .Net did'nt introduce thread pools I have'nt heared
    > about it
    > and it makes me worried that maybe it's a bit platform specific.
    > (But if you dont care than it's great method to ease your work)
    >
    > If you could shed some light on your project maybe people could
    > give a more precise counsel on the MT method you should use...


    Its a multithreaded web server using pthreads and the socket api (hey
    everybody else in my class looking for ideas :) ).

    Here's my basic algorithm:
    1. main() makes a singleton ServerKernal object to control program
    flow
    2. ServerKernal listens for requests on a specified port. this is done
    by creating a thread that loops and continuously accepts connections.
    3. A successful accepted connection is put into a queue (from the STL
    library).
    4. Meanwhile, back at the ranch, another thread is created and running
    that continuously checks for entries into the queue.
    5. if an entry is in there, a new thread is spawned to handle the
    request. That thread then dies.

    What do you think of this algorithm?

    A couple of things i'm thinking about:
    1. As per the reason i created this post, I was thinking about how
    objects related to threads. At first I was thinking that an object
    should create a thread. this has been advised as bad (thanks for the
    advice!). Now I'm thinking that instead, threads should create
    objects, and destroy them before the thread ends. for example, when a
    request is in the queue, a thread is created to handle it. Within this
    new thread, a RequestHandler object is instantiated. It's methods are
    used to process the request. The object is then destroyed. Finally,
    the thread ends.

    2 I was thinking about thread pools. Maybe there could be 10 threads
    set up, waiting for requests. I dont know much about thread pools yet
    though. It may not be appropriate. Or, maybe the threads could be
    sleeping, then awoken by signaling when a request enters the queue.
     
    darren, May 18, 2008
    #7
  8. On May 18, 11:43 am, darren <> wrote:

    > At first I was thinking that an object
    > should create a thread.  this has been advised as bad (thanks for the
    > advice!).  


    That is not a bad idea at all that an object creates a thread in the
    constructor. Do not be mistaken.

    There are programming models where there are objects which are active
    entities. As I earlier mentioned one early proposal of this kind is
    the Distributed Processes programming concept. This means that it
    depends on discipline only. You can build an abstraction for yourself
    where the object starts its dedicated thread as the last step in the
    constructor and joins the low level thread in the destructor. That is
    not a bad idea at all.

    That means that you can use configurator blocks in your program where
    you declare so-called thread objects and shared objects together.

    {
    Buffer b;
    Producer p(b);
    Consumer c(b);
    }

    The block realises a parallel block or fork-join block as they call it
    in a trendy terminology.

    Best Regards,
    Szabolcs
     
    Szabolcs Ferenczi, May 18, 2008
    #8
  9. On May 18, 11:43 am, darren <> wrote:

    > Here's my basic algorithm:
    > 1. main() makes a singleton ServerKernal object to control program
    > flow


    > What do you think of this algorithm?


    Try to avoid using singletons (if you refer to the singleton pattern).
    It is not a good idea even in non-MT programs. You can always avoid
    using singletons by disciplined programming. In this case you do not
    need singleton either.

    Best Regards,
    Szabolcs
     
    Szabolcs Ferenczi, May 18, 2008
    #9
  10. On May 18, 2:24 am, darren <> wrote:

    > Doest Boost use pthread library calls in its implementation, or are
    > they up to something else?  


    As far as I know, Boost is built on Pthread library on the Unix
    platform. In principle it could be implemented on any other low level
    libraries as well on Unix too. That is the benefit of higher level
    structures that they hide low level details.

    Best Regards,
    Szabolcs
     
    Szabolcs Ferenczi, May 18, 2008
    #10
  11. On May 18, 11:43 am, darren <> wrote:

    > 3. A successful accepted connection is put into a queue (from the STL
    > library).
    > 4. Meanwhile, back at the ranch, another thread is created and running
    > that continuously checks for entries into the queue.


    Be aware that although STL is thread-safe to a certain extent, you
    must wrap around the STL data structure to make a kind of a bounded
    buffer out of it.

    The point is that checking the data structure and carrying out the
    corresponding action must be atomic. For instance checking if there is
    element in the data structure and taking that element must be atomic.

    Best Regards,
    Szabolcs
     
    Szabolcs Ferenczi, May 18, 2008
    #11
  12. darren

    ManicQin Guest

    On May 18, 12:43 pm, darren <> wrote:

    > A couple of things i'm thinking about:
    > 1. As per the reason i created this post, I was thinking about how
    > objects related to threads. At first I was thinking that an object
    > should create a thread. this has been advised as bad (thanks for the
    > advice!). Now I'm thinking that instead, threads should create
    > objects, and destroy them before the thread ends. for example, when a
    > request is in the queue, a thread is created to handle it. Within this
    > new thread, a RequestHandler object is instantiated. It's methods are
    > used to process the request. The object is then destroyed. Finally,
    > the thread ends.
    >
    > 2 I was thinking about thread pools. Maybe there could be 10 threads
    > set up, waiting for requests. I dont know much about thread pools yet
    > though. It may not be appropriate. Or, maybe the threads could be
    > sleeping, then awoken by signaling when a request enters the queue.



    1. sounds good maybe you would like to read about RAII
    (or auto_ptr in stl - remeber not to create a continer of auto_ptrs!)

    2. use thread pools. it's easy and it's a "fire and forget"
    mechanizm...


    Szabolcs Ferenczi wrote:

    > Try to avoid using singletons (if you refer to the singleton pattern).
    > It is not a good idea even in non-MT programs. You can always avoid
    > using singletons by disciplined programming. In this case you do not
    > need singleton either.


    He is right but! The fact that "sigletons are evil" (google it) is not
    always a common knowledge.
    If you've learned singleton you are being expected to use it and
    reciting to you prof\tester why you decided to avoid using singletons
    will not always be accepted.
     
    ManicQin, May 18, 2008
    #12
  13. On May 18, 11:43 am, darren <> wrote:

    > 5. if an entry is in there, a new thread is spawned to handle the
    > request. That thread then dies.


    If you make the shared data structure thread safe so that multiple
    threads can get element from it, you do not have to create and destroy
    the thread but you can launch a certain number of worker threads that
    compete to obtain a work packets from the queue. This is a simple
    solution. If you want to tune it dynamically according to the work
    load, a thread pool can be set up.

    Best Regards,
    Szabolcs
     
    Szabolcs Ferenczi, May 18, 2008
    #13
  14. darren

    James Kanze Guest

    On 18 mai, 12:44, Szabolcs Ferenczi <>
    wrote:
    > On May 18, 11:43 am, darren <> wrote:


    > > At first I was thinking that an object should create a
    > > thread. this has been advised as bad (thanks for the
    > > advice!).


    > That is not a bad idea at all that an object creates a thread
    > in the constructor. Do not be mistaken.


    Except that, as Chris has already pointed out, it results in a
    race condition. It's a serious design error.

    --
    James Kanze (GABI Software) email:
    Conseils en informatique orientée objet/
    Beratung in objektorientierter Datenverarbeitung
    9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
     
    James Kanze, May 18, 2008
    #14
  15. darren

    James Kanze Guest

    On 18 mai, 13:29, ManicQin <> wrote:
    > On May 18, 12:43 pm, darren <> wrote:


    [...]
    > > Try to avoid using singletons (if you refer to the singleton pattern).
    > > It is not a good idea even in non-MT programs. You can always avoid
    > > using singletons by disciplined programming. In this case you do not
    > > need singleton either.


    > He is right


    Bullshit. (If you read any of Szabolcs' postings, you'll
    quickly realize that he's never actually written any real code.)
    You don't want to abuse them, but there are special cases where
    they are the appropriate solution. In the case of detached
    threads, in fact, some form of singleton is almost necessary for
    a clean shutdown.

    --
    James Kanze (GABI Software) email:
    Conseils en informatique orientée objet/
    Beratung in objektorientierter Datenverarbeitung
    9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
     
    James Kanze, May 18, 2008
    #15
  16. On May 18, 3:23 pm, James Kanze <> wrote:

    > Except that, as Chris has already pointed out, it results in a
    > race condition.  It's a serious design error.


    Well, he did not point out anything but claimed something. He has
    postings that he used to correct the next hour or the next day.

    You better read carefully what I have written. I highlighted that one
    needs discipline for it. It is hopless for you but at least you calm
    down.

    I hope I could help though.

    Best Regards,
    Szabolcs
     
    Szabolcs Ferenczi, May 18, 2008
    #16
  17. On May 18, 3:27 pm, James Kanze <> wrote:
    > On 18 mai, 13:29, ManicQin <> wrote:
    >
    > > On May 18, 12:43 pm, darren <> wrote:

    >
    >     [...]
    >
    > > > Try to avoid using singletons (if you refer to the singleton pattern).
    > > > It is not a good idea even in non-MT programs. You can always avoid
    > > > using singletons by disciplined programming. In this case you do not
    > > > need singleton either.

    > > He is right

    >
    > Bullshit.  (If you read any of Szabolcs' postings, you'll
    > quickly realize that he's never actually written any real code.)
    > You don't want to abuse them, but there are special cases where
    > they are the appropriate solution.  In the case of detached
    > threads, in fact, some form of singleton is almost necessary for
    > a clean shutdown.


    Calm down, my friend, and do not write "Bullshit".

    If you do not know about something, do not attack it just because of
    your ignorance.

    The singleton pattern is discouraged even by its creator.

    Best Regards,
    Szabolcs
     
    Szabolcs Ferenczi, May 18, 2008
    #17
  18. darren

    James Kanze Guest

    On 18 mai, 11:43, darren <> wrote:
    > On May 18, 1:13 am, ManicQin <> wrote:


    [...]
    > > If you could shed some light on your project maybe people
    > > could give a more precise counsel on the MT method you
    > > should use...


    > Its a multithreaded web server using pthreads and the socket
    > api (hey everybody else in my class looking for ideas :) ).


    > Here's my basic algorithm:
    > 1. main() makes a singleton ServerKernal object to control program
    > flow
    > 2. ServerKernal listens for requests on a specified port. this is done
    > by creating a thread that loops and continuously accepts connections.


    There's really not necessarily a reason to start a separate
    thread for this.

    > 3. A successful accepted connection is put into a queue (from the STL
    > library).
    > 4. Meanwhile, back at the ranch, another thread is created and running
    > that continuously checks for entries into the queue.
    > 5. if an entry is in there, a new thread is spawned to handle the
    > request. That thread then dies.


    That sounds like extra complication as well. What's wrong with
    just starting the connection thread immediately when you get the
    connection?

    > What do you think of this algorithm?


    What are the constraints concerning shutdown? If you don't have
    any (i.e. the only way to stop the process is to kill it), then
    your connection threads are basically fire and forget: you don't
    really need to keep any trace of them (which means that you
    don't have any "thread" objects). In fact, unless the server
    needs to access shared in memory data, it may be preferable to
    use processes instead of threads. (That's what a lot of
    traditional servers do: FTP, telnet, etc.)

    > A couple of things i'm thinking about:
    > 1. As per the reason i created this post, I was thinking about how
    > objects related to threads.


    They don't, necessarily. Fundamentally, the "thread" object is
    somewhere in the OS, not in your code. If the thread should do
    something resulting in returned data, and you will eventually
    have to wait for it (join), then some sort of object is probably
    desirable in your application. This object is traditionally
    called a "thread" as well, but it's important to realize that it
    isn't really the thread itself, it's just an interface to
    certain characteristics of the thread the OS is maintaining. If
    you need to support clean shutdown, then you'll need some means
    of keeping track of which threads are active (which might result
    in "thread" objects as well), so that you can notify them of a
    desired shutdown, and wait until all of them have shutdown. But
    in the simplest case of a server, it's fire and forget for each
    connection. Just start the thread, and forget about it; the
    thread takes care of everything itself. (Conceptually, you
    might think of it as an object, and within the OS, it certainly
    is, but practically, in your code, at least with pthreads or
    WinThreads, it's a function with its own stack, and that's it.)

    > At first I was thinking that an object should create a thread.
    > this has been advised as bad (thanks for the advice!).


    In the end, it is the call to pthread_create which will create
    the thread. Depending on what you want to do with it, you might
    want to create an object which manages this information. The
    type of this object should not be a base class, nor should
    instances be members of another object. Practically, doing so
    leads to race conditions; conceptually, you're modeling
    something in the OS backwards from the way the OS implements it:
    in the OS, it is the thread which owns the functions it is
    executing, and not vice versa---in other words, the "object"
    which you execute is a member or base class of the thread, and
    not vice versa. In C++, supposing you need a thread object, you
    can do this in three ways: the type of the thread object can be a
    template on the object to be executed, it can take over
    ownership of an object create elsewhere, or it can make a copy
    of an object you pass its constructor. The latter is what
    Boost does, but it requires some pretty tricky template
    programming (not in Boost threads, but in Boost functions, which
    Boost threads uses) to work. The second solution is probably
    the easiest for a beginner to implement; you define an abstract
    base class Threadable or Runnable, with an pure virtual
    function run, and you pass a pointer to this to your thread
    object.

    > Now I'm thinking that instead, threads should create objects,
    > and destroy them before the thread ends.


    Almost certainly. And each thread has its own stack on which it
    can do this.

    > for example, when a request is in the queue, a thread is
    > created to handle it. Within this new thread, a
    > RequestHandler object is instantiated. It's methods are used
    > to process the request. The object is then destroyed.
    > Finally, the thread ends.


    > 2 I was thinking about thread pools. Maybe there could be 10
    > threads set up, waiting for requests. I dont know much about
    > thread pools yet though. It may not be appropriate. Or, maybe
    > the threads could be sleeping, then awoken by signaling when a
    > request enters the queue.


    The usual way to use thread pools is for all of the threads to
    wait on a message queue. The listener thread then sends the
    incoming request to the queue; depending on design constraints,
    it may decide to create an additional new thread first, if no
    thread is currently waiting, or to reject the connection, if no
    thread picks up the message after a specified time.

    --
    James Kanze (GABI Software) email:
    Conseils en informatique orientée objet/
    Beratung in objektorientierter Datenverarbeitung
    9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
     
    James Kanze, May 18, 2008
    #18
  19. darren

    James Kanze Guest

    On 18 mai, 11:43, darren <> wrote:
    > On May 18, 1:13 am, ManicQin <> wrote:


    [...]
    > > If you could shed some light on your project maybe people
    > > could give a more precise counsel on the MT method you
    > > should use...


    > Its a multithreaded web server using pthreads and the socket
    > api (hey everybody else in my class looking for ideas :) ).


    > Here's my basic algorithm:
    > 1. main() makes a singleton ServerKernal object to control program
    > flow
    > 2. ServerKernal listens for requests on a specified port. this is done
    > by creating a thread that loops and continuously accepts connections.


    There's really not necessarily a reason to start a separate
    thread for this.

    > 3. A successful accepted connection is put into a queue (from the STL
    > library).
    > 4. Meanwhile, back at the ranch, another thread is created and running
    > that continuously checks for entries into the queue.
    > 5. if an entry is in there, a new thread is spawned to handle the
    > request. That thread then dies.


    That sounds like extra complication as well. What's wrong with
    just starting the connection thread immediately when you get the
    connection?

    > What do you think of this algorithm?


    What are the constraints concerning shutdown? If you don't have
    any (i.e. the only way to stop the process is to kill it), then
    your connection threads are basically fire and forget: you don't
    really need to keep any trace of them (which means that you
    don't have any "thread" objects). In fact, unless the server
    needs to access shared in memory data, it may be preferable to
    use processes instead of threads. (That's what a lot of
    traditional servers do: FTP, telnet, etc.)

    > A couple of things i'm thinking about:
    > 1. As per the reason i created this post, I was thinking about how
    > objects related to threads.


    They don't, necessarily. Fundamentally, the "thread" object is
    somewhere in the OS, not in your code. If the thread should do
    something resulting in returned data, and you will eventually
    have to wait for it (join), then some sort of object is probably
    desirable in your application. This object is traditionally
    called a "thread" as well, but it's important to realize that it
    isn't really the thread itself, it's just an interface to
    certain characteristics of the thread the OS is maintaining. If
    you need to support clean shutdown, then you'll need some means
    of keeping track of which threads are active (which might result
    in "thread" objects as well), so that you can notify them of a
    desired shutdown, and wait until all of them have shutdown. But
    in the simplest case of a server, it's fire and forget for each
    connection. Just start the thread, and forget about it; the
    thread takes care of everything itself. (Conceptually, you
    might think of it as an object, and within the OS, it certainly
    is, but practically, in your code, at least with pthreads or
    WinThreads, it's a function with its own stack, and that's it.)

    > At first I was thinking that an object should create a thread.
    > this has been advised as bad (thanks for the advice!).


    In the end, it is the call to pthread_create which will create
    the thread. Depending on what you want to do with it, you might
    want to create an object which manages this information. The
    type of this object should not be a base class, nor should
    instances be members of another object. Practically, doing so
    leads to race conditions; conceptually, you're modeling
    something in the OS backwards from the way the OS implements it:
    in the OS, it is the thread which owns the functions it is
    executing, and not vice versa---in other words, the "object"
    which you execute is a member or base class of the thread, and
    not vice versa. In C++, supposing you need a thread object, you
    can do this in three ways: the type of the thread object can be a
    template on the object to be executed, it can take over
    ownership of an object create elsewhere, or it can make a copy
    of an object you pass its constructor. The latter is what
    Boost does, but it requires some pretty tricky template
    programming (not in Boost threads, but in Boost functions, which
    Boost threads uses) to work. The second solution is probably
    the easiest for a beginner to implement; you define an abstract
    base class Threadable or Runnable, with an pure virtual
    function run, and you pass a pointer to this to your thread
    object.

    > Now I'm thinking that instead, threads should create objects,
    > and destroy them before the thread ends.


    Almost certainly. And each thread has its own stack on which it
    can do this.

    > for example, when a request is in the queue, a thread is
    > created to handle it. Within this new thread, a
    > RequestHandler object is instantiated. It's methods are used
    > to process the request. The object is then destroyed.
    > Finally, the thread ends.


    > 2 I was thinking about thread pools. Maybe there could be 10
    > threads set up, waiting for requests. I dont know much about
    > thread pools yet though. It may not be appropriate. Or, maybe
    > the threads could be sleeping, then awoken by signaling when a
    > request enters the queue.


    The usual way to use thread pools is for all of the threads to
    wait on a message queue. The listener thread then sends the
    incoming request to the queue; depending on design constraints,
    it may decide to create an additional new thread first, if no
    thread is currently waiting, or to reject the connection, if no
    thread picks up the message after a specified time.

    --
    James Kanze (GABI Software) email:
    Conseils en informatique orientée objet/
    Beratung in objektorientierter Datenverarbeitung
    9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
     
    James Kanze, May 18, 2008
    #19
  20. darren

    ManicQin Guest

    On May 18, 4:56 pm, James Kanze <> wrote:

    > What are the constraints concerning shutdown? If you don't have
    > any (i.e. the only way to stop the process is to kill it), then
    > your connection threads are basically fire and forget: you don't
    > really need to keep any trace of them (which means that you
    > don't have any "thread" objects). In fact, unless the server
    > needs to access shared in memory data, it may be preferable to
    > use processes instead of threads. (That's what a lot of
    > traditional servers do: FTP, telnet, etc.)



    When you say processes do you mean different processes running
    and communicating via files\pipelines\sockets and so on?

    1) Wont it just complicate things?
    2) Darren is supposed to submit his project to his prof\tester
    usually spliting your projects (IMHO) to sub processes gives it a...
    (maybe unjustified) scent of a bad design... Most of my professors
    were
    fixed on the notion that an application is one process. (I think that
    spliting
    your process to subs is a concept that is more acknowledged in linux
    \unix platforms then
    windows. AFAIK it's partially due to the reason that in linux you only
    load your code
    once for all the instances of the application... or something like
    that... CMIIW!!!)
     
    ManicQin, May 18, 2008
    #20
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. patrick boulay
    Replies:
    7
    Views:
    6,787
    PatrickBlais
    Apr 2, 2009
  2. ghoetker
    Replies:
    1
    Views:
    378
  3. Marcin Rodzik
    Replies:
    6
    Views:
    357
    Marcin Rodzik
    Aug 25, 2011
  4. Marcin Rodzik
    Replies:
    1
    Views:
    280
    markspace
    Aug 2, 2011
  5. Bryan Balfour
    Replies:
    5
    Views:
    129
    Bryan Balfour
    Jul 28, 2005
Loading...

Share This Page