Click here to Skip to main content
15,881,248 members
Articles / Programming Languages / C++

The Resource in RAII

Rate me:
Please Sign up or sign in to vote.
0.00/5 (No votes)
3 Jul 2010CPOL2 min read 7.3K   2  
So far we have concentrated on the 'AII!' part of RAII, so now let's look at the important bit, the R, the Resource.

So far we have concentrated on the 'AII!' part of RAII, so now let's look at the important bit, the R, the Resource.

Here's the class interface to our managed MIDI handle so far:

C++
class CMidiOutHandle
{
public:
    CMidiOutHandle();
    ~CMidiOutHandle();

private:
    CMidiOutHandle(const CMidiOutHandle &);
    CMidiOutHandle& operator=(const CMidiOutHandle&);

private:
    HMIDIOUT m_hMidiOutHandle;
};  

The constructor creates the handle, the destructor tears it down, and we prevent any copying of the class because we've decided our handle should be non-copyable. So far so good. Unfortunately, while a stunning piece of software architecture, the class as it stands is completely useless. We have encapsulated the resource a little too well.

Here's a sneak preview of the raw MIDI API function we will be calling into:

C++
MMRESULT midiOutShortMsg(      
    HMIDIOUT hmo,    // Takes a HMIDIOUT, not a CMidiOutHandle!
    DWORD dwMsg  );  

Quite selfishly, when Microsoft wrote their API, they did not consider our class. So how best to get the managed handle to the API?

When we first learn about object-oriented techniques, we are told it is all about encapsulation. And it is! We should hide our internals. But RAII is different - RAII is a special kind of object oriented technique. It encapsulates the resource management, but does not hide away the resource itself. So we're going to add a simple get function:

C++
const HMIDIOUT GetHandle() const {return m_hMidiOutHandle;} 

Let's go const-mad. It is member function const because we're not modifying the class, and returns a const despite being a simple value type to emphasize the fact it is to be used only as an rvalue. This prevents such errors as:

C++
if(GetHandle() = null)	// Oops! I meant to say ==

We can now use the class as follows:

C++
CMidiOutHandle midiOutHandle;
midiOutShortMsg(midiOutHandle.GetHandle(), ...

Let's go one step further for ultra-convenience and define an operator:

C++
operator HMIDIOUT() const { return GetHandle(); } 

And now we can call the API as if CMidiHandle is a HMIDIOUT handle, which is nice:

C++
CMidiOutHandle midiOutHandle;
midiOutShortMsg(midiOutHandle, ... 

Here is our interface so far. To top it off, I have inlined the two functions mentioned above:

C++
class CMidiOutHandle
{
public:
    CMidiOutHandle();
    ~CMidiOutHandle();

private:
    // Non copyable handle
    CMidiOutHandle(const CMidiOutHandle &);
    CMidiOutHandle& operator=(const CMidiOutHandle &);

public:
    inline const HMIDIOUT GetHandle() const;
    inline operator HMIDIOUT() const;

private:
    HMIDIOUT m_hMidiOutHandle;
}; 

The danger with returning a HMIDIOUT like this is that someone can use this value to close the handle outside of the RAII class. This is a situation we need to handle carefully, so the next article is going to look at error handling. We are then going to move on to the very new and exciting topic of move construction and assignment!

And then, finally we might get on with writing an actual MIDI wrapper.

This article was originally posted at http://www.webbiscuit.co.uk/feed

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer Web Biscuit
United Kingdom United Kingdom
At Web Biscuit, you can find software, articles, a good dollop of quality and an unhealthy obsession over biscuits.
Website: http://www.webbiscuit.co.uk
Twitter Watch: http://twitter.com/WebBiscuitCoUk

Comments and Discussions

 
-- There are no messages in this forum --