Welcome
Example Code
C and C++
Argument Parsing
Create Subprocess
Create Thread
Is Subprocess Done
Non-Blocking File (Unix)
Mutex (Lock)
TCP Server
Wait For File (Unix)
Python
Non-Blocking Read

Monju System Architects



Code - C++ - Create Thread
Download: thread.cpp (the linked-to file is properly tabbed)
Requires: mutex.h, mutex.cpp, thread.h
//  Copyright (c) 2007, Monju System Architects
//
//  Released under the Monju-Public copyright license:
//
//  Permission is hereby granted, free of charge, to any person or entity
//  obtaining a copy of this software and associated documentation files
//  (the "Software"), to deal in the Software without restriction,
//  including without limitation the rights to use, copy, modify, merge,
//  publish, distribute, sublicense, and/or sell copies and modifications
//  of the Software, and to permit persons to whom the Software is
//  furnished to do so, subject to the following conditions:
//
//  The above copyright notice and this permission notice shall be
//  included in all copies or substantial portions of published, sold, or
//  ownership-transferred versions of the Software. The notices are not
//  required for binary-only releases or binary-only derivatives of the
//  Software, or documentation provided with binary-only releases and
//  binary-only derivatives.
//
//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
//  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
//  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
//  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
//  CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
//  TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
//  SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.




//  INCLUDES.
#ifndef _WIN32
    #include <unistd.h>
#endif

#include "public/thread.h"
#include "public/mutex.h"



//  FUNCTION DECLARATIONS.
SYSTEM_THREAD_FUNCTION_RETURN_TYPE _threadFunction(void* argument);




//  GLOBAL VARIABLES.
static MUTEX_TYPE           g_threadCountMutex              = createMutex();
static int                  g_threadCount                   = 0;




//  createThread()
void createThread(THREAD_FUNCTION_TYPE  threadFunction,
                  void*                 threadArgument,
                  void**                ppOptionalResult) {
    createThread(NULL, threadFunction, threadArgument, NULL);
}
void createThread(THREAD_TYPE*          pThread,
                  THREAD_FUNCTION_TYPE  threadFunction,
                  void*                 threadArgument,
                  void**                ppResult) {

    //  ALLOCATE NEW ARGUMENTS.
    void** ppArguments  = new void*[3];
    ppArguments[1]      = (void*)threadFunction;
    ppArguments[2]      = threadArgument;
    ppArguments[3]      = ppResult;

    //  START A NEW THREAD WITH THE INTERNAL THREAD FUNCTION FOR PROPER
    //  EXCEPTION HANDLING AND THREAD MANAGEMENT.
    #ifdef _WIN32
        *pThread = CreateThread(NULL,
                                0,
                                (LPTHREAD_START_ROUTINE)_threadFunction,
                                ppArguments,
                                0,
                                NULL);
        if (pThread == NULL) {
            delete(ppArguments);
            throw("CreateThread() failed.");
        }
    #else
        if (0 != pthread_create(pThread, NULL, threadFunction, ppArguments)) {
            delete(ppArguments);
            throw("pthread_create() failed.");
        }
    #endif
}



//  msleep()
void msleep(int milliseconds) {
    #ifdef _WIN32
        Sleep(milliseconds);
    #else
        usleep(milliseconds * 1000);
    #endif
}



//  usleep()
#ifdef _WIN32
    void usleep(int microseconds) {
        Sleep(microseconds / 1000);
    }
#endif



//  waitForAllThreads()
bool waitForAllThreads(double timeout) {

    //  WAIT FOR THREADS.
    while (timeout > 0.0) {
        if (g_threadCount > 0) {
            msleep(1);
            timeout -= .001;
            continue;
        }
        return true;
    }
    return false;
}



//  _threadFunction()
SYSTEM_THREAD_FUNCTION_RETURN_TYPE _threadFunction(void* argument) {

    //  GET THE ARGUMENTS.
    void**                  ppArgument      = (void**)argument;
    THREAD_FUNCTION_TYPE*   pThreadFunction = (THREAD_FUNCTION_TYPE*)(&(ppArgument[0]));
    void*                   pThreadArgument = ppArgument[1];
    void**                  ppResult        = (void**)ppArgument[2];
    int                     threadExitValue = 0;

    //  INCREMENT THE THREAD COUNT.
    lockMutex(g_threadCountMutex);
    g_threadCount++;
    unlockMutex(g_threadCountMutex);

    //  CALL THE FUNCTION.
    try {
        void* pResult = (*pThreadFunction)(pThreadArgument);
        if (ppResult != NULL) {
            *ppResult = pResult;
        }
    }

    //  CATCH ANY EXCEPTIONS.
    catch (...) {
        threadExitValue = 1;
    }

    //  DELETE THE ARGUMENT.
    delete ppArgument;

    //  DECREMENT THE THREAD COUNT.
    lockMutex(g_threadCountMutex);
    g_threadCount--;
    unlockMutex(g_threadCountMutex);

    //  RETURN OUR EXIT STATUS.
    return (SYSTEM_THREAD_FUNCTION_RETURN_TYPE)threadExitValue;
}