Introduction

There are lots of hyperlink controls on CodeProject. So why is there any need for this one? Indeed, when I implemented this class couple of years ago, I never thought of publishing it, because it had really nothing special worth for an article. But three weeks ago, I included this class in my ODBCTracer-project (ODBCTracer) and someone on CodeProject was interested in it. Especially, the fact that it was not a CWnd derivate was the main point of interest.

Why not using the MFC versions?

At this point, I want to avoid any heated discussion about the advantages and disadvantages of MFC in different kinds of projects. Generally, I don't know of any disadvantage about MFC in client-side software systems if you know about the pitfalls. But sometimes, any dependency between your application and a specific MFC version is somewhat annoying. Just think about how things can get messy if you mix different versions of the MFC in different modules used by the same application. In such a case, it is better to rely on Win32 and steer clear of the MFC. This was exactly the case, when I worked on my ODBCTracer project.

Backgrounds

Although the implementation is very straightforward, there is an aspect about it which is worth mentioning. I am using a modified worker object pattern for initialization of the class when the first instance of it is created. Initialization means that the window class of the Win32 control is registered by calling the Win32 API function RegisterClass and the hand cursor is loaded from a specific module. These two jobs have to be done only once, and normally, to assure this, we are using something like a flag which indicates (when it was set) that the initialization is finished. Let's see how this technique could be implemented:

The disgusting thing about this technique is that within the constructor there is a check for initialization all the time, and besides the first invocation of the constructor, this check will return false. By using the modified worker object pattern, you are able to invoke initialization operations before the first instance is created and you can avoid such a check.

Worker object pattern

The worker object pattern is used in situations where you want to execute some piece of code and assure that this is done in any circumstance. Imagine, you have a code fragment where you have to take care about thread safety so you want to assure that only one thread is within this piece of code. You can use a CRITICAL_SECTION and the Win32 API functions InitializeCriticalSection() and DeleteCriticalSection() to ascertain the exclusive access of a single thread. But if you use these functions directly within your code, there are many ways which can lead you to a perfect system deadlock. Let's see how this can happen:

The most important point is that you always delete the lock when you leave the critical section. This is done by calling DeleteCriticalSection(&lock). But what happens when the code within the critical section throws an exception? It's likely that DeleteCriticalSection(&lock) won't be called and the next thread which wants to acquire the lock in InitializeCriticalSection(&lock) will have to wait a very long period of time...

By using a worker object pattern, you can avoid such things. A worker object is an instance of a class which does execute code in its constructor and / or destructor. So, what we need to do is to invoke the functions for acquiring and releasing the lock within the constructor and destructor of a specific class which may be called a mutex.

void func1()
{
//code block here...//critical section enter
{
Mutex lock; //when the instance is created the lock is acquired.//fragile code which may only accessed by a single thread
} //at this point the object disappears from the stack and the lock is released//code block here...
}

The modified worker object pattern

Let me first emphasise that I don't think that the idea introduced here is something new. The only fact is that I have never read about it on CodeProject nor in any other community. This doesn't mean that there are no articles on this topic anywhere. It's just I've never come into contact with them...

The modified worker object pattern is based on the worker object pattern. It describes a way of executing some piece of code while the application or the module is loaded. Let's have a look at the class declaration of CHyperlink.

The worker object in this class is the static member called __autoinitializer of the class _autoinitializer. When the application or module is loaded, the common runtime creates all global or static instances. We can verify that by putting a breakpoint in the constructor of _autoinitializer to trace back the invocation.

Once the instance of _autoinitializer is created it initializes the class by registering the window class and loading the hand cursor. When the application is unloaded, the runtime calls the destructor which frees all the resources. The technique of using the runtime to invoke initialization routines even work with DLLs. If you use this class in any kind of DLL, the initialization operation will be invoked when you call LoadLibrary() for the first time from your application. Once you unload the library, the runtime automatically calls the destructor which in turn handles the deinitialization process. In DLLs, you can also export the DllMain function to do initialization jobs once the module is attached to the process space. But in this case, initialization and class implementation are scattered through your module which leads to bad design which in turn complicates maintenance.

Pitfalls

You cannot influence the sequence in which modified worker objects will be created! When we put another static member to the declaration of CHyperlink like the following update, we cannot say which instance will be created first: __autoinitializer1 or __autoinitializer2.

//static member. because _autoinitializer is a private class no one //else then CHyperlink is able to create instances of it: this is an unique instancestatic _autoinitializer __autoinitializer1;
static _autoinitializer __autoinitializer2;

It is not specified by the ANSI C++ standard how compiler vendors have to generate code for creation of this kind of objects. Be aware of this and refer to Scott Meyers :)

By the way, hope you can use the hyperlink class.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

Comments and Discussions

You use the critical section the wrong way, you only want to call InitializeCriticalSection and DeleteCriticalSection exactly once for a single critical section for it to work. EnterCriticalSection and LeaveCriticalSection should then be used to gain access to it.

I've never seen nor heard of this pattern before, neither have I been able to locate it in any of the well publicized books on Patterns. (Checked Google and all that came back were 3 non-productive references. Imagine! Google only found 3.)

Whereabout in Scott Meyers work does he talk about it? I have not been able to locate it anywhere in any of his books.

WREY wrote:I've never seen nor heard of this pattern before, neither have I been able to locate it in any of the well publicized books on Patterns. (Checked Google and all that came back were 3 non-productive references. Imagine! Google only found 3.)

Worker objects are instances of a specific class (for example a mutex) that encapsulate a method. There is a bettern known AOP pattern called worker object creation pattern, which deals with the aspect oriented creation of the worker objects (just google: "worker object" pattern).

WREY wrote:Whereabout in Scott Meyers work does he talk about it? I have not been able to locate it anywhere in any of his books.

Somewhere, in his "Effective C++" or "More Effective C++" book, he consideres about problems with applications which rely on a specific sequence of global object creation... I will post a message when I find out where exactly it was.

...and the problem with this approach is that the order of initialisation is (mostly) beyond your control. So, if you have one class that needs another class to be initialised first using your technique something may or may not fail depending on how the compiler feels about the order of construction for your static objects.

I say "mostly" because there is a #pragma you can use to basically say "this source file is a library and needs to be initialised first". But if you have 2 such static objects with one relying on the other then you are screwed (again)

Whilst having to call CYourStuff::Initialise may be ugly it's reliable. Your approach seems to be the lazy approach with little or no regard for the large C++ projects - and honestly the first time you have to track down an annoying initialisation sequence error will be the last time you use this approach for anything non-trivial.

anonymous wrote:...and the problem with this approach is that the order of initialisation is (mostly) beyond your control. So, if you have one class that needs another class to be initialised first using your technique something may or may not fail depending on how the compiler feels about the order of construction for your static objects.

...as I pointed out there is a pitfall you have to take care about. The situation you describe is exactly what you have to prevent. By the way, you can do this by adding an initializer class which invokes other sublevel initializers when it is created according to the extended worker object pattern.

anonymous wrote:Whilst having to call CYourStuff::Initialise may be ugly it's reliable. Your approach seems to be the lazy approach with little or no regard for the large C++ projects - and honestly the first time you have to track down an annoying initialisation sequence error will be the last time you use this approach for anything non-trivial.

I don't think, this has something to do with the size of the project nor if it is trivial or not. In either case you'll just have to watch out for the pitfall.