473,324 Members | 2,178 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,324 software developers and data experts.

API initialization and cleanup

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

Nov 24 '05 #1
9 1706
Mark Stijnman wrote:
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.
Nov 24 '05 #2

Ben Pope wrote:
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

Nov 24 '05 #3

Mark Stijnman wrote:
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++.

Nov 24 '05 #4
Mark Stijnman wrote:
Ben Pope wrote:
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.


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
Nov 24 '05 #5

Ben Pope wrote:
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.
Ben Pope


regards Mark

Nov 24 '05 #6
On 24 Nov 2005 01:54:32 -0800, "Mark Stijnman"
<Ma***********@gmail.com> wrote:
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.
Nov 24 '05 #7
Mark Stijnman wrote:
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

Nov 24 '05 #8

Mi*************@tomtom.com wrote:

[]
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.


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.

Nov 24 '05 #9

Maxim Yegorushkin wrote:
Mi*************@tomtom.com wrote:

[]
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.


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

Nov 24 '05 #10

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

6
by: use dmgass at hotmail dot com | last post by:
I'm writing a module and when it is imported by a script I want some code automatically executed when the importing script is finished executing. I'd like it to execute before interactive mode is...
1
by: Qin Chen | last post by:
I will present very long code, hope someone will read it all, and teach me something like tom_usenet. This question comes to me when i read <<Think in C++>> 2nd, chapter 10 , name control,...
3
by: ferdinand.stefanus | last post by:
Hi I am writing a C++ class that performs video decoding using a hardware library. In the library documentation, it is stated that the library has a function that must be called once before all...
0
by: sowencheung | last post by:
think about we have a private hashtable object (variable) we initialize the objects in some methods, now we create a cleanup method, we can either new 1) hash = new HashTable(); or
15
by: Dilip | last post by:
The subject is a bit misleading because I really can't figure out what the following code snippet is doing and would appreciate any help in deciphering it. I mean I can understand code-wise what...
1
by: Jason S | last post by:
I haven't used try/catch/finally very much in Javascript. My function (let's call it try_it()) needs to call a function that could throw an exception (let's call it dangerous()) with some setup()...
69
by: MQ | last post by:
Hi all I am just wondering how most people implement cleanup in C functions. In particular, if the function opens a number of resources, these need to be released properly should an error occur...
3
by: Petr Pavlu | last post by:
Hello, I have two questions how the functions should be written. I read the FAQ but didn't find any answer. If there is any please point me out. I. Cleanup code Consider I have to open file1,...
4
by: IanWright | last post by:
I've got a section of a program that I can't quite get to work. I'm fairly sure its something very simple/trivial but it looks correct to me, so if someone could help me fix the problem, and explain...
0
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...
0
by: jfyes | last post by:
As a hardware engineer, after seeing that CEIWEI recently released a new tool for Modbus RTU Over TCP/UDP filtering and monitoring, I actively went to its official website to take a look. It turned...
0
by: ArrayDB | last post by:
The error message I've encountered is; ERROR:root:Error generating model response: exception: access violation writing 0x0000000000005140, which seems to be indicative of an access violation...
1
by: PapaRatzi | last post by:
Hello, I am teaching myself MS Access forms design and Visual Basic. I've created a table to capture a list of Top 30 singles and forms to capture new entries. The final step is a form (unbound)...
1
by: Defcon1945 | last post by:
I'm trying to learn Python using Pycharm but import shutil doesn't work
1
by: Shællîpôpï 09 | last post by:
If u are using a keypad phone, how do u turn on JavaScript, to access features like WhatsApp, Facebook, Instagram....
0
by: af34tf | last post by:
Hi Guys, I have a domain whose name is BytesLimited.com, and I want to sell it. Does anyone know about platforms that allow me to list my domain in auction for free. Thank you
0
by: Faith0G | last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 3 Apr 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome former...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.