Very basic multithreading

Hi.
I've been experimenting with basic threading, trying to create a thread running a loop, and being breakable by cin action. Here's my code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#include <windows.h>
#include <stdlib.h>
#include <iostream>
#include <winbase.h>
using namespace std;

int BreakIt(0);
HANDLE ThreadHandle;
DWORD WINAPI Loop(void*){
    while(1)if(BreakIt)break;
    MessageBox(NULL,"Broken!","Loop",MB_ICONEXCLAMATION);
    return 0;
};
int BreakTheLoop(){
    BreakIt=true;
    return 0;
};
int InitThread(){
    ThreadHandle=CreateThread(0,0,Loop,0,0,0);
    if(ThreadHandle==NULL)cout<<"Error: "<<GetLastError()<<"\n";
    return 0;
};
int main(){
    InitThread();
    cout<<"Thread init.\n";
    cin.get();
    BreakTheLoop();
    cin.get();
    CloseHandle(ThreadHandle);
    return 0;
};

By my calculations, it should create the separate thread running Loop(), wait for user input, and when the user presses enter, break the loop (aka. display the "Broken!" message box). However, nothing seems to happen. The more bizarre part is that if I add something like:

cout<<".";

inside the while(1) loop, it suddenly and magically starts working perfectly: it couts . all over the screen, but when I press enter, it displays the "Broken!" message, which is what I want.
Now why would that happen? How is anything related to what is executed inside the threaded function?

Thanks in advance.
Are you building the release target?

If so, try making BreakIt volatile.

volatile int BreakIt(0);

Andy
Seems to be working. Thank you.
What was I doing wrong? I know the "volatile" prevents optimization, so perhaps somehow the loop was being modified (erasing the if(BreakIt)break; line since the compiler assumed BreakIt will never change state perhaps?), but why did the cout call make things work?

[Edit] Since we're here, is it possible to call a non-dword(void*) function from inside a class in a separate thread? I tried accomplishing that using a wrapper, but it produces a segmentation fault. I mean something like:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <windows.h>
#include <winbase.h>
#include <iostream>
using namespace std;

HANDLE ThreadHandle;
class Foo{
    public:
    int Func();
};
int Foo::Func(){
    return 0;
};
DWORD WINAPI FuncWrapper(void* P){
    return (DWORD)((Foo*)P)->Func();
};
main(){
    Foo MyFoo;
    ThreadHandle=CreateThread(0,0,FuncWrapper,&MyFoo,0,0);
    cin.get();
    CloseHandle(ThreadHandle);
    return 0;
};


or need I "volatilize" something in here too?

[Edit] This exact code is doing its job. Going to debug what the problem is.

[Edit] It's looking good now. No idea how that error showed up.
Last edited on
Yes, it's the optization. I guess that the optimization wasn't worth doing when the cost of the cout call had to be met.

But as the wait loop you're using is something that should never occur in real code, this particular problem is just a curiousity. Spinning an empty loop is potentially very costly in terms of CPU, so you would use a wait function in practice.

Using a class for the thread is better. This code is just for illustrative purposes.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#include <windows.h> // windows.h includes winbase.h
#include <cstdlib>
#include <iostream>
using namespace std;

HANDLE EventHandle;
HANDLE ThreadHandle;
DWORD WINAPI Loop(void*){
    WaitForSingleObject(EventHandle, INFINITE);
    MessageBox(NULL,"Broken!","Loop",MB_ICONEXCLAMATION);
    return 0;
}
int BreakTheLoop(){
    SetEvent(EventHandle);
    return 0;
}
int Init(){
    EventHandle = CreateEvent(NULL, TRUE, FALSE, NULL);
    if(EventHandle == NULL)
        cout<<"Failed to create event; error: "<<GetLastError()<<"\n";
    ThreadHandle=CreateThread(0,0,Loop,0,0,0);
    if(ThreadHandle == NULL)
        cout<<"Failed to create thread; error: "<<GetLastError()<<"\n";
    return 0;
}
int TearDown(){
    if(ThreadHandle != NULL){
        CloseHandle(ThreadHandle);
        ThreadHandle = NULL;
    }
    if(EventHandle != NULL){
        CloseHandle(EventHandle);
        ThreadEvent = NULL;
    return 0;
}
int main(){
    cout<<"Init\n";
    Init();
    cin.get();
    cout<<"BreakTheLoop\n";
    BreakTheLoop();
    // wait for thread to signal that it's ended
    WaitForSingleObject(ThreadHandle, INFINITE);
    cout<<"Thread has exited\n";
    cin.get();
    cout<<"TearDown\n";
    TearDown();
    return 0;
}


Andy
Last edited on
I see.
Compilers are complicated things :D It's hard to understand how they "think" everything...
Thank you for the time. I'll now mark this as solved.
Topic archived. No new replies allowed.