Saturday, May 30, 2009

Is Native Code Hard?

If you read this blog then probably your answer is, like mine, no. So what's the difference between native and managed that makes people avoid native code like the plague? What makes people not want to come back? In my opinion there are a few reasons, especially for Windows Mobile native code:
  • Lack of tools - just try to write a C# application using notepad and the command line compiler and you will see how much tools make a managed developer life easy. There is no comparable level of tool support for native code developers, and this may be linked to the next point.
  • Lack of comprehensive and cohesive libraries and frameworks - the Win32 API is way too low-level for most uses. It's very nice to be able to use it directly without paying the P/Invoke price, but this comes at a cost of having to write dozens of lines of code to achieve a very simple outcome. The OLE DB and MAPI COM interfaces are a perfect example of this - way too complex to use as they are offered. Just compare the "stock" OLE DB samples with the OLE DB Client library I published here...
  • Memory management - this is a minor issue for small applications but when the scale starts to grow it becomes a headache. When are you supposed to delete that object? Is it safe to do it now? Are there other objects referring to it?
I have recently been confronted with the memory management issue in a relatively complex application when I found myself wanting to have the memory management of a particular set of objects to be done automatically. These objects are referred to by an arbitrary number of other objects and determining when their life cycle ended was becoming more and more difficult, especially because they were being referred to by different threads.

There are two basic approaches to automatic memory management that have been used for quite a long time:
  • Reference counting - The iPhone uses a reference counting mechanism to determine when a given object can be removed from memory. The price you pay for this type of memory management is that you have to remember to increment and decrement the memory reference counts. Failing to do this will result in memory leaks. The iPhone uses an optional "autorelease pool" object that kind of protects you from this.
  • Garbage collection - The Java and .NET platforms both use garbage collection to reclaim the memory of objects that are no longer active. The price you pay for this is that the GC has a mind of its own and stops your code in order to clean up the mess. On mobile devices, if you don't manage your memory by reusing objects and by avoiding excessive allocations, the GC will kill your application performance.
One of the interesting advantages of C++ is that it implements deteministic object destruction: when your statically allocated object goes out of scope, the destructor is called. This behavior allows us to implement classes like CWaitCursor that displays the wait cursor on the constructor and hide it or replace it on the destructor. You just have to create a variable of that type and the wait cursor will be shown while the object is alive.

If we couple this with a simple reference counting mechanism, we can actually get all the benefits of a reference-counted memory management scheme without the pain that is imposed on us by the iPhone: we don't have to remember when to increment and decrement the references. How? The dead-old solution is to use reference counted smart pointers to manage our objects' life cycles.

After performing a search for reference-counted smart pointers, and realizing that my needs were quite simple, I decided to roll my own. The first thing we need is a place where to store the reference counts. Some implementations use a proxy object to do this but, for simplicity sake, I decided to put the reference count right on the object through inheritance. This has the disadvantage of having to make all the reference-counted objects inherit from one class, but it's a simple class that will only add four bytes to the object size:


class CRefCount
{
private:
LONG m_nRefCount;

public:
CRefCount(void) : m_nRefCount(0) { };

void RefIncrement()
{
InterlockedIncrement(&m_nRefCount);
}

bool RefDecrement()
{
return InterlockedDecrement(&m_nRefCount) <= 0; } };

Note that I'm using the InterlockedIncrement and InterlockedDecrement to manage the reference count because these methods can be used from different threads. Also, note that the reference count starts at zero (and not at one like on the iPhone) because I want to count how many smart pointers are referring to this object. Let's see how the smart pointer class is defined:


template <class T>
class CRefPtr
{
private:
T *p;

public:
CRefPtr() : p(NULL) { }
CRefPtr(T *pT) : p(pT)
{
if(p)
p->RefIncrement();
}

CRefPtr(const CRefPtr& ptr) : p(ptr.p)
{
if(p)
p->RefIncrement();
}

~CRefPtr() throw()
{
Release();
}

void Release()
{
T* pTemp = p;

if(pTemp)
{
p = NULL;
if(pTemp->RefDecrement())
delete pTemp;
}
}

void Attach(T* p1)
{
Release();
p = p1;
}

operator T*() const throw()
{
return p;
}

T& operator*() const
{
ATLENSURE(p!=NULL);
return *p;
}

bool operator!() const throw()
{
return (p == NULL);
}

T* operator=(const CRefPtr& rhs)
{
if(this != &rhs)
{
Release();
p = rhs.p;
if(p)
p->RefIncrement();
}
return *this;
}

T* operator=(T* pT)
{
if(p != pT)
{
Release();
p = pT;
if(p)
p->RefIncrement();
}
return *this;
}

T* operator->() const
{
ATLASSERT(p != NULL);
return p;
}
};

As you can see each smart pointer takes up the same amount of memory as a regular pointer, so you can safely pass and return it by value from your own methods and functions. This is a very bare-bones implementation and may lack some more sophisticated features, but so far has worked quite well for me. You use it like a CComPtr (I confess that I did look it up when writing this code).

Friday, May 29, 2009

Gynoid

There is a new article on Code Project by Vincent Richomme where he presents the Gynoid framework for cross-platform mobile development. In the included sample, Vincent was so kind as to use the "touch list" WTL control that I have published in this blog. Thank you Vincent!

P.S.: I'm not a guru, I just love this stuff and write about it... ;-)

Saturday, May 23, 2009

Integer Trigonometry

Adding a live GPS feed to a map means, besides near-second updates, the requirement to display a location marker with the current heading. The Window Mobile GPSID provides the current heading in the GPS_POSITION structure as the fHeading value, representing the angle in degrees between the current heading and true North (zero degrees). So how do you go about drawing a compass like the one in the picture?

The drawing is composed of two simple triangles: red for North and blue for South. The drawing is performed by using the Polygon GDI function that takes a list of points describing a closed shape and draws it using the selected pen and brush. Nothing new here. The interesting challenge is how to draw the image in the different angles without a big performance hit (translated: how to implement fast trigonometry functions).

Current Windows Mobile devices are not guaranteed to have an FPU unit that will do all the floating point math for you. If you use the Compact Framework, you are sure that all floating point calculations are performed in a software emulated FPU, so they are much slower than what they could be when performed with a real FPU. When using native code, you have the advantage of using the FPU if one is available, but the code will fall back to the emulator if the FPU is missing.

My approach here was to skip any floating point processing at all. There are two reasons for this:
  1. Drawing a map on a Windos Mobile device is a resource-intensive operation, especially if you are updating it frequently and you want to spend the least amount of time drawing any decorations on top of it. So a fast implementation is required.
  2. This object requires very simple transformations (rotation plus offset) and the required accuracy of the final result is not very high. In fact, it is somewhat low considering the relatively small resolution of WM device screens. The bottom line is that you can live with a bit of error when drawing your compass (this is not rocket science).
So how do you calculate a rotation transformation? Please refer to a good book on the subject (I'm using this lovely book as a reference: Essential Mathematics for Games and Interactive Applications) and you will see that it all boils down to these two simple equations (transforms a point through a counter-clockwise rotation around the origin):
  • x' = x cos(a) - y sin(a)
  • y' = x sin(a) + y cos(a)
Where (x, y) are the original point coordinates, (x', y') are the transformed point coordinates and a is the rotation angle. The first thing you need to do is to "draw" your compass by defining the vertexes assuming that the center of your coordinate system is in the center of the image. In this case, I used the following points:
  • (0, 32) - North
  • (-7, 0) - West
  • (0, -32) - South
  • (8, 0) - East
The reason why I'm not using (7, 0) for East is simple: the final image looks much better on a discrete screen if it has an odd width. If you look at the sample project you will see that I split the compass into two distinct triangles in order to draw them with different pens and brushes.

Now the interesting bit is how I implemented the sin and cos functions: through a table lookup. Assuming that you can live with an error of one degree when specifying the angle, all you need is a precomputed list of the sin values between 0 and 90 degrees. Using basic trigonometry you can derive all sin and cos values from the first quadrant sin values. If you look at the code, you will see that the precomputed sin values are scaled by 10,000. When calculating x sin(a) the code uses the precomputed value and divides the result by 10,000 to get the approximate result (you can use a higher scale for a higher resolution calculation, but that might not be required for this purpose). You can see the implementation of these functions in the FastTrig.h and FastTrig.cpp files in the sample.

Before we can draw our compass on the screen, we must take care of two important issues:
  1. The original compass coordinates are centered around the origin, so we must transform them further to make it fully visible on the screen;
  2. The screen coordinates of a Windows Mobile device are a bit different: while x grows to the right as we expect, y grows down and not up.
This means that beside the rotation we must apply a translation and a "mirror" transformation. In the sample code, I translate by adding the x and y offsets corresponding to the middle of the screen and then the y coordinate is flipped by subtracting it from the window height. Enough of this talk, here's the sample project: GpsCompass.zip.

On a future post I will update this code so that it uses a double buffer painting method to eliminate flickering and connect the compass direction to the GPS heading.

Wednesday, May 20, 2009

One GPS, multiple windows

After publishing the simple GPS class on my last post, I found myself in a situation where I needed the same CGps object to notify more than one window whenever a new GPS event arrived. My scenario is quite simple: while feeding a window with a map, I also need the same CGps object to notify another window where I display some GPS information like the current latitude and longitude coordinates.

The original code supports notifications for one window only so, to solve this issue I could create another instance of the CGps class and have it notify the new window. Although this would work, it would also create an extra thread in the appliction (if you look at the CGps implementation, you will see that it uses a thread to wait on the GPSID events) which is unneeded and consumes more system resources.

I ended up by devising a simpler solution: add multiple window handle - message pairs to the notification mechanism. To implement this I created a new class - CWindowNotifier - that is nothing more than a simple array of HWND and UINT pairs. When the consuming object wants to send a notification to a set of windows, it just calls the appropriate method (Post or Send). If one of the notification windows was closed, the code automatically removes it from the notification list. Using this class is very simple: just call the AddWindow method with the HWND you want to notify and a UINT value containing the message code for the notification. When you want to send a notification use either the Post or Send methods. The Post method uses the PostMessage API so it returns immediately and is the one I recommend for most uses. The Send method uses the SendMessage API, so it works synchronously and waits before all notification windows have responded. You can get the class source code here.

The updated CGps source code is here. Note that this new version uses a new wrapper for the CRITICAL_SECTION objects which you can find here. Enjoy.

Friday, May 15, 2009

A simple GPS reader class

I've been recently involved in a number of projects that require information from the Window Mobile GPS Intermediate Driver. The usage pattern is quite similar in all cases as the application needs to update a window based on the GPS information stream. There are two possible approaches for this: you can use a window timer and poll the GPSID or you can create a worker thread that waits on the GPS stream to wake up and notify the window through a PostMessage call.

The CGps class (download here) is very simple to use. On your window class just declare a member variable of type CGps, like this:

CGps m_gps;

To start receiving GPS data, just call

m_gps.Start(m_hWnd, WM_GPS);

where WM_GPS is a user-defined window message. You can use something like:

#define WM_GPS (WM_USER + 0x654)

Now you need to handle the WM_GPS message in your code (this will be somewhat different if you are using straight API, MFC or WTL). Note that when handling the message, both wParam and lParam are zero - the message works as a simple notification mechanism to let the window class or procedure know that the GPS updated its data. You read the GPS information quite simply:

GPS_POSITION gpsPos;

m_gps.GetPosition(&gpsPos);

To stop the GPS events you can either call Stop() or let the destructor do that for you when the object goes out of scope and is destroyed.

When implementing this class, I had to work around the now-known GPSID API bug. On some devices, the GPSGetPosition API uses a different size for the GPS_POSITION structure (something that has been explained by John Spaith here). The workaround is simple: just feed the thing with a fake buffer and cast it back to a GPS_POSITION. If you look at the implementation, you will see all this trickery at work. But don't worry - it does work!

Tuesday, May 12, 2009

Windows Mobile Marketplace now open

The Windows Mobile Marketplace is now open (but only for US developers?)

Thursday, May 07, 2009

AllKeys, documented

Here is the key capturing API we've all been waiting for since the demise of GAPI: AllKeys.

Wednesday, May 06, 2009

WTL frames, toolbars and headers

The WTL CFrameWindowImpl class template uses a very simple approach to manage the client, toolbar and status bar windows. The preset arrangement for these windows is very simple:
  • a client view that occupies most of the frame's client area;
  • an optional toolbar window that is placed at the top of the frame's client area and above the client view;
  • an optional status bar placed at the bottom of the frame's client area and below the client view.
The frame window already knows how to handle the three child windows. Each frame contains three member variables for them:
  • m_hWndClient for the client view;
  • m_hWndToolBar for the top toolbar window and
  • m_hWndStatusBar for bottom status bar
To make the three child windows work together you must create them and assign them to the appropriate member variable. The top and bottom windows must implement a special handling of the WM_SIZE message because this is how the frame tells each window to place itself in its client area and thus calculate the remaining area for the client view. This special message is nothing but a WM_SIZE message with both parameters (wParam and lParam) set to zero. Here's a sample from my production code:



void OnSize(UINT nType, CSize size)
{
if(size.cx == 0 && size.cy == 0)
{
CWindow wndParent(GetParent());
CRect rc;

wndParent.GetClientRect(&rc);
rc.top = rc.bottom - m_cyToolbar;
MoveWindow(&rc);
}
}

Easy, huh?