Thank you C++ for … exceptions

Return value is not the best error handling mechanism

C

This example closely resembles the code I’ve seen in Windows CE drivers.

BOOL doStuff() {
    void* mem_buff = NULL;
    PHANDLE res_1_handle = NULL;
    PHANDLE res_2_handle = NULL;
    BOOL result = FALSE;

    if (mem_buff = malloc(WORK_BUFFER_SIZE)) {
        goto error;
    }

    if (RES_ERR == acqRes1(res_1_handle)) {
        goto error;
    }

    if (RES_ERR == acqRes2(res_2_handle)) {
        goto error;
    }

    if (compute(res_1_handle, res_2_handle, mem_buff)) {
        result = TRUE;
    }

    error:
    if (res_2_handle != NULL) {
        relRes2(res_2_handle);
        res_2_handle = NULL;
    }

    if (res_1_handle != NULL) {
        relRes1(res_1_handle);
        res_1_handle = NULL;
    }

    if (mem_buff != NULL) {
        free(mem_buff);
        mem_buff = NULL;
    }

    return result;
}

What’s not visible above is the amount of repeated error handling logic deep in the bowels of relRes[12]() and acqRes[12]().

C++11

As you may guess the resource classes can be done much better by the usage of templates so that there is much less code repetition. As we try to stick with the C code, C++ can’t shine that well.

class Resource1 {
public:
    Resource1() : m_handle(NULL) {
        if (RES_ERR == acqRes1(m_handle)) {
            throw;
        }
    }

    ~Resource1() {
        relRes1(m_handle);
        m_handle = NULL;
    }

    PHANDLE get() {
        return m_handle;
    }

private:
    PHANDLE m_handle;
};

class Resource2 {
public:
    Resource2() : m_handle(NULL) {
        if (RES_ERR == acqRes2(m_handle)) {
            throw;
        }
    }

    ~Resource2() {
        relRes2(m_handle);
        m_handle = NULL;
    }

    PHANDLE get() {
        return m_handle;
    }

private:
    PHANDLE m_handle;
};

bool doStuff() {
    try {
        Resource1 res1;
        Resource2 res2;
        std::unique_ptr<void> buffer(
            (void*)new char[WORK_BUFFER_SIZE]
        );

        return compute(res1.get(),
                       res2.get(),
                       buffer.get());
    }
    catch (...)
    {
        return false;
    }
}

You can choose your winner now.

Advertisements

Tags: ,

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s


%d bloggers like this: