1

Writing code in Brew when local interfaces are being used in it can be repetitive and error prone to make it robust, i.e.:

Foo()
{
ISomeInterface* interface = NULL;
int err = ISHELL_Createnstance(…,...,&interface);

err = somethingThatCanFail();
if (AEE_SUCCESS != err)
    ISomeInterface_Release(interface);

err = somethingElseThatCanFail()
if (AEE_SUCCESS != err)
    ISomeInterface_Release(interface);

etc....

It would be quick to write an RAII class to automatically release the interface on exit from the function, but it would be specific to a particular interface (it would of course call ISomeInterface_Release in its destructor)

Is there any way of making a generic RAII class that can be used for interfaces of different types? i.e. is there a generic Release function that could be called in the RAII instead of the interface specific release, or some other mechanism?

--- Edit ---- Apologies, I originally added the C++ and RAII tags to this posting which I've now removed. As the answer requires Brew knowledge not C++ knowledge. Thanks to the people who took the time to answer, I should have added more info to begin with and not added those additional tags.

Gruntcakes
  • 37,738
  • 44
  • 184
  • 378

2 Answers2

3

shared_ptr does what you ask for:

ISomeInterface* interface = NULL;
int err = ISHELL_Createnstance(…,...,&interface);
std::shared_ptr<ISomeInterface*> pointer(interface, ISomeInterface_Release);

Reference: http://www.boost.org/doc/libs/1_46_1/libs/smart_ptr/shared_ptr.htm#constructors


EDIT Here is a sample:
#include <cstdio>
#include <memory>

int main(int ac, char **av) {
  std::shared_ptr<FILE> file(fopen("/etc/passwd", "r"), fclose);
  int i;
  while( (i = fgetc(file.get())) != EOF)
    putchar(i);
}
Robᵩ
  • 163,533
  • 20
  • 239
  • 308
2

The RAII class that calls a specified function in destructor may look like this:

template<typename T, void (*onRelease)(T)>
class scope_destroyer {
    T m_data;

public:
    scope_destroyer(T const &data) 
        : m_data(data)
    {}

    ~scope_destroyer() { onRelease(m_data); }

    //...
};

Then you just pass a type T (e.g. a Foo*) and a function that can be called with a single parameter of type T and releases the object.

scope_destroyer<Foo, &ISomeInterface_Release> foo(CreateFoo());
Juraj Blaho
  • 13,301
  • 7
  • 50
  • 96
  • 1
    Thanks, but after having a closer look into the brew side of things, its not as simple as it being a function call. There's a bunch of #defines which eventually reduces down to the following (simplyfied a bit): (TypeName##Vtbl)->Release(pointer). Using a template for TypeName doesn't work due to the ## stringization preprocessing (the result is a stringization of T##Vtbl, not the actual typename as required) – Gruntcakes May 19 '11 at 18:09