API initialization and cleanup

M

Mark Stijnman

I need to use an API in our current project and I have been writing
some wrapper classes for the functionality we need. Unfortunately,
before you can use any API calls, the API must be initialized, and
after your done with the API, it wants you to call a cleanup function.
I am now looking for a safe solution to wrap the API
initialization/cleanup.

I am thinking of something along these lines: every class that needs
the API is privately inherited from a class like this one:

class ApiUser {
public:
ApiUser() {
if (_count==0) API_Init();
_count++;
}
ApiUser(ApiUser& a) {
_count++;
}
~ApiUser() {
_count--;
if (_count==0) API_Cleanup();
}
private:
static unsigned int _count;
};

// In cpp file:
int ApiUser::_count = 0;

So, if class A uses the Api, I would declare

class A: private ApiUser { ... };

Would this be a good solution? The static count variable makes me a
little uncomfortable, especially since I expect that threads will be
used at some point. I could of course use mutexes/locks on the static
variable. Are there any other drawbacks I'm missing?

Are there any other approaches that can be used? I've tried looking for
them, but haven't been able to find it, despite the fact that this must
be a rather commonly occurring thing. How have you solved this? Thanks
for any comments or pointers,

regards Mark
 
B

Ben Pope

Mark said:
I need to use an API in our current project and I have been writing
some wrapper classes for the functionality we need. Unfortunately,
before you can use any API calls, the API must be initialized, and
after your done with the API, it wants you to call a cleanup function.
I am now looking for a safe solution to wrap the API
initialization/cleanup.

I am thinking of something along these lines: every class that needs
the API is privately inherited from a class like this one:

class ApiUser {
public:
ApiUser() {
if (_count==0) API_Init();
_count++;
}
ApiUser(ApiUser& a) {
_count++;
}
~ApiUser() {
_count--;
if (_count==0) API_Cleanup();
}
private:
static unsigned int _count;
};

// In cpp file:
int ApiUser::_count = 0;

So, if class A uses the Api, I would declare

class A: private ApiUser { ... };

Would this be a good solution? The static count variable makes me a
little uncomfortable, especially since I expect that threads will be
used at some point. I could of course use mutexes/locks on the static
variable. Are there any other drawbacks I'm missing?

Thats horrible, what if a free function needs to use the API?
Are there any other approaches that can be used? I've tried looking for
them, but haven't been able to find it, despite the fact that this must
be a rather commonly occurring thing. How have you solved this? Thanks
for any comments or pointers,

Whats wrong with:

class ApiWrapper {
ApiWrapper() {API_Init();}
~ApiWrapper() {API_Cleanup();}
}

int main() {
// Anything not using API.
ApiWrapper apiWrapper;
// Anything using API.
// Cleanup automatic when the temporary is destroyed.
}

Unless it's particularly expensive to initialise and you might not need
it in the programs lifetime.

Ben Pope.
 
M

Mark Stijnman

Ben said:
Thats horrible, what if a free function needs to use the API?

One could use a local variable in the free function like so:

void ApiUsingFunc() {
ApiUser localApiUser;
// Do Api stuff
}
Whats wrong with:

class ApiWrapper {
ApiWrapper() {API_Init();}
~ApiWrapper() {API_Cleanup();}
}

int main() {
// Anything not using API.
ApiWrapper apiWrapper;
// Anything using API.
// Cleanup automatic when the temporary is destroyed.
}

Unless it's particularly expensive to initialise and you might not need
it in the programs lifetime.

Ben Pope.

For one thing, having that in the main function makes it more difficult
to transparently use the other wrapper classes. I kinda like the RIIA
idiom and I would if anyway possible hide the init/cleanup details from
the user. In your example, the programmer would need to know that
somewhere in all the components your application uses, the Api is
needed.

regards Mark
 
M

Maxim Yegorushkin

Mark said:
Would this be a good solution?

It's a good one. Looks somewhat similar to schwarz counter used ti
initialize iostreams.
The static count variable makes me a
little uncomfortable, especially since I expect that threads will be
used at some point. I could of course use mutexes/locks on the static
variable. Are there any other drawbacks I'm missing?

On many platforms you could use atomic integer ops, such as those from
<bits/atomicity.h> header shipped with g++.
 
B

Ben Pope

Mark said:
One could use a local variable in the free function like so:

void ApiUsingFunc() {
ApiUser localApiUser;
// Do Api stuff
}


For one thing, having that in the main function makes it more difficult
to transparently use the other wrapper classes. I kinda like the RIIA
idiom and I would if anyway possible hide the init/cleanup details from
the user. In your example, the programmer would need to know that
somewhere in all the components your application uses, the Api is
needed.

OK, so I think I misunderstood, slightly.

You're providing an API that uses another API. Your API has several
classes, and multiple classes require the other API?

Actually, your example isn't nearly as bad as I thought it might be, I
thought you expected your users to inherit from the base class.

I think it's fine, perhaps use a protected destructor if you don't have
any free functions that require the API.

Apologies for the misunderstanding!

Ben Pope
 
M

Mark Stijnman

Ben said:
OK, so I think I misunderstood, slightly.

You're providing an API that uses another API. Your API has several
classes, and multiple classes require the other API?

Yeah, that's what's happening, I'm basically wrapping some
functionality from a C API in some classes, and they need the API to be
initialized. The cleanup of that API however destroys all open
resources, so just calling API_Init in each class's ctor and
API_Cleanup in each dtor won't work.
Actually, your example isn't nearly as bad as I thought it might be, I
thought you expected your users to inherit from the base class.

No, only the wrapper classes that I am writing will inherit from
ApiUser.
I think it's fine, perhaps use a protected destructor if you don't have
any free functions that require the API.

Apologies for the misunderstanding!

No sweat :) Besides, your comment about free functions was something I
hadn't thought about, so thanks for pointing that out. I'll probably
just keep the dtor public, so I can indeed use this for free functions
too, should the need ever arrive.

regards Mark
 
Z

Zara

I need to use an API in our current project and I have been writing
some wrapper classes for the functionality we need. Unfortunately,
before you can use any API calls, the API must be initialized, and
after your done with the API, it wants you to call a cleanup function.
I am now looking for a safe solution to wrap the API
initialization/cleanup.

I am thinking of something along these lines: every class that needs
the API is privately inherited from a class like this one:

class ApiUser {
public:
ApiUser() {
if (_count==0) API_Init();
_count++;
}
ApiUser(ApiUser& a) {
_count++;
}
~ApiUser() {
_count--;
if (_count==0) API_Cleanup();
}
private:
static unsigned int _count;
};

// In cpp file:
int ApiUser::_count = 0;

So, if class A uses the Api, I would declare

class A: private ApiUser { ... };

Would this be a good solution? The static count variable makes me a
little uncomfortable, especially since I expect that threads will be
used at some point. I could of course use mutexes/locks on the static
variable. Are there any other drawbacks I'm missing?

Are there any other approaches that can be used? I've tried looking for
them, but haven't been able to find it, despite the fact that this must
be a rather commonly occurring thing. How have you solved this? Thanks
for any comments or pointers,

regards Mark

This is in fact the usual solution, if you are in a single threaded
application.
For mutithreaded applications, I would recommend asking in
comp.programming.threads.
 
M

Michiel.Salters

Mark said:
I need to use an API in our current project and I have been writing
some wrapper classes for the functionality we need. Unfortunately,
before you can use any API calls, the API must be initialized, and
after your done with the API, it wants you to call a cleanup function.

( Good single-threaded solution)
The static count variable makes me a
little uncomfortable, especially since I expect that threads will be
used at some point. I could of course use mutexes/locks on the static
variable. Are there any other drawbacks I'm missing?

The library might need per-thread cleanup, and you don't have to
lockout
all threads if a thread drops one reference but keeps another. So,
basically
i'd do (in pseudo-code)

if(thread_reference_count == 0) {
lock mutex
if( program_reference_count == 0 ) {
init_api()
program_reference_count == 1
} else {
++program_reference_count;
unlock mutex
thread_reference_count = 1;
} else
thread_reference_count += 1;
}

You only need the mutex once per thread in this design.

HTH,
Michiel Salters
 
M

Maxim Yegorushkin

(e-mail address removed) wrote:

[]
The library might need per-thread cleanup, and you don't have to
lockout
all threads if a thread drops one reference but keeps another. So,
basically
i'd do (in pseudo-code)

if(thread_reference_count == 0) {
lock mutex
if( program_reference_count == 0 ) {
init_api()
program_reference_count == 1
} else {
++program_reference_count;
unlock mutex
thread_reference_count = 1;
} else
thread_reference_count += 1;
}

You only need the mutex once per thread in this design.

Note that you hit visibility isses when you increment the variable
outside the critical section. This is not a problem when you are only
interested in 0 -> 1 state change because this happens inside the
critical section which imposes a memory barrier. You'll have to
decrement it inside a critical section only if you'd like to do
cleanup.

In this paticular case if you are interested in initialization only one
could use pthread_once function.
 
M

Michiel.Salters

Maxim said:
(e-mail address removed) wrote:

[]
The library might need per-thread cleanup, and you don't have to
lockout
all threads if a thread drops one reference but keeps another. So,
basically
i'd do (in pseudo-code)

if(thread_reference_count == 0) {
lock mutex
if( program_reference_count == 0 ) {
init_api()
program_reference_count == 1
} else {
++program_reference_count;
unlock mutex
thread_reference_count = 1;
} else
thread_reference_count += 1;
}

You only need the mutex once per thread in this design.

Note that you hit visibility isses when you increment the variable
outside the critical section.

Apparently it wasn't clear from the pseudo code that
thread_reference_count
is a thread-local reference count. It's outside the critical section
because
each thread has its own instance. Therefore, it's not visible outside
that
thread and doesn't need protection.

HTH,
Michiel Salters
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top