Thread

Multithreading Tutorial (Was to be "Is there a wait command?") (Sdk)

Multithreading Tutorial (Was to be "Is there a wait command?") // Sdk

1  |  

o0oiiijoshiiio0o

Jul 17, 2002, 10:34am
Multithreading is a good thing. I'll give you some code to get you started,
but be warned that my code actually only waits 5 between saying it will wait
5 and saying it has waited 5 - it won't stop its other actions from running.
Excersise for the student, not the woke-up-10-minutes-ago teacher ;)

#include <windows.h>
#include <aw.h>
#include <time.h>

HANDLE d_ThreadHandle;
DWORD d_threadID;
bool d_IsRunning;

int StartTime;
int TimeToFinish;

void TimerStarter()
{
aw_say("Behold, as I wait a marvelous 5 seconds!");

// Check to make sure a handle doesn't already exist.
if(d_ThreadHandle)
{
return;
}

// Create the thread to run immediately. TimerTimer is the actual
procedure
d_ThreadHandle = CreateThread(NULL,
0,
(unsigned
long (_stdcall*)(void*))TimerTimer,
0,
0,

(LPDWORD)&d_threadID);

if(d_ThreadHandle)
{
// An error occured. GetError will return a DWORD that you can look
up on msdn.microsoft.com
}

d_IsRunning = true;

// StartTime = ??? I still don't have my K&R at my desk, but look up
time.h
// TimeToFinish = StartTime + <5 seconds. Implement this depending on
which
// member of the time_t you just used a second ago>
}

DWORD WINAPI TimerTimer()
{
// This is the thread procedure function. Think main() for the thread.
//int CurrentTime = <make this identical to the StartTime = from before>

if(TimeToFinish - CurrentTime <= StartTime)
TimeFinish();

return 0;
}

void TimeFinish()
{
// Called when our 5 seconds are up

aw_say("Tada! 5 seconds!");
d_IsRunning = false;
CloseHandle(d_ThreadHandle); // Normally we'd use
WaitForSingleObject, but
// we know because this function was called, it's done.
d_ThreadHandle = NULL;
}

Now you can call TimeStart() from your main thread, and there'll be 5
seconds between one message and the next (but it won't actually stop the
rest of your program). Shamus told me that the SDK isn't thread safe but
single instance programs should be fine, so..... keep that in mind. Check
d_IsRunning to see if the thread has finished yet... Ask me if you need help
with actually understanding the concept of threads...

Another important thing is thread safety. To show the necessity...

Take, for example, a program that has two functions that create threads:

FindObjectInList
DeleteEntireList

and they're designed to manipulate your linked list (Aww, come on, surely
you know how to do that. They're so much fun! ::shrugs:: ask me if not).

However, if you call DeleteEntireList, and then FindObjectInList,
FindObjectInList may traverse right onto an empty pointer, thus creating a
serious problem... Actually, probably a crash of your program.

What you need is a Mutex (Mutual Exclusivity Operator, or something like
that). Mutex's are like those red-and-green lights on the railroad tracks.
They say, ok, now it's safe for one guy to go, now it's safe for the other.
As long as you aren't playing with the same toys at the same time, sharing
can be fun.

I'm not actually going to give you code beyond copy-pasting from something
of mine that's only a slight modification on elsewhere's code. I have two
functions, one for a blocking mutex and one for a non-blocking mutex. I'm
gunna give you the blocking mutex.

Works simple: For your valuable data (like your list) you make an instance
of the mutex. Whenever you need to access it, you call MutexOn();... If it
is off, it's turned on and now you can access the data. If it is turned on,
it stops you from going (that's the blocking part) until the other guy calls
MutexOff, at which point you're good to access the data. When you're done,
you call MutexOff();.


class cMonitor
{
HANDLE d_mutex;

public:
cMonitor()
{
// This mutex will help the two threads share their toys.
d_mutex = CreateMutex( NULL, false, NULL );
if( d_mutex == NULL )
throw cError( "cMonitor::cMonitor() - Mutex creation failed." );
}


virtual ~cMonitor()
{
if( d_mutex != NULL )
{
CloseHandle( d_mutex );
d_mutex = NULL;
}
}

void MutexOn() const
{
WaitForSingleObject( d_mutex, INFINITE ); // To be safe...
}

void MutexOff() const
{
ReleaseMutex( d_mutex ); // To be safe...
}
}

-J

[View Quote]

faber

Aug 1, 2002, 6:57pm
"o0oiiijoshiiio0o" <joshua_trask at capecod.com> schrieb im Newsbeitrag news:3d356465 at server1.Activeworlds.com...

> DWORD WINAPI TimerTimer()
> {
> // This is the thread procedure function. Think main() for the thread.
> //int CurrentTime = <make this identical to the StartTime = from before>
>
> if(TimeToFinish - CurrentTime <= StartTime)
> TimeFinish();
>
> return 0;
> }
>

I just had to comment on this: If this is your ThreadFunction, your thread won't wait 5 seconds. It will determine that 5 seconds
are not yet over and exit. I am not sure about your time calculation, so it might even call TimeFinish() but not after 5 seconds but
immediately. There is no loop in there or Sleep() or Waitxxx() which would cause the thread to spend some time anywhere.

- Faber

faber

Aug 1, 2002, 6:58pm
[View Quote]
This one can be accomplished by using the function Sleep() unless your bot has a GUI, which complicated things.

use Sleep(5000); to wait 5 seconds.

- Faber

o0oiiijoshiiio0o

Aug 1, 2002, 8:39pm
Ahahah. Yeah. That was stoooopid of me. Well, it should have a loop that
checks the difference and calls the finisher once there is none... Oops.

-J

[View Quote]

1  |  
Awportals.com is a privately held community resource website dedicated to Active Worlds.
Copyright (c) Mark Randall 2006 - 2024. All Rights Reserved.
Awportals.com   ·   ProLibraries Live   ·   Twitter   ·   LinkedIn