April 29, 2024, 10:51:06 AM

News:

Own IWBasic 2.x ? -----> Get your free upgrade to 3.x now.........


CThread and CCriticalSection Classes

Started by Mike Stefanik, February 13, 2006, 03:07:22 AM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

Mike Stefanik

Here's another couple of classes that I've been working on. The CThread class deals with creating and managing threads, and the CCriticalSection class allows you to easily synchronize access to shared resources by multiple threads.

Creating a new thread is really pretty easy. All you have to do is create a class derived from CThread and add the code that you want to have executed in the ThreadMain method. For example, you could create a class called CWorkerThread that looked like this:


class CWorkerThread:CThread
{
declare ThreadMain(), unsigned int;
}

// Thread entry point
CWorkerThread::ThreadMain(), unsigned int
{
    // Do something useful here

    return 0;
}


Then, you simply create an instance of your CWorkerThread class and call the Create method:


CWorkerThread* pThread;

pThread = new(CWorkerThread, 1);
pThread->Create();


That's it. The thread will start executing whatever is in ThreadMain, and the return value from ThreadMain is set as the thread's exit code. There's two ways to handle checking if the thread is done. One is to poll the thread using the IsFinished() method, typically using a timer. The other is to simply wait for the thread to terminate by calling the Join method, such as:


if (pThread->Join())
    pThread->GetExitCode(&dwExitCode);


There's also methods that let you do things like explicitly yield to other threads, change a thread's priority, suspend and resume  execution of the thread and so on. To make things easier with debugging, you can also assign a name to your thread and return that value by calling the GetName method. So instead of just going by the numeric thread ID, you can name it "File Upload 1" and then use that with functions like OutputDebugString.

Suggestions, problems, questions are welcome. I've attached the classes and an example program that creates three threads which update some UI controls and demonstrates synchronized access to global variables.
Mike Stefanik
www.catalyst.com
Catalyst Development Corporation

Parker

I wrote a couple of thread functions for the CCL, but I haven't learned much about them. I'll have to take a look at your classes. Thanks.

Mike Stefanik

I've updated the classes and example for the latest version of the compiler (the 2/16/2006 build).
Mike Stefanik
www.catalyst.com
Catalyst Development Corporation

John Syl.

Mike or anyone,
when using a CriticalSection, am I right in thinking that you will have several instances of CriticalSection to control different areas of critical code?

John
Intel 3.6 p4 ht, XP home,2 gb mem, 400 gb hd 20gb raid 0, Nvidia 6600le.
AMD k6-2 500, 40gb.

Started on PDP11 Assembler, BASIC, GWBASIC, 6502, Z80, 80x86, Java, Pascal, C, C++, 
IBasic (std & pro), Aurora, EBasic.  (Master of none, but it's been fun!)

Mike Stefanik

That really depends on how you want to synchronize access to the code. A critical section is shared by all threads (of course), and once one thread enters that critical section, all other threads that reach that code will block until that thread exits the section. Generally speaking, if you're synchronizing access to global data then you only need a single critical section, since any public function can access it and they may be called by any thread.

Keep in mind that critical sections are fairly "expensive" if all you're doing is something like updating a global value in a multithreaded application. For that, you'd really want to use the functions like InterlockedExchange, InterlockedIncrement, InterlockedDecrement and so on.
Mike Stefanik
www.catalyst.com
Catalyst Development Corporation

kryton9

This sounds really cool. Does a thread run as a service in Windows then?

John Syl.

Thanks Mike, I'll try and put this as best as I can, as it is in the embrionic stage, not sure if it is feasible, good or advised or even if I know what I want or what I'm talking about.  This I will only know for sure when I get a basic design done, I'm at the ideas stage..

In your example you made the CriticalSection global, so If I have x amount of threads running class a object, I also have y amount of threads running a class b object, each class will have method(s) with critical sections which are obviously not the same as thety are different classes.

So, If a thread of x locks it's critical section, then a thread of y cannot enter it's own critical section beacuse the global critical section is locked.
So instead of making the critical section global, I make it local to a class (private).  Yes?

Also are there any practical limits to the number of threads one can have running?

many thanks
John
Intel 3.6 p4 ht, XP home,2 gb mem, 400 gb hd 20gb raid 0, Nvidia 6600le.
AMD k6-2 500, 40gb.

Started on PDP11 Assembler, BASIC, GWBASIC, 6502, Z80, 80x86, Java, Pascal, C, C++, 
IBasic (std & pro), Aurora, EBasic.  (Master of none, but it's been fun!)

Mike Stefanik

You don't want to create a critical section for each instance of the class. You want to do it at the module level so that all instances of the class share the same critical section.

The practical limit on the number of threads really depends on the system; primarily how many processors it has and how much physical memory. Of course, it also depends on how much "work" those threads are doing. If they're primarily I/O bound then you could create hundreds. If they're primarily compute bound, then you need to do some performance monitoring and watch the overall CPU utilization.
Mike Stefanik
www.catalyst.com
Catalyst Development Corporation

John Syl.

Thanks Mike for that, I got my brain crosswired when I referred to putting the critical section in the class..after reading your reply I realised that was not what I wanted.
If I make several instances of CriticalSection and use each instance of critical section to lock a specific area of code or areas of code, that will get me on the right track.
Many thanks for helping me get this idea sorted.

John
Intel 3.6 p4 ht, XP home,2 gb mem, 400 gb hd 20gb raid 0, Nvidia 6600le.
AMD k6-2 500, 40gb.

Started on PDP11 Assembler, BASIC, GWBASIC, 6502, Z80, 80x86, Java, Pascal, C, C++, 
IBasic (std & pro), Aurora, EBasic.  (Master of none, but it's been fun!)

Parker

kryton9: Services and threads are completely different. A thread is just another line of execution, while a service is a background process run by the operating system.

You use threads when you want to execute two pieces of code at once in the same program. For example, the Aurora IDE uses a thread for executing the compiler and other tools, so it doesn't freeze up while you are compiling.

A service is something that's run in the background and hidden. The Apache web server is run as a service so that you don't have a console window open and so that you don't have to start it manually every time you turn on your computer. Services can also run when nobody has logged on yet. This means that you can leave a computer on but not be logged on (for security usually), but it can still be running a web server. There are many other services available also.