Tag Archives: programming

Code Timing functions

When it comes to timing your code, there are a lot of options, and depending on what you need to do, not all of them make sense. There are timing functions which utilize callbacks and other ways to periodically call a designated function at a regular interval–I’m not going to discuss those types of timers.

Instead, I’ll focus on the kinds of timing you can do to assess code performance.

To illustrate the differences between these methods, let’s have a simple C++ program:

[code lang=”cpp”]
#include
#include

using namespace std;

int main(int argc, char** argv)
{
//begin timing

//test code
const int nLimit = 10000000;
double sum = 0;

for (int i=0;i {
double rt = sqrt(static_cast(i));
sum+=rt;
}

//end timing

cout << “sum: “<

cout << elapsed << ” second(s) total”< cout << avg << ” second(s) average iteration”<

return 0;
}[/code]

I deliberately chose something simple and fast. Here’s why: if you’re timing something that always takes an hour–a second doesn’t matter, and the first option will work perfectly fine. On the other hand, if you need to time something small that will potentially be repeated dozens, hundreds, thousands, or millions of times, every microsecond can matter.

time_t and CTime

time() is the good old C standby. It’s simple, it’s easy, it’s historic, and it’ll break after 19:14:07, January 18, 2038, UTC.

To remedy this, Microsoft has the _time64() function, which uses the type __time64_t. It improves the lifespan, but not the precision.

Our code is now:
[code lang=”cpp”]
#include
#include
#include

using namespace std;

int main(int argc, char** argv)
{
//begin timing
time_t start = time(NULL);

//test code
const int nLimit = 10000000;
double sum = 0;

for (int i=0;i {
double rt = sqrt(static_cast(i));
sum+=rt;
}

//end timing
time_t end = time(NULL);
cout << “sum: “< long elapsed = static_cast(end – start);
double avg = (double)elapsed / nLimit;
cout << elapsed << ” second(s) total”< cout << avg << ” second(s) average iteration”<

return 0;
}[/code]

Output:
sum: 2.10819e+013
16 second(s) total
0 second(s) average iteration

MFC’s CTime is just a wrapper for time_t (VC++6.0) or __time64_t (VC++7), so nothing new here.

time_t is good when you don’t need very precise measurements, when you’re just interested in the date and/or time, as in wall-clock time, or when it’s your only option.

For timing code, this is not a great option.

GetTickCount

Windows contains a function called GetTickCount which returns the number of milliseconds since the machine was turned on. This gives us 1,000 times better accuracy then time().

[code lang=”cpp”]
#include
#include
#include

using namespace std;

int main(int argc, char** argv)
{
//begin timing
DWORD start = GetTickCount();

//test code
const int nLimit = 10000000;
double sum = 0;

for (int i=0;i {
double rt = sqrt(static_cast(i));
sum+=rt;
}

//end timing
DWORD end = GetTickCount();
cout << “sum: “< double elapsed = (end – start) / 1000.0;//ms –> s
double avg = ((double)elapsed)/ nLimit;
cout << elapsed << ” second(s) total”< cout << avg << ” second(s) average iteration”<

return 0;
}[/code]

Output:
sum: 2.10818e+010
0.172 second(s) total
1.72e-008 second(s) average iteration

As seen above, this value is returned in a DWORD, which is 32-bits wide. 232 milliseconds comes out to about 49 days, at which time the counter rolls over to 0. If you’re timing very short intervals, this probably won’t be a problem. The MSDN documentation has a code example to detect timer wrap-around.

GetTickCount provides much more precision than time_t, but with processor speeds at multiple gigahertz, a lot can happen in a millisecond. Enter…

QueryPerformanceCounter and QueryPerformanceFrequency

This set of functions is also available in the Win32 API and they are much more accurate than time_t and GetTickCount.

Their usage is often paired. QueryPerformanceCounter returns the current count on the timer, and QueryPerformanceFrequency returns how many counts per second there are. The documentation makes clear that timer frequency is not the same as processor clock frequency. This timer is hardware-based, however, and if your computer doesn’t have a timing device, then calling QueryPerformanceCounter returns the same thing as GetTickCount above, and QueryPerformanceFrequency returns 1000 (1000 ms = 1 s).

The code reads:

[code lang=”cpp”]
#include
#include
#include

using namespace std;

int main(int argc, char** argv)
{
//begin timing
LARGE_INTEGER start;
::QueryPerformanceCounter(&start);

//test code
const int nLimit = 10000000;
double sum = 0;

for (int i=0;i {
double rt = sqrt(static_cast(i));
sum+=rt;
}

//end timing
LARGE_INTEGER end;
LARGE_INTEGER countsPerSecond;
::QueryPerformanceCounter(&end);
::QueryPerformanceFrequency(&countsPerSecond);

double elapsed = (double)(end.QuadPart – start.QuadPart) / countsPerSecond.QuadPart;
double avg = elapsed / nLimit;
cout << “sum: “< cout << elapsed << ” second(s) total”< cout << avg << ” second(s) average iteration”<

return 0;
}[/code]

Output:
sum: 2.10818e+010
0.165298 second(s) total
1.65298e-008 second(s) average iteration

You can easily see the much improved precision.

OK, well these are all well and good if you have Windows, but what if you don’t have Windows, or the time isn’t as important as the number of cycles required to compute something?

Here’s…

GetMachineCycleCount

…a function to read the current CPU clock cycle. Note that there aren’t any API or standard library functions to do this so we need to use assembly. Note also that this wasn’t possible until the Pentium came along, so don’t run this code on a pre-Pentium computer. 🙂

[code lang=”cpp”]
#include
#include

using namespace std;

inline __int64 GetMachineCycleCount()
{
__int64 cycles; //64-bit int

_asm rdtsc; // won’t work on 486 or below – only pentium or above
_asm lea ebx,cycles; //ebx = &cycles
_asm mov [ebx],eax; //get low-order dword
_asm mov [ebx+4],edx; //get hi-order dword

return cycles;
}

int main(int argc, char** argv)
{
//begin timing

__int64 start = GetMachineCycleCount();

//test code
const int nLimit = 10000000;
double sum = 0;

for (int i=0;i {
double rt = sqrt(static_cast(i));
sum+=rt;
}

//end timing
__int64 end = GetMachineCycleCount();

cout << “sum: “< __int64 elapsed = end – start;
double avg = (double)elapsed / nLimit;
cout << elapsed << ” cycles total”< cout << avg << ” cycles average iteration”<

return 0;
}[/code]

Output:
sum: 2.10818e+010
263631085 cycles total
26.3631 cycles average iteration

What are some situations where this is useful? If you want to make a piece of code absolutely the fastest on any piece of hardware, regardless of clock-time, this can give you a truer reflection of the effectiveness of your algorithm. If you don’t have a high-performance timer API (and you don’t want to write one), then this is a quick-and-dirty, but effective, solution.

So what about discovering the speed of your processor? Well, there’s no machine instruction to do this. Basically, you have to combine the cycle count with the performance timers and run through a lot of loops to calculate an average.

I hope this has helped some people wade through the various options of timing performance-critical code.

Code Security and Typed Assembly Language

Over the summer I’m taking a class called Programming Languages and Security. This is the first time I’ve delved into security at this level before. It’s a seminar style, which means lots of paper reading, and I am going to give two presentations.

My first presentation was this past Thursday. I spoke about typed assembly language and security automata. It was absolutely fascinating, ignoring the formality of proofs, and all the mathematical notations.

The two papers I discussed were:

The TALx86 begins by describing many shortcomings of the Java Virtual Machine Language (bytecode), including such things as:

  • Semantic errors in the bytecode that could have been discovered if a formal model had been used in its design.
  • Difficulty in compiling languages other than Java into bytecode. For example, it’s literally impossible to correctly compile Scheme into bytecode. OK, Scheme is a pretty esoteric language, but…
  • Difficulty even in extending the Java language because of the bytecode limitations
  • Interpretation is slow, and even though JIT is often used these days, that’s not built-in to the VM

My immediate thought on reading this was, “Hey! .Net addresses each and every single one of these points!”

  • The CLR defines a minimal subset of functionality that must be supported by every .Net language–allowing over 40 languages to be compiled to MSIL
  • As a bonus, MSIL is typed (as is Java bytecode)
  • Just-In-Time compilation was designed in from the beginning and generally has superior performance to Java (in my experience)

It also seems that many of the experimental features present in such early research, such as TALx86, has ended up in .Net and compilers these days. Type safety is being pushed lower and lower. Security policies are being implemented into frameworks, operating systems and compilers, and there are other tools that analyze your code for adherence to security best practices.

On platforms such as .Net, type safety is more important because you can have modules written in VB.Net interacting with objects written in C++ or Python, for example. Those languages don’t know about each other’s types, but at the MSIL level you can ensure safety.

If you’d like, a copy of the presentation is available.

Code Complete 2

I finally bought myself a copy of Steve McConnell’s Code Complete, 2nd Edition. I’ve read about a third of it so far and love it. It’s by far the most practical and useful book on programming I have ever read.

But how to learn it all? Sure, an experience programmer will pick up many of these ideas over time, but how can I start implementing ALL of them?

I think my plan is to read it through once, and then while I sit at my desk at work (or home), leave it open to a random page so I can think about the displayed topic.

A Month with NUnit

I’d been hearing about this thing called NUnit for the past 6 months, and finally two months or so ago I decided to see what all the hoopla is about.

NUnit is a .Net version of the original JUnit unit-testing package for Java. The newest version has a very strong .Net feel with its use of attributes to control testing.

I decided to start using NUnit in my BRayTracer project. Immediately, I was faced with some issues (not problems, just things I needed to decide).

The first is that NUnit works by creating classes that contain methods which have the TestAttribute applied to them. This allows NUnit to find all of the testing code given a module or project.

I could either put this testing code into the same module as the existing code, or I could break my ray tracing code into a separate module. I didn’t want the testing code to bulk up my executable size (which can in some instances translate to slower code due to paging and locality issues). I decided to break my ray tracing code out into a separate module (I was planning on doing this eventually anyway).

Done with the housekeeping, I began setting up my tests.

So far, I’ve implemented about 150 unit tests covering a few my objects. It’s not totally comprehensive yet, but it’s a good start. Effectively testing the entire rendering process will require thousands of tests.

So far, the tests have helped me fix about 10 serious bugs that I had otherwise missed. The regressions testing is helping a lot, since the code is still in a lot of flux.

I’ve been making a strong effort to write all (most) the tests before I write the code they’re supposed to verify. This definitely makes testing more enjoyable, and more likely to get done.

I’ve been thinking about how to use inheritance and polymorphism to my advantage in these unit tests. I have a Shape object and numerous subclasses (Box, Sphere, etc.). I initially had a few abstract functions in Shape to test basic functionality of all shapes, but I found that this isn’t really buying me
much. So much code has to be taylored to the individual classes that inheritance is helping in that way. More analysis will be needed.

Another aspect of using NUnit is that I’m finding myself needing the debugger less and less. It’s now possible to narrow down problems very quickly with such focused tests. This translates to quicker development.

So far, so good… I’m converted.

Modifying the System Menu in MFC

Introduction

The system menu is a standard feature of every Windows application. It is managed by Windows so normally we don’t have to worry about it at all. However sometimes it is nice to be able to modify that menu according to our own program with things that Windows can’t automatically do for us.

As my main example I will be using a tool I’ve created called BabelOn. This is a C++/MFC program that accesses a web-service to translate text into foreign languages. It uses a toolbox window, so we don’t see the system menu icon in the upper-left corner, however the menu can still be accessed with Ctrl-Space or by right-clicking on the title bar. The menu has been modified to contain two extra commands: About BabelOn, and Exit. Exit is needed because the default action for Close (Alt-F4) has been overridden in the program to hide the window and allow tray access.

Adding Commands

First we need to define a unique variable to represent each menu item. This can be done in the Resource.h file, or in any standard header file. If the commands already exist as part of another standard or context menu, then this step can be skipped because the definitions already exist. However, it’s important to note that even if we use the pre-existing definitions, the message handlers for the commands on the regular menu will NOT be automatically called. System commands are routed differently. So, in the end, it doesn’t matter if we use the existing or define our own.

For our example, we’ll define two:

[code]
#define IDM_ABOUT 16
#define IDM_EXIT 17
[/code]

The IDM just means this is a menu-item ID.

We add these commands in our window’s initializing function ( OnInitDialog(), OnCreate() ). My example is in a dialog class, so this is what the function looks like:

[code lang=”cpp”]
BOOL CBabelOnDlg::OnInitDialog()
{
CDialog::OnInitDialog();
// Add “About…” and “Exit” menu items to system menu.
// Command IDs must be in system range
// the ANDing is because of a bug in Windows 95
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000);
ASSERT((IDM_EXIT & 0xFFF0) == IDM_EXIT);
ASSERT(IDM_EXIT < 0xF000);
CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != NULL) {
pSysMenu->AppendMenu(MF_STRING,IDM_EXIT,”E&xit Program”);
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, “A&bout BabelOn”);

}
. . .
//other initialization
[/code]

The first thing you should notice is a couple of ASSERT statements for each command. The first one deals with a bug present in Windows 95 and the second ensures the custom command is below the range used by pre-defined system commands. From the MFC documentation: “All predefined Control-menu items have ID numbers greater than 0xF000. If an application adds items to the Control menu, it should use ID numbers less than F000.”

Next we get a pointer to the system menu with the GetSystemMenu. We call it with an argument of FALSE to get the pointer. If we call it with TRUE, then it will reset the menu to its default state.

If the pointer is valid, we call some commands to add to the bottom of the menu, passing the IDs and the string we want to show up when the menu is viewed.

Simple, isn’t it?

Processing Custom Commands

In order to have those commands do anything, we can’t rely on the normal message-handling mechanism, even if we have handlers for the same items in other menus. We have to handle the WM_SYSCOMMAND message in our dialog/window class.

[code lang=”cpp”]
void CBabelOnDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
//trap our own system menu messages
if ((nID & 0xFFF0) == IDM_ABOUTBOX)
{
CAboutDlg dlgAbout; dlgAbout.DoModal();
} else if ((nID & 0xFFF0)==SC_CLOSE)
{
OnClose();
} else if ((nID & 0xFFF0)==IDM_EXIT)
{
::PostQuitMessage(0);
} else {
CDialog::OnSysCommand(nID, lParam);
}
}
[/code]

This is the height of simplicity herself. We compare the code that was passed in with the system to our commands, again ANDing them to account for the Windows 95 bug. Then call whatever code we want to handle it.

If we selected Exit, then we post a message to quit the application.

Take a look at the second test: SC_CLOSE is a predefined menu constant. It’s one normally handled by Windows, but we can still add custom processing to it if we want. In this application, I didn’t want it to exit, but to merely hide the application (with an icon in the tray). So I just call a handler that I wrote that does that. If the ID doesn’t equal anything we want to custom-process, we just pass it on up the hierarchy for default processing.

The IDs for the most common system commands are:

SC_CLOSE – Close the CWnd object.
SC_MAXIMIZE (or SC_ZOOM) – Maximize the CWnd object.
SC_MINIMIZE (or SC_ICON) – Minimize the CWnd object.
SC_MOVE – Move the CWnd object.
SC_RESTORE – Restore window to normal position and size.
SC_SIZE – Size the CWnd object.

There are others in special situations that you can learn about in the documentation for WM_SYSCOMMAND.

Modifying Existing Commands

We just saw that it’s possible to change the default handling of built-in system commands, but it’s also possible to modify existing menu items by changing their text, or to entirely remove them.

To modify the text of a command, use the ModifyMenu() function on pSysMenu in the above example. For example, to change “Close” to “Hide”, I could do this:
[code lang=”cpp”]
pSysMenu->ModifyMenu(SC_CLOSE, MF_BYCOMMAND,IDM_HIDE, “&Hide”);
[/code]

The MF_BYCOMMAND argument tells the function to interpret SC_CLOSE as a command ID. IDM_HIDE is a new command ID, and then comes the text we want to show.

Alternatively, we can call ModifyMenu() on the ith menu item:

[code lang=”cpp”]
pSysMenu->ModifyMenu(0,MF_BYPOSITION,IDM_HIDE,”&Hide”);
[/code]

This changes the first menu item to Hide.

Removing commands

Don’t want a close command at all on the window? Not sure if this is a good idea or not, but you can do it.

Use this method:

[code lang=”cpp”]
pSysMenu->RemoveMenu(SC_CLOSE,MF_BYCOMMMAND); pSysMenu->RemoveMenu(0,MF_BYPOSITION);
[/code]

The first one removes the command associated with SC_CLOSE, while the second removes the first item on the menu.

Conclusion

Modifying the system menu in this way has limited application but it is sometimes useful for small applications and utilities that have a limited menu structure otherwise. It can be useful for commands you want to be easily accessible from the task bar–when a program is is in the background or minimized, right-clicking on it’s icon on the task bar will bring up the system menu.

Something should be said, however, about the wisdom of certain modifications. Removing or modifying functionality that user expects is usually a bad idea. It makes your program less usable and friendly compared to other applications. UI guidelines and standard look and feel exist for a good reason!

Enjoy playing with this!

©2004 Ben Watson

Operator Overloading in C++

Definition

This can be a weird subject for some, especially those with a strong Java background, or another language that doesn’t support this feature. It can be confusing even for excellent programmers. But it is a strong feature of C++ that, if mastered, can yield some increased productivity in programming.

We all know that an operator can be used in mathematical expressions:

[code lang=”cpp”]
int z=x+y;
float g=3.14*g;
[/code]

Now wouldn’t it be nice to use operators on our own objects to do what we want? For example, a string class could use + to concatenate, or a Throttle class could use the ++ and — operators to increase or decrease throttle position. The operators can be programmed to do whatever we want them to.

However, some words of caution. Operator overloading provides NO additional functionality to your code. It just compiles to normal function calls. It’s even written out like normal function calls. It is mainly for aesthetics. There is, however, one extremely useful set of operators to overload that makes life much easier: the streaming operators, which I will cover at the end.

Second, you should NOT use operator overloading for unobvious relationships. Using + to concatenate two strings intuitively makes sense to most programmers, so it’s easy to use it like that. But how would you define string1*string2? or string1^string2? It isn’t very clear what that means. So use caution when considering adding operators to your objects.

Sample Object

For my sample object, I’m going to implement a matrix. This won’t be a full-scale implementation of every imaginable matrix operation, but it should be enough to cover the basics of operator overloading, and maybe whet your appetite to complete the implementation for other operations (dot product, inverse, determinant, etc.).

In order to completely encapsulate a matrix within a class, we actually need two classes: Row and Matrix.

So let’s start with Row:
[code lang=”cpp”]
template
class Row {
public:
Row(int cols=0):row(NULL) {SetRowSize(cols);}
~Row() {SetRowSize(0); }
Row(const Row &r):row(NULL) {
SetRowSize(r.numCols);
for (int i=0;i row[i]=r.row[i];
}

void SetRowSize(int n) {
if(row) delete[] row;
if (n>0) {
row=new T[n];
memset(row,0,sizeof(T)*n/sizeof(char));
}
else row=NULL;
numCols=n;
}

int size() { return numCols;}
private:
int numCols;
T* row;
};[/code]

Let’s look at this before continuing on. Notice that I’m making it a template class. This is so you can have a matrix of all the usual numerical types, as well as any type you want to define yourself. The only requirement for the type is that it must have the +, -, and * operators defined on it. We’ll get into how to do that. If you don’t understand templates, you can think of all of the T’s as ints for now.

SetRowSize() deletes any old data, and allocates space for new data, unless we set the number of columns to 0, in which case it merely deletes the data. This lets us use this function for construction, destruction, and dynamic modification in one method. Nifty, eh? The call to memset() just zeroes out the array after figuring out how many bytes the row uses and dividing this by the size of character, because memset() works in terms of chars.

I also defined a copy constructor, which will come in handy quite a bit, as we’ll see later on when we copy matrices.

Overloading []

OK, let’s overload our first operator: []

Yes, that’s one operator. The array-access operator. It makes perfect sense here, because we have a linear array of objects we would like to access. Let’s add this definition to our Row class:
[code lang=”cpp”]
T& operator[](int column) {
assert(column return row[column];
}
[/code]

The arguments to our brackets are going to be integers specifying the index of the item we want, so that will be the function’s arguments. Notice the syntax: [ReturnType] operator[Op]([argument list]). We do an assertion to make sure we’re accessing memory within the array’s bounds. If all is OK, we return a reference to the object. Why a reference instead of a value? It won’t make much of a difference in a case like this:

[code]
Row r(1);//1×1 matrix

int a=r[0];
[/code]

a will get the value of r[0] whether a reference or a value is returned. However, if we return a reference, we can then change the value in the row from outside the class, using the [] accessor operator, like so:
[code lang=”cpp”]
Row r(1);

r[0]=3.142;
float pi=r[0];
[/code]

Very cool, isn’t it.

Overloading =

The only other operator we need to overload is assignment (=). When overloading assignment, we must keep in mind that the object we’re assigning to must already exist, and it is that object’s operator= method which will be called.
[code lang=”cpp”]
Row& operator=(const Row& r) {
SetRowSize(r.numCols);
for (int i=0;i row[i]=r.row[i];
return *this;
}
[/code]

Again we return a reference, but this time it’s a reference to itself. First we set the size of the current row equal to that of the source row, then we copy its values. There is an important note here. Notice that I’m using [] on the primitive T array itself–NOT the overloaded []s of Row. Remember that Row’s [] returns a reference, thus if we had written row[i]=r[i], we would get a row that references the exact same data in memory, so that when we changed one the other would change–this isn’t what we want at all, so we need to access the raw data in the Row class.

Now we can write code like this:
[code lang=”cpp”]
Row r1(5);
Row r2;//creates an empty row
Row r3(2);
r2=r1;
r3=r1;//overwrites previous row information to contain same info as r1
[/code]

Matrices are Made of Many Rows

Now that we have a working Row, we can combine rows into a matrix. Let’s start with this basic definition:
[code lang=”cpp”]
template
class Matrix {
public:
Matrix(int rows=0, int cols=0): matrix(NULL) {
SetSize(rows,cols);
}
Matrix(const Matrix& m): matrix(NULL) {
SetSize(m.numRows,m.numCols);
for (int r=0;r matrix[r]=Row(m.matrix[r]);//assign to primitive array, NOT overloaded []–to get a copy
}
void SetSize(int rows, int cols) {
if (rows) delete[]matrix;
if (cols > 0 && rows >0) {
matrix=new Row[rows];
for (int i=0;i matrix[i].SetRowSize(cols);
}
else
rows=NULL;
numCols=cols;numRows=rows;
}
int GetCols() { return numCols;}
int GetRows() { return numRows;}

private:
int numCols, numRows;
Row* matrix;

};
[/code]

This follows very closely the basic form of the Row class. The only item of interest is when we declare and allocate a matrix: we must specify the type, T, after the class name.

First let’s implement the same operators we did on the Row class:
[code lang=”cpp”]
Row& operator[](int index) {
assert(index return matrix[index];
}

Matrix& operator=(const Matrix& m) {
SetSize(m.numRows,m.numCols);
for (int r=0;r matrix[r]=Row(m.matrix[r]);//assign to primitive array, NOT overloaded []–to get a copy
return *this;
}
[/code]

The most important part of this code is the return type of operator[]. It returns a reference to a Row of type T. This little fact allows us to use the Matrix class like this:
[code lang=”cpp”]
Matrix a(2,2);

a[0][0]=2;
a[0][1]=4;
a[1][0]=8;
a[1][1]=16;
[/code]

That is, we can refer to Matrix objects now with exactly the same notation as primitive 2-D arrays in C++: array[row][column]. Our operator overloading is faking it well enough to keep a consistent interface with analogous structures, but add much more functionality and safety. Isn’t this cool?

The = operator works the same way as in Row. It sets the size of the current Matrix to that of the source, and then copies all of the objects to the current Matrix. Now we can do the following:
[code lang=”cpp”]
Matrix<__int64> m(1000,1000);
Matrix<__int64> n=m;
[/code]

…and we have two very large matrices of 64-bit integers.

Overloading +

Let’s do some more interesting things with these matrices now. There are a number of mathematical operations that can be performed on a matrix, the simplest perhaps is addition. Addition of matrices requires that they both have the same dimensions. The resulting matrix is made by simply adding each number in the same position in each matrix and putting the answer in the same position as the two operands.
[code lang=”cpp”]
[1 0] [4 3] [5 3]
[2 1] + [-1 0] = [1 1]
[/code]

Since addition creates a new matrix, we don’t want to return a reference, but an actual matrix object. Here’s what the code looks like:
[code lang=”cpp”]
const Matrix operator+( const Matrix& m) {
assert(numCols==m.numCols && numRows==m.numRows);
Matrix theMatrix(numRows,numCols);
for (int r=0;r for (int c=0;c theMatrix[r][c]=matrix[r][c]+m.matrix[r][c];
return theMatrix;
}
[/code]

This adds the current matrix to the matrix in argument m. We first assure that the dimensions are equivalent, then create a new matrix with the same dimensions as the sources. It is then a simple matter of adding the two sources, and returning the new matrix. Notice that we perform the actual math on the types that make up each row.
[code lang=”cpp”]
Matrix a(2,2);
Matrix b(2,2);
Matrix c(2,3);
Matrix d=a+b;
Matrix e=a+c;//will fail assertion, abort program
[/code]

It is just as easy to define subtraction:
[code lang=”cpp”]
const Matrix operator-( const Matrix& m) {
assert(numCols==m.numCols && numRows==m.numRows);
Matrix theMatrix(numRows,numCols);
for (int r=0;r for (int c=0;c theMatrix[r][c]=matrix[r][c]-m.matrix[r][c];
return theMatrix;
}
[/code]

Overloading += and -=

+= and -= are operators that both add and change the current object, so the code to describe it is a combination of +/- and =. We’ll return a reference again because we don’t want to create a new object, but just modify the existing one, which called the function. We’ll just add whatever is currently in it to the other matrix, and return a reference to itself:
[code lang=”cpp”]
Matrix& operator+=(const Matrix& m) {
assert(numCols==m.numCols && numRows==m.numRows);
for (int r=0;r for (int c=0;c matrix[r][c]+=m.matrix[r][c];
return *this;
}

Matrix& operator-=( const Matrix& m) {
assert(numCols==m.numCols && numRows==m.numRows);
for (int r=0;r for (int c=0;c matrix[r][c]-=m.matrix[r][c];
return *this;
}
[/code]

We can now expand our repertoire to include the following possibilities:
[code lang=”cpp”]
Matrix a(2,1);
Matrix b(2,1);

a+=b;
a-=b;
[/code]

Scaling: Overloading *

Another useful operation we can perform on matrices is scaling. This just multiples every element in the matrix by a constant.
[code lang=”cpp”]
[1 2] [2 4]
[2 4] * 2 = [4 8]
[/code]

This operation returns a new matrix so we will return by value, not reference. The code should be trivial to read by now:
[code lang=”cpp”]
const Matrix operator*(const float s) {
Matrix theMatrix(numRows,numCols);
for (int r=0;r for (int c=0;c theMatrix[r][c]=matrix[r][c]*s;
return theMatrix;
}
[/code]

We use a float as the scalar, and multiply it by every value in the source matrix, and return a new matrix. It is left up to the reader to implement *=. (/ and /= could also be implemented as inverses of scaling, but since scaling allows a float, this is mostly redundant.)

Matrix Multiplication – Overloading * again

We can actually overload the same operator more than once if we would like. As long as the function’s signature (return type, name, and arguments) is different, we can define as many as we want. The * operator would be a likely candidate for implementing matrix multiplication as well as scaling. Both imply multiplication of some sort, so it should make sense.

Matrix multiplication has a requirement: the number of columns in the first matrix must be equal to the number of rows in the second. Matrix multiplication is NOT commutative. I won’t explain how to do matrix multiplcation–it’s easy enough to look up this topic on-line or in a math textbook. Or you can deduce the “by-hand” algorithm from the code.
[code lang=”cpp”]
const Matrix operator*(Matrix& m) {
assert(numCols==m.numRows);
Matrix theMatrix(numRows,m.numCols);
for (int r=0;r for (int c=0;c for (int i=0;i theMatrix[r][c]+=matrix[r][i]*m[i][c];
}
}
}
return theMatrix;
}
[/code]

Overloading < < and >>

There are only two more important operators that I will cover here. These are perhaps the operators that should be implemented for each and every class you create. The streaming operators < < and >> allow your object to be saved and restored from any stream, be it console, network, or file.

There is a slight additional challenge with these operators because we must allow the stream access to our object’s private data. Therefore, these functions must be declared as friends inside the Matrix class.

Let’s first look at outputting to a stream:
[code lang=”cpp”]
friend ostream& operator< <(ostream& os,const Matrix& m) {
os << m.numRows<<” “< Matrix a(2,2);

cout < <“Matrix a:”<

ofstream ofile(“output.dat”);
ofile << a << endl<<“End of File”;
[/code]

It is a quite similar technique to read in values from a stream:
[code lang=”cpp”]
friend istream& operator>>(istream& is, Matrix& m) {
int rows,cols;
is >> rows >> cols;
m.SetSize(rows,cols);
for (int r=0;r for (int c=0;c is >> m[r][c];
return is;
}
[/code]

Here we declare some local variables to hold our matrix dimensions, which we then pass to the referenced matrix object. Then it’s just a matter of reading in the next number and putting it in the appropriate location. We then return a reference to the stream in case the calling function wanted to continue getting data from it in the same command.

Putting it all together

To demonstrate the Matrix class and its overloaded operators, I’ve written a sample main() as well as some helper functions that will run the class through its paces:

[code lang=”cpp”]
//the functions fill in a matrix with random values–they are type-specific
void init_matrix(Matrix& m) {
for (int r=0;r for (int c=0;c m[r][c]=rand()%5+1;
}

void init_matrix(Matrix<__int64>& m) {
for (int r=0;r for (int c=0;c m[r][c]=rand()%100000+1;
}

void init_matrix(Matrix& m, int precision) {
for (int r=0;r for (int c=0;c float dec=float(rand()%precision)/precision;
m[r][c]=float(rand()%5)+1.0+dec;
}
}

int _tmain(int argc, _TCHAR* argv[])
{
srand((unsigned)time(NULL));

//save/load from file7
Matrix a(5,5);
init_matrix(a);
a[0][0]=-13;
a[1][1]=-13;
cout < < “Writing to file from Matrix a:” < cout << a< ofstream of;
of.open(“test.txt”);
of << a< of.close();
ifstream iff(“test.txt”);
if (!iff) {
cout << “Error opening file”< return 1;
}
Matrix b;
cout < < “Reading from file into Matrix b:”< iff >> b;
iff.close();
cout < cout << b<

cout <<“Press any key to continue…”< getchar();

//add two floating-point matrices
Matrix c(3,2);
init_matrix(c,100);
cout < <“Matrix c:”< Matrix d(3,2);
init_matrix(d,100);
cout < < “Matrix d:”< cout << “c+d:”<

cout <<“Press any key to continue…”< getchar();

//scale a floating-point matrix
Matrix e(10,10);
init_matrix(e,1);
float scalar=-1.5;
cout < < “Matrix e:” << endl< cout << “Scalar: “< cout << “e * scalar:”<

cout <<“Press any key to continue…”< getchar();

//matrix-product
Matrix<__int64> f(3,5);
Matrix<__int64> g(5,6);
init_matrix(f);
init_matrix(g);
cout < <“Matrix f:”< cout <<“Matrix g:”< cout <<“f*g:”<

cout <<“Press any key to continue…”< getchar();

return 0;
}
[/code]

Conclusion

Operator overloading can be a powerful programming tool when it increases usability and understandability of a class. In this case, it’s much nicer to write matrix[0][4] rather than matrix->GetRow(0)->GetCol(4). However, it must always be remembered that overloading serves to make programming easier–it doesn’t benefit the end user at all. Overloading an operator must make sense, as I hope all of the decisions I made in this class make sense. If it’s appropriate, go ahead and use it. If it will make people wonder what you meant, than it’s probably something to stay away from.

Also, because this is a template, you could possibly have a matrix of any object, including, for example strings. This will work perfectly in some situations, but not in others. Basically, if + is defined on strings, then you can do matrix addition on a string matrix. However, * is usually not defined for strings, so a statement with that would refuse to compile.
[code lang=”cpp”]
Matrix s(2,7);
Matrix t(2,7);

/*
will work fine–concatenates strings
at same locations in matrix
*/
Matrix u=s+t;

Matrix v(7,5);
/*
will not compile: error C2676: binary ‘*’ :
‘std::string’ does not define this operator or a conversion to a type
acceptable to the predefined operator
*/
Matrix w=s*v;
[/code]

I did not make use of the — and ++ unary operators in this tutorial because they don’t always make sense when used on a matrix. With these operators it is important to know that since they can be both prefix and postfix, each version has a slightly different function signature. With the understanding you have gained in this tutorial, you should be able to look up how to implement these operators without trouble.

Hope this helps somebody understand this subject better! Happy coding!

Threads in MFC Part III: Exceptions, Suspense, Murder, and Safety

Exceptions

In the previous tutorial, I described the various synchronization objects you can use to control access to shared objects. In most cases, these will work fine, but consider the following situation:

[code lang=”cpp”]
UINT ThreadFunc(LPVOID lParam)
{
::criticalSection.Lock();
::globalData.DoSomething();
SomeFunctionThatThrowsException();
::criticalSection.Unlock();
return 0;
}[/code]

What’s going to happen when that exception gets thrown? The critical section will never be unlocked. If you start the thread again, it will again try to lock it, and finding it already locked, it will sit there forever waiting. Of course, a mutex will unlock when the thread exits, but a critical section won’t. So MFC has a couple of wrapper classes that can incorporate any of the other basic synchronization classes. These are called CSingleLock and CMultiLock.

Here is how they are used:
[code lang=”cpp”]
UINT ThreadFunc(LPVOID lParam)
{
CSingleLock lock(&(::criticalSection));
lock.Lock();
::globalData.DoSomething();
FunctionThatThrowsException();
lock.Unlock();
return 0;
}
[/code]

You merely pass the address of the “real” synchronization object. CSingleLock lock is created on ThreadFunc’s stack, so when an exception is thrown, and that function exits prematurely without a chance to nicely clean up, CSingleLock’s destructor is called, which unlocks the data. This would not happen to criticalSection because, being a global variable, it will not go out of scope and be destroyed when ThreadFunc exits.

CMultiLock

This class allows you to block, or wait, on up to 64 synchornization objects at once. You create an array of references to the objects, and pass this to the constructor. In addition, you can specify whether you want it to unblock when one object unlocks, or when all of them do.

[code lang=”cpp”]
//let’s pretend these are all global objects, or defined other than in the local function
\tCCriticalSection cs;
CMutex mu;
CEvent ev;
CSemaphore sem[3];

CSynObject* objects[6]={&cs, &mu, &ev,
&sem[0], &sem[1], &sem[2]};
CMultiLock mlock(objects,6);
int result=mlock.Lock(INFINITE, FALSE);

[/code]

Notice you can mix synchronization object types. The two parameters I specified (both optional) specify the time-out period and whether to wait for all the objects to unlock before continuing. I saved the return value of Lock() because that is the index into the array of objects of the one that unblocked, in case I want to do special processing.

Killing a Thread

Generally, murder is very messy. You have blood and guts everywhere that certainly don’t clean up after themselves. But sometimes, sadly, it is necessary (no one call the cops–my metaphor is about to end).

If you start a child thread, and for some reason it is just not exiting when you need it to, and you’ve fixed your code, double-checked all your signaling mechanisms, and then and only then you want to kill it, here’s how. When you create the thread, you need to get its handle and save it for later use in your
class.

[code lang=”cpp”]
HANDLE hThread;//handle to thread
[/code]

A handle is only valid while the thread is running. What if we create a thread, start it off running, and it exits immediately for some reason? Back in our main thread, even if the very next statement after creating the thread is to grab its handle, it could very possibly be too late.

So we create a thread suspended! We just don’t even let it get to first base before we allow ourselves to get to the handle. This is a piece of cake, simply change the last parameter we’ve been giving fxBeginThread() from 0 toCREATE_SUSPENDED:

[code lang=”cpp”]
CWinThread* pThread=AfxBeginThread(ThreadFunc,NULL, THREAD_PRIORITY_NORMAL, 0, CREATE_SUSPENDED);
::DuplicateHandle(GetCurrentProcess(), pThread->m_hThread, GetCurrentProcess(), &hThread, 0, FALSE, DUPLICATE_SAME_ACCESS);
pThread->;
ResumeThread();
[/code]

We start the thread suspended, use an API call to duplicate the thread’s handle, saving it to our class variable, and then resuming the thread.

Then, if we want to commit this heinous crime:

[code lang=”cpp”]::TerminateThread(hThread,0);
[/code]

Don’t say I didn’t warn you.

Thread-Safe Classes

Thread-safety refers to the possibility of calling member functions across thread-boundaries. Their are two types of safety: Class-level and Object-level. Class level means that I can create two CStringT objects called a and b, and access each of them in separate threads, but I cannot safely access just a in
two threads. Object safety means that it’s perfectly ok to access a in two or more threads simultaneously. Thread-safety at the object level generally means using synchronization objects to control access to all internal datamembers. So why not make all classes thread-safe at the object level? Because that would just about kill your performance. You can lock objects yourself outside of the actual object (as shown in Part II) to make it safe.

This is not to say that your program will always crash if you try to access a single object from two threads, but it most likely will. Also, you should not generally lock access to MFC member functions or public variables–you don’t know when the MFC framework is going to need access to them. There really isn’t need to lock on a CWnd* object anyway.

Etc

There are many, many details I have neglected to cover in these three tutorials. You can look in the SDK or .NET documentation for more information on such things as pausing/resuming, scheduling, masks in CMultiLock(), or any of the other member functions of the thread classes. If you want to learn about the internal details of Windows, threads and fibers, (plus a lot of other important subjects) check out Programming Applications for Microsoft Windows by Jeffrey Richter.

I have yet to cover so-called user-interface threads (internally, there is no difference–all threads are created equal). Perhaps in a future tutorial…

Threads are a very powerful tool, but they can quickly increase the complexity of your application by an order of magnitude. Use wisely. As always, it takes some experimentation to get the hang of how to go about it. So have fun!

©2004 Ben Watson

Threads in MFC II: Synchronization Objects

Introduction

In part I, I looked at getting threads communicating with each other. Now let’s look at how we can manage how multiple threads operate on single objects.

Let’s take an example. Suppose we have a global variable (or any variable that is accessible to two or more threads via scope, pointers, references, whatever). Let’s say this variable object is a CStringArray called stringArray
.

Now, let’s suppose our main thread wants to add something to the array. Fine enough. We can do that. Then, let’s throw in a second thread which can somehow access this object. It, too, wants to access stringArray . What would happen if both threads tried to simultaneously write to the first position in the array for example? Or even if one were just reading and the other writing? Well, if there is no synchronization between the two threads, you don’t know what would happen. The result is completely unpredicatable. One thread would write some bytes to memory, while another reads it, and you could have the correct answer or the wrong answer or a mix. Or it could crash. Who knows…

You can’t even assume safety when merely reading an object from two threads. Even if it seems like no bytes are changing, and both threads should get valid results, you have to think about a lower level: A single C++ statement compiles to many assembly or machine language instructions. These instructions directly access the processor, including the registers that keep track of where we are, what data we’re looking at. It’s possible to have one of those registers hold a pointer to the current character in the string, so if you have two threads that rely on that pointer in that register–they are obviously not both going to be correct except in a very rare circumstance.

OK, I think I’ve made the case. How do we control access to objects then?

Windows has a number of synchronization objects that you can use to effectively prevent accidents. MFC encapsulates these into CEvent , CCriticalSection, CMutex , and CSemaphore . To use these, include afxmt.hin your project.

CEvent

Let’s start with these so-called triggers. An event in this context is nothing more than a flag, a trigger. Imagine it as cocking a gun (Reset) and then firing it (Set). You can use events for setting of threads. Here’s how.
Remember how we created a structure that contained all the data we wanted to send the thread? Let’s add a new one. First create a CEvent object in the dialog (or any window or non-window) class called m_event . Now, in our [code lang=”cpp”]THREADINFOSTRUCT [/code], let’s add a pointer to an event:

[code lang=”cpp”]
typedef struct THREADINFOSTRUCT {

CEvent* pEvent;

} THREADINFOSTRUCT;
[/code]

When we initialize the structure, we must do the assignment:

[code lang=”cpp”]tis->pEvent=&m_event; [/code]

In our thread function, we call:

[code lang=”cpp”]tis->pEvent->Lock(); [/code]

This will “lock” on the event (the same event that is in our dialog class in the main thread). The thread will effectively stop. It will loop inside of CEvent::Lock() until that event is “Set.” Where do you set it? In the main thread. An event is initially reset–cocked. Create the thread. When you want the thread to unblock itself and continue, you call m_event.Set()–fire the gun.

So what are some practical examples? You could lock a thread before you access a global object. In your main thread, when you’re done using that object, you call Set(). You can also use an event to signal a thread to exit (such as if
you hit an abort button in the main thread). To see an example of this usage, look at the demo project I’ve uploaded to the code tool section.

There are two types of events: ones that automatically reset when you set them, and ones that don’t.

You can use a single event to trigger multiple threads, but the event had better be a manual-reset event or only one thread will be triggered at a time.

CCriticalSection

These are pretty simple to use. You simply surround every usage of the shared object by a lock and an unlock command:

[code lang=”cpp”]CCriticalSection cs;

cs.Lock();
stringArray.DoSomething();
cs.Unlock();
[/code]
Do that in every thread that uses that object. You must use the same critical section variable to lock the same object. If a thread tries to lock an object that’s already locked, it will just sit there waiting for it to unlock so it can safely access the object.
CMutex

A mutex works just like a critical section, but it can also work across different processes. But you don’t want to always use mutexes, because they are slower than critical sections.
You can declare a mutex like this:

[code lang=”cpp”]CMutex m_mutex(FALSE, “MyMutex”); [/code]
The first parameter specifies whether or not the mutex is initially locked or not. The second parameter is the identifier of the mutex so it can be accessed from two different processes.

If you lock a critical section in a thread and then the thread exits without unlocking it, then any other thread waiting on it will be forever blocked. Mutexes, however, will unlock automatically if the thread exits. Mutexes can
also have a time-out value (critical sections can too, but there are some doubts as to whether or not they work–perhaps the bugs are fixed in MFC 7.0).

Otherwise, it works the same:

[code lang=”cpp”]
m_muytex.Lock(60000);//time out in milliseconds
stringArray.DoSomething();
m_mutex.Unlock();
[/code]

CSemaphore

A semaphore is used to limit simultaneous access of a resource to a certain number of threads. Most commonly, this resource is a pool of a certain number of limited resources. If we had ten string arrays, we could set up a semaphore to guard them and let only ten threads at a time access them. Or COM ports, internet connections, or anything else.

It’s declared like this:

[code lang=”cpp”]CSemaphore m_semaphore(10,10); [/code]

The first argument is the initial reference count, while the second is the maximum reference count. Each time we lock the semaphore, it will decrement the reference count by 1, until it reaches zero. If another thread tries to lock the semaphore, then it will just go into a holding pattern until a thread unlocks it.

As with a mutex, you can pass it a time-out value.

It’s used with the same syntax:

[code lang=”cpp”]
m_semaphore.Lock(60000);
stringArray.DoSomething();
m_semaphore.Unlock();
[/code]

Conclusion

These two tutorials, along with the sample projects, should be enough to get you started using threads. There are a couple of other MFC objects and issues that I have yet to cover, so I’ll group all of these into Part III of this
tutorial. These topics include exception-handling and thread-safe classes. Make sure that you examine the documentation of all of these classes: there is more functionality than I could cover in this short tutorial. And if you really want to learn threads, get a good book that covers the Windows kernel (one called Programming Applications for MS Windows comes to mind, published by Microsoft).

The sample project for this tutorial has a time object that it shares between two threads. It’s protected by a critical section. There are also two events: for starting the thread and aborting it. The main thread uses a timer to add the current time to a list box every second, while the thread traces the current time to the debug window and sends a message to the main thread to remove the first time from the list. The thread is only started after the time
hits an even ten-second boundary.

©2004 Ben Watson

Threads in MFC I: Worker Threads

There are two types of threads in MFC. Worker and User Interface. Here, I will discuss how to use a worker thread.First, let’s discuss some multi-threading basics. Each application has what we call a process. Usually, an application has only one process. This process defines all the code and memory space for the application. You can use the Window Task Mananger to view running processes.

You could possibly view a thread as a process within a process. It is an independently (mostly) running sub-process, that the CPU can task and switch to like any other process on the machine.

Under 16-bit Windows, you could have mulitple processes (i.e., many programs running: multi-tasking). However, each application was limited to its one main process. It was multi-tasked, not multi-threaded. With 32-bit Windows, applications could spawn their own threads or sub-processes.
 

Threads have priority levels. The explanation of exactly how Windows manages these in determining how much processor time each receives is a topic you can find in the MSDN literature. Basically, higher priorities receive more time.

When your Win32 program creates a thread, you specify its priority level. By default, it has the same priority as the calling thread.

There are two main issues you must deal with when using threads: 1) Inter-thread communication, and 2) inter-thread object access.

I’ll leave object access for part II of this tutorial.

Communication

The easiest way to communicate among threads in your application is with messages. Since this tutorial deals with worker threads, we’ll restrict this to having the worker thread post messages to the main application thread.
ThreadFunc()

So, now let’s walk through creating a simple worker thread that does nothing but update the progress control in a dialog box.

I’m going to assume you know how to create a dialog box, with a progress control, bound to a member variable in the dialog class. Do that now. You could also create a button that starts the thread.

OK, the first thing you need to do is create the thread’s controlling function. This can either be global or a class member, but I prefer to make it global because this separates the thread from the main process in my mind.

[code lang=”cpp”]UINT MyThreadFunc(LPVOID lParam); [/code]

All MFC thread “controllers” must be declared like that.

To call this function in a thread, we use the following code:

[code lang=”cpp”]
CWinThread *pThread = AfxBeginThread(MyThreadFunc, NULL, THREAD_PRIORITY_NORMAL, 0, 0); [/code]

This creates a separate thread using the MyThreadFunc function, passes a NULL for its one parameter, sets the priority to normal, gives it the same stack size as the calling thread, and starts the thread immediately. If the last parameter here is CREATE_SUSPENDED instead of 0, then the thread is created, but it does not start running until you explicitly tell it to.

This will successfully create a thread, which will run until MyThreadFunc returns. However, the calling thread will not know when that thread is done. Somehow, we have to pass the thread some information about the calling program.
Passing Information To a Thread
A thread controller can only have one parameter–the LPVOID argument. Therefore, it is often convenient to wrap up all the information we want to send the thread into a single struct:
[code lang=”cpp”]
typedef struct THREADINFOSTRUCT {
HWND hWnd;
CString someData;
} THREADINFOSTRUCT; [/code]
We can put any data we want in that structure, but one that should always be in there is a handle to the thread’s parent window. This will allow us to communicate with it.

Now, before we start the thread, let’s allocate some space for this structure. If we merely declare it on the stack with

[code lang=”cpp”]THREADINFOSTRUCT tis; [/code]

then as soon as this data goes out of scope, it will be destroyed. So let’s put it on the heap:

[code lang=”cpp”]THREADINFOSTRUCT *tis=new THREADINFOSTRUCT;
tis->hWnd=m_hWnd;
tis->someData=”This is in a thread.”; [/code]

And now we call the same function as before, passing tis:

[code lang=”cpp”]CWinThread *pThread = AfxBeginThread(MyThreadFunc,tis,
THREAD_PRIORITY_NORMAL,0,0); [/code]

OK, now we can pass some information to the thread. How do we let the thread tell the main process what’s going on?

Communicating with Threads
We can communicate to the calling window via a windows messages. First we have to define our own custom messages in our dialog class’s header file:

[code lang=”cpp”]#define WM_USER_THREAD_FINISHED (WM_USER+0x101)
#define WM_USER_THREAD_UPDATE_PROGRESS (WM_USER+0x102) [/code]
We also have to provide handlers for these messages in our dialog class:

[code lang=”cpp”]
afx_msg LRESULT OnThreadFinished(WPARAM wParam, LPARAM lParam);
afx_msg LRESULT OnThreadUpdateProgress(WPARAM wParam, LPARAM lParam); [/code]

All custom message handlers must follow that generic template. But we can interpret the parameters any way we want.

We must also manually update the message map with these two lines:

[code lang=”cpp”]
ON_MESSAGE(WM_USER_THREAD_FINISHED, OnThreadFinished)
ON_MESSAGE(WM_USER_THREAD_UPDATE_PROGRESS, OnThreadUpdateProgress) [/code]

And now we add the function definitions somewhere in our source file:

[code lang=”cpp”]
LRESULT CMyDialog::OnThreadFinished(WPARAM wParam, LPARAM lParam)
{
AfxMessageBox(“Thread has exited”);
return 0;
}
LRESULT CMyDialog::OnThreadUpdateProgress(WPARAM wParam, LPARAM lParam)
{
m_progress.SetPos(100*(int)wParam/(int)lParam);
return 0;
}
[/code]
So what should our thread do? In this example, not much:

[code lang=”cpp”]
UINT MyThreadFunc(LPVOID lParam)
{
THREADINFOSTRUCT* tis=(THREADINFOSTRUCT*)lParam;
for (int i=0;i<100;i++) {
PostMessage(tis->hWnd,WM_USER_THREAD_UPDATE_PROGRESS,i,100);
Sleep(100);
}
PostMessage(tis->hWnd,WM_USER_THREAD_FINISHED,0,0);
delete tis;
return 0;
} [/code]

Let’s analyze this. First we typecast the function’s argument into the structure type we passed. Then we just run through a simple loop that sends a message to the main thread to update the progress bar. We sleep for 100 ms just so it doesn’t go too fast that we don’t see it.

Next we send a message saying that our thread is finished.

Finally we delete the pointer to tis; Wait a second! Didn’t we define that in the main thread??? Yes, and it’s perfectly fine to allocate memory in one thread and free it in another. As long as we the programmer keep track of where things are happening. Alternatively, we could have set a class variable to hold that structure, and delete it in the [code lang=”cpp”]OnThreadFinished[/code] functioned. Either way is acceptable.

The function then returns, and the thread ends.

That’s all! It’s so easy! To see a working example project, look in the code tools section.

Of course, we can easily make it more complicated. Part II will talk about some synchronization methods used to control simultaneous access to objects from multiple threads. Now things can start becoming fun…
©2004 Ben Watson