A common template for initializing and turning off a library?

Is there a pattern that I can use to call the required initialization and cleanup procedures for the base (C) library? In my case, I would like to create a wrapper class so that it can be compiled into other objects. The problem is that when I destroy the wrapper class, the cleanup routines of the base library are called. This is fine until I create some objects of my wrapper class. My question is the best way to handle this situation? A static check counter comes to my mind, but I wanted to know if there are other potentially better options and related trades.

+7
c ++ design-patterns
source share
5 answers

Not everything should be class. The Singleton template would allow you to turn this into a class, but it really didn't buy you anything in terms of global functions:

bool my_library_init(); void my_library_shutdown(); 

The first call returns true if the library was successfully initialized, the second simply silently does everything that needs to be done and exits. You can add any counting links or type of thread tracking for these interfaces that you like.

Also, do not neglect the possibility that your library can do all this transparently. When the first library function is called, can it detect that it has not yet been initialized and is not configured before the job is done? To shutdown, simply register the resources that you want to destroy using the global object, so they will be destroyed when you exit the program. Performing this method is, of course, more complicated, but it can be useful for library users.

+4
source share

If initialization can be called before the main launches, and cleaning is called after the main ends, this little trick (hack?) May 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. This is like RAII for the whole program.

+1
source share

I've seen a lot of Singleton talk, so I can only recommend watching Alexandrescu work .

However, I'm not sure if you really need Singleton . Because if you do, you assume that all your calls will share the state ... is that so? Do you really want when you call the library through another instance of Wrapper to get the state in which the last call is set?

If not, you need to serialize 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 

Pretty simple ... although you need to make sure that Mutex initialized correctly (once) and live until it is no longer needed.

Boost offers funds for after-release , and since we use a stack-based approach with MMutex , it should not be wrong ... I think (buzz).

+1
source share

If you can change the library implementation, each call to one of the library functions can access the singleton element that is created upon first use.

Or you put a global / static variable in a library that initializes it at build time and disables it at destruction time. (This can be annoying if the library uses global variables and the order of initialization / termination of work with them conflicts. In addition, linkers may decide to exclude invalid global variables ...)

Otherwise, I don’t see how you want to avoid link counting. (Note, however, that it has a drawback, perhaps creating several initialization / shutdown cycles during the program life cycle.)

0
source share

If your set of C library routines is not too large, you can try combining Singleton and Facade so that the C library routines are called only through Facade. The façade provides initialization and clearing of the C. library. Singleton ensures that there is only one instance of the façade.

 #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 
0
source share

All Articles