Is there a pattern that I may use for calling the required initialization and cleanup routines of an underlying (C) library? In my case, I would like to create the wrapper class so that it can be composed into other objects. The problem is that, when I destroy the wrapper class, the cleanup routines of the underlying library are called. That's fine until I instantiate multiple objects of my wrapper class. My question is what is the best way to really handle this situation? A static reference counter comes to mind, but I wanted to know if there were other potentially better options and the trades involved.
Not everything has to be a class. The Singleton pattern would let you turn this into a class, but it's really not buying you anything over global functions:
bool my_library_init();
void my_library_shutdown();
The first call returns true if the library was successfully initialized, the second just quietly does whatever needs to be done and exits. You can add whatever reference counting or thread tracking type stuff behind these interfaces you like.
Also, don't neglect the possibility that your library may be able to do all of this transparently. When the first library function is called, could it detect that it is not initialized yet and set everything up before doing the work? For shutdown, just register the resources to be destroyed with a global object, so they are destroyed when the program exits. Doing it this way is certainly trickier, but may be worth the usability benefit to your library's callers.
If the initialization can be called before main starts, and cleanup called after main ends, this little trick (hack?) might work for you:
#include <iostream>
// C library initialization routine
void init() {std::cout << "init\n";}
// C library cleanup routine
void fini() {std::cout << "fini\n";}
// Put this in only one of your *.cpp files
namespace // anonymous
{
struct Cleaner
{
Cleaner() {init();}
~Cleaner() {fini();}
};
Cleaner cleaner;
};
int main()
{
std::cout << "using library\n";
}
Output:
init
using library
fini
It uses (abuses?) the fact that constructors for static objects are called before main, and that destructors are called after main. It's like RAII for the whole program.
If you can change the library implementation, you could have each call to one of the library's functions access a singleton which is created on first use.
Or you put a global/static variable into the library which initializes it during construction and shuts it down during destruction. (That might become annoying if the library uses global variables itself and the order of initialization/shutdown conflicts with them. Also, linkers might decide to eliminate unreferenced globals...)
Otherwise, I don't see how you want to avoid reference counting. (Note, however, that it has the drawback of possibly creating multiple init/shutdown cycles during the program's lifetime.)
If your set of C library routines is not too large, you can try combining the Singleton and Facade patterns so that C library routines are only invoked via the Facade. The Facade ensures the initialization and cleanup of the C library. Singleton insures that there is only one instance of the Facade.
#include <iostream>
// C library initialization and cleanup routines
void init() {std::cout << "init\n";}
void fini() {std::cout << "fini\n";}
// C library routines
void foo() {std::cout << "foo\n";}
void bar() {std::cout << "bar\n";}
class Facade // Singleton
{
public:
void foo() {::foo();}
void bar() {::bar();}
static Facade& instance() {static Facade instance; return instance;}
private:
Facade() {init();}
~Facade() {fini();}
};
// Shorthand for Facade::instance()
inline Facade& facade() {return Facade::instance();}
int main()
{
facade().foo();
facade().bar();
}
Output:
init
foo
bar
fini
I have seen a lot of Singleton
talk, so I can only recommend a look at Alexandrescu's work.
However I am not sure that you really need a Singleton
there. Because if you do, you assume that all your calls are going to share the state... is it the case ? Do you really wish when you call the library through a different instance of Wrapper
to get the state in which the last call set it ?
If not, you need to serialize the access, and reinitialize the data each time.
class Wrapper
{
public:
Wrapper() { lock(Mutex()); do_init_c_library(); }
~Wrapper() { do_clean_up_c_library(); unlock(Mutex()); }
private:
static Mutex& Mutex() { static Mutex MMutex; return MMutex; }
}; // class Wrapper
Quite simple... though you need to make sure that Mutex
is initialized correctly (once) and live until it's not needed any longer.
Boost
offers facilities for the once issue, and since we use a stack based approach with MMutex
it should not go awry... I think (hum).