Click here to Skip to main content
15,895,142 members
Articles / Programming Languages / C++

A C++ Cross-Platform Thread Class

Rate me:
Please Sign up or sign in to vote.
4.56/5 (26 votes)
15 Nov 20034 min read 518.7K   1.8K   49  
Write portable object-oriented threads that work on Win32 and Posix-Compliant systems without modification.
/*
  Example1.cpp

  In this example, I will show you how to write your own class to define your own
  thread function that is tied to an object, along with one way to use a semaphore
  and a mutex.

  Win32:
   Make sure to set "C/C++" -> "Code Generation" -> "Runtime Library" to
      - Multi-Threaded Debug, or
      - Multi-Threaded

  Solaris, Linux, Unix, [Posix Compliant]:

    compile as g++ Example1.cpp /usr/lib/libthread.so

    sometimes it's libpthread.so... try

        find /usr/lib -n "lib*thread*.so"
*/

#include <iostream>
using namespace std;
#include <time.h>

#include "Thread.h"
#include "Mutex.h"
#include "Semaphore.h"

int ii = 0;

// the mutex that all threads will use
Mutex ii_lock;

// the semaphore that the Run() function waits on
Semaphore sem_done;

const static int rep = 1000;

// Our class that has Thread<int> as a base class - int is the parameter type.
class ThreadTester : private Thread<int>
{
  public:
    void Run()
    {
      // create rep #threads with parameter i.
      // if this class was private Thread<void>, there would not be a
      // parameter.
      // real code should check for errors from Create().
      for ( int i = 0; i < rep; ++i )
        Create(i);

      // when sem_done.Post() is called below, this wait completes
      // and also decrements the value of sem_done back to zero.
      sem_done.Wait();

      // another way to do this might be to keep a list of all
      // the thread handles and call Join() for each one,
      // but I chose this way since the number of threads is pre-determined.
    }

  private:
    // the thread entry function, which is part of this object.
    // for Thread<void>, there would be no parameter.
    // i is a reference because it is copied in the _real_ thread
    // initialization, and so this just points to it. handy for
    // structs and things other than integral data types.
    void ThreadMain(int &i)
    {
      // get mutually exclusive access to ii
      ii_lock.Lock();

      ++ii;

      // if this is the last created thread, increment the value
      // of sem_done to 1, which causes Run() to complete.
      if ( ii >= rep ) sem_done.Post();

      // let someone else pass ii_lock
      ii_lock.Unlock();

    }
};

int main()
{
  clock_t c1, c2;
  ThreadTester Test;

  // just to test efficiency.
  c1 = clock();
  Test.Run();
  c2 = clock();

  // you will notice a MAJOR speed increase from win32 to solaris. I havent
  // run this example on anything else, but I assume that win32 threads are
  // either less efficient, or the creation process is more "processor-friendly"
  // since win32's aim isn't to create fast but to run fast
  // (if that's really possible for win32 :P )
  // I get about ~200 for my winXP 850 Pentium III-M -
  // clocked about !!!5000!!! for SunOS 5.8 on (I believe) 4 processors.
  cout << (double)rep/((double)(c2-c1)/(double)CLOCKS_PER_SEC) << " Threads per second!" << endl;

  #ifdef WIN32
  system("pause");
  #endif
  return 0;
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Web Developer
United States United States
I am a student at Portland State University in Portland, Oregon majoring in Mathematics and minoring in Computer Science and Physics.

Comments and Discussions