I revised a code i found on the net. It doesn't print/output "0 1 2 3" when running it?. any potential bad errors?.

#include <iostream>
#include <windows.h>

class Thread
{
    public:
    Thread();
    static void * EntryPoint(void*);
    int Start();
    int Run(int arg);
    void Execute(int);
    int Arg() const {return Arg_;}
    void Arg(int a){Arg_ = a;}
    private:
    int Arg_;
};

Thread::Thread() {}

void * Thread::EntryPoint(void * pthis)
{
    Thread * pt = (Thread*)pthis;
    pt->Run( pt->Arg() );
    return 0;
}

int Thread::Start()
{
    HANDLE h[4];

    for (int i = 0; i < 4; i++)
    {
        DWORD dwArg = (DWORD) i;
        Arg(dwArg);
        h[i] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)EntryPoint, &dwArg, 0, NULL);
    }

    WaitForMultipleObjects(4, h, TRUE, INFINITE);

    return 0;
}

int Thread::Run(int arg)
{
    Execute( arg );
    return 0;
}

void Thread::Execute(int a)
{
    printf("%d\n", a);
}

int main()
{
    Thread pt;
    pt.Start();
    return 0;
}

Recommended Answers

All 3 Replies

After I include cstdio the program compiled and ran as expected..Actaully line 33 in your program might be incorrect. Your passing the address of dwArg to create thread which is changing as the loop iterates, this is probably what's causing the weird nummbers.

I tried using a global integer array to pass the values to each thread...It seems to work.

#include <iostream>
#include <windows.h>
#include <cstdio>

#define NO_THREADS 4

int thread_a[NO_THREADS];

class Thread
{
    public:
    Thread();
    static void * EntryPoint(void*);
    int Start();
    int Run(int arg);
    void Execute(int);
    int Arg() const {return Arg_;}
    void Arg(int a){Arg_ = a;}
    private:
    int Arg_;
};

Thread::Thread() {}

void * Thread::EntryPoint(void * pthis)
{
    Thread * pt = (Thread*)pthis;
    pt->Run( pt->Arg() );
    return 0;
}

int Thread::Start()
{
    HANDLE h[4];

    for (int i = 0; i < 4; i++)
    {
        thread_a[i] = i + 1;
        h[i] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)EntryPoint, &thread_a[i], 0, NULL);
    }

    WaitForMultipleObjects(4, h, TRUE, INFINITE);

    return 0;
}

int Thread::Run(int arg)
{
    Execute( arg );
    return 0;
}

void Thread::Execute(int a)
{
    printf("%d\n", a);
}

int main()
{
    Thread pt;
    pt.Start();
    return 0;
}

Your thread class is somewhat confusing because it manages all threads. Compare that to something a bit more single-thread oriented where the calling application manages multiple thread objects:

#include <windows.h>

namespace jsw {
    namespace threading {
        class auto_event {
        public:
            auto_event(): _event(CreateEvent(0, false, false, 0)) {}

            BOOL wait(DWORD timeout = 1) const
            {
                return WaitForSingleObject(_event, timeout) == WAIT_OBJECT_0;
            }

            BOOL set() { return SetEvent(_event); }
        private:
            HANDLE _event;
        };

        class handshake_event {
        public:
            BOOL wait_for_syn(DWORD timeout = 1) const { return _onSyn.wait(timeout); }
            BOOL wait_for_ack(DWORD timeout = 1) const { return _onAck.wait(timeout); }

            void syn() { _onSyn.set(); }
            void ack() { _onAck.set(); }

            BOOL syn(DWORD timeout) { _onSyn.set(); return wait_for_ack(timeout); }
            BOOL ack(DWORD timeout) { _onAck.set(); return wait_for_syn(timeout); }
        private:
            auto_event _onSyn, _onAck;
        };

        class thread {
        public:
            static thread start(
                LPTHREAD_START_ROUTINE fn, LPVOID args = 0, 
                DWORD state = 0, DWORD timeout = 5000)
            {
                return thread(CreateThread(0, 0, fn, args, state, 0), timeout);
            }

            static void sleep(DWORD milliseconds) { Sleep(milliseconds); }
            static void exit(DWORD exitCode) { ExitThread(exitCode); }
        public:
            thread(HANDLE thread, DWORD timeout): _thread(thread), _timeout(timeout) {}
            ~thread() { CloseHandle(_thread); }

            DWORD exit_code() const
            {
                DWORD exitCode = NO_ERROR;

                GetExitCodeThread(_thread, &exitCode);

                return exitCode;
            }

            HANDLE handle() const { return _thread; }
            BOOL is_alive() const { return exit_code() == STILL_ACTIVE; }
            DWORD join() { return WaitForSingleObject(_thread, _timeout); }
            DWORD suspend() { return SuspendThread(_thread); }
            DWORD resume() { return ResumeThread(_thread); }
            BOOL abort(DWORD exitCode) { return TerminateThread(_thread, exitCode); }
        private:
            HANDLE _thread;
            DWORD _timeout;
        };
    }
}

#include <iostream>

using namespace jsw::threading;

DWORD WINAPI worker(LPVOID)
{
    auto_event e;

    for (int i = 0; i < 10; i++) {
        std::cout << i << std::endl;
        e.wait();
    }

    return NO_ERROR;
}

int main()
{
    thread thread1 = thread::start(worker);
    thread thread2 = thread::start(worker);

    thread1.join();
    thread2.join();
}
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.