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 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.
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
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++.
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
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
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.
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 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.
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 This thread has been closed and replies have been disabled. Please start a new discussion. Similar topics
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...
|
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,...
|
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...
|
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
|
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...
|
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()...
|
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...
|
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,...
|
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...
|
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...
|
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...
|
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...
|
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)...
|
by: Defcon1945 |
last post by:
I'm trying to learn Python using Pycharm but import shutil doesn't work
|
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....
|
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
|
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...
|
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...
| |