WinRT: reference count strikes back

At a first look WinRT objects look similar to .NET objects. In fact, WinRT supports many constructs we can found in the .NET framework: classes, methods, properties, delegates, events. But, under the hood, the model is completely different. In WinRT there is no managed runtime.

One of the differences that will the most painful, in my opinion, is that WinRT objects are not garbage collected. They are COM objects. They are reference counted; their lifespan is managed calling the old dear AddRef, Release and QueryInterface IUnknown functions.

Old-time COM developers remember that manually managing the calls to AddRef, Release and QueryInterface was no fun; COM rules could get very complicated, and smart pointers (like ATL CComPtr<>) were very handy, in most cases, to simplify the developer’s life.

The good news is that WinRT language projections take care to manage the reference count for us (as nicely as the old VB used to do). Normally, there should not be many reasons to call AddRef and Release explicitly.  But still, WinRT objects are not garbage collected. This makes a big difference: it is sometimes possible to have (kind of) memory leaks in .NET. But it is very easy  to have memory leaks in COM. What one needs to leak two objects is basically just a cross reference between them.

A small memory leak example

Look at the small class in Listing 1 as an example. The class WinRTComponent  exposes a single property, Ref, which can be set to a reference of another instance of WinRTComponent . Listing 2 shows the code of a client JavaScript app which references the WinRTComponent  project. When the web application is launched, every time the left button is clicked the function addAndLinkObjects  instantiates two instances of WinRTComponent  and sets cross references between them.

We can first run the application disabling the cross reference (commenting the line that sets the second reference: objB.ref = objA;). Once the JavaScript objects that “wrap” the WinRT objects go out of scope they can be deleted by the JS garbage collector. We don’t know when this deletion will happen; JavaScript uses its own garbage collection algorithm to decide when to destroy unreferenced objects. But the collection will certainly happen at least when the web application is being closed.

We can force the application to terminate with Alt+F4. Normally this causes the JS wrapper to release the last reference to the WinRT object, and have it destroyed too. This can be easily verified by setting a breakpoint in the class destructor.

But what happens if we uncomment the last line and set a cross-reference between the two WinRT objects? In this case the two WinRTComponent objects, cross referencing each other will still have the reference count to one and will stay alive forever. The destructor breakpoint will never get called. In other words, the objects will be leaked. (Not really forever, of course: their memory must be deallocated when the process terminates).

This memory leak pattern is quite bad, for two reasons:

  1. In a mobile/tablet environment memory is a scarce resource, so any memory leak should be avoided.
  2. If we use a RAII pattern and rely on the destructor to do some clean up (like closing a DB connection), the destructor could never be called.

In his //build/ talk on the internal details of C++ Metro apps Deon Brewis was mentioned using weak references as a possible way to avoid this kind of problems. Before the next post I’ll try to find out how we can use weak references to fix our WinRTComponent class.

Listing 1 – The WinRT object

#pragma once
#include <Windows.h>

using namespace Windows::Foundation;

namespace WinRTTest1
{
    public ref class WinRTComponent sealed
    {
        WinRTComponent^ _ref;

    public:
        WinRTComponent() {
            OutputDebugString(L"created\n");
        }
        ~WinRTComponent() {
            OutputDebugString(L"deleted\n");
        }

        property WinRTComponent^ Ref
        {
            WinRTComponent^ get() { return _ref; }
            void set(WinRTComponent^ propertyAValue) { _ref = propertyAValue; }
        }
    };
}
Listing 2 – The JavaScript client
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>WinWebApp1</title>
    <!-- WinJS references -->
    <link rel="stylesheet" href="/winjs/css/ui-dark.css" />
    <script src="/winjs/js/base.js"></script>
    <script src="/winjs/js/wwaapp.js"></script>
    <!-- WinWebApp1 references -->
    <link rel="stylesheet" href="/css/default.css" />
    <script src="/js/default.js"></script>
    <script>
        function addAndLinkObjects() {
            var objA = new WinRTTest1.WinRTComponent();
            var objB = new WinRTTest1.WinRTComponent();
            objA.ref = objB;
            //objB.ref = objA;
        }
    </script>
</head>
<body id="b" onclick ="addAndLinkObjects();">
</body>
</html>

Windows 8 and WinRT

At the recent //build conference Microsoft has presented Windows 8 bits, and offered its first bits, by publishing a “Developer Preview” version, available for download at the MSDN site.

The big change in Win8 is the shift to “Metro-style” apps, targeted especially to mobile and tablet devices. Steven Sinofsky explained the design goal for Windows 8 as “no compromises”, in the sense that Windows 8 will support the old desktop interface together with the new, immersive, Metro-style interface.

Desktop apps will continue to be written with the technologies used today (Win32, .NET, WPF, and so on). Metro apps are written either using HTML5/JavaScript or using an XAML-based, totally unmanaged GUI framework, codenamed Jupiter. While unmanaged, Jupiter offers an API very similar to WPF and Silverlight.

In both cases, at the foundation of Metro apps lays WinRT (the Windows runtime). This is new runtime, also totally unmanaged, based on COM and written in C++, which targets C++, .NET and JavaScript clients.

From a purely technical point of view, WinRT is the most fascinating aspect of Windows 8. Heavily inspired by .NET, it brings some of the strengths of the managed world to unmanaged C++.

Having downloaded and installed the first prerelease I feel like a kid with a new toy to break and put back together. What I hope to do in these pages is to present a few notes of my little exploration of Win8 and its new runtime.