0

I have an object APIController that handles an external library. And I would like to access this (unique) controller from different calls of the same function (C-style).

Therefor, I thought about making a global APIController variable in order to access to the same instance throughout the different calls of my function where the given context_t *context is different at every call. At the end, the program calls the close function for every context.

APIController *controller = NULL;

void call(context_t *context) /* called with different contexts */
{
    if (controller == NULL) controller = new APIController();
    controller->instances_counter++;
    /* use controller */
    controller->use_it();
}

void close(context_t *context)
{
    controller->instances_counter--;
    if (controller->instances_counter == 0)
        delete controller;
}

Is it proper to proceed that way? I feel it is not but I don't see another easy way of doing it.

Jav
  • 1,445
  • 1
  • 18
  • 47
  • What's a _'c global variable'_ please? Did you mean a static instance of your class?!? _'Is it proper to proceed that way?'_ Certainly that's not a very good solution IMHO. – πάντα ῥεῖ Jun 20 '14 at 14:27
  • If you're going to have multiple threads in those functions at the same time, you should use some sort of mutex to guard access to the controller and its counter. – dlf Jun 20 '14 at 14:29
  • I agree with "not good" and "mutex", but just a short plain answer: Yes, it is allowed. If you compile as C++ it is C++, doesn´t matter which sort of thread function you´re using. And in C++, you can use C++ objects... – deviantfan Jun 20 '14 at 14:31
  • 1
    I you really need to provide a singleton you should use a proper singleton class idion (as e.g. [proposed here](http://stackoverflow.com/questions/18613633/c-singleton-with-private-constructor/18613945#18613945)). This is guaranteed to be thread safe in the current standard! – πάντα ῥεῖ Jun 20 '14 at 14:32
  • 1
    @πάνταῥεῖ Just curious--what was added to the current standard to make that threadsafe? – dlf Jun 20 '14 at 14:33
  • 1
    @dlf The way how local static variables are to be instantiated. Mentioned here: http://stackoverflow.com/questions/8102125/is-local-static-variable-initialization-thread-safe-in-c11 – πάντα ῥεῖ Jun 20 '14 at 14:34
  • The multithreaded part is safe... I'm concerned about the global variable up there instead of being in a context (I updated my code) – Jav Jun 20 '14 at 14:35
  • @Jav _'The multithreaded part is safe'_ Not as far I can see?!? I'd really recommend to stay away from this global pointer stuff! It's error prone as can actually be :P ... – πάντα ῥεῖ Jun 20 '14 at 14:38
  • @πάνταῥεῖ, actually, the program is threaded after all the calls to the function `call(context_t *context)`, I was confused when I wrote the question. – Jav Jun 20 '14 at 14:40
  • @Jav Why the comment `/* called by the the different threads */` is there then? If it's called from different threads, it's not thread safe as it is, period! – πάντα ῥεῖ Jun 20 '14 at 14:43
  • @πάνταῥεῖ Wonderful. Except, apparently, for those of us using a [Microsoft compiler](http://msdn.microsoft.com/en-us/library/vstudio/hh567368(v=vs.120).aspx) (see "Magic statics"). – dlf Jun 20 '14 at 14:43
  • @dlf Ehh, what?!? Where was microsoft compiler addressed in this question??? (in fact it was GCC) – πάντα ῥεῖ Jun 20 '14 at 14:45
  • @πάνταῥεῖ I know; I'm just whining about discovering yet another great C++11 feature I don't get to use :). – dlf Jun 20 '14 at 14:45
  • Sorry for the confusion. I updated my question (and removed the obsolete comment). FYI, the program is creating threads after all calls of the function `call` and close them before calling all calls of the function `close`. – Jav Jun 20 '14 at 14:47

2 Answers2

1

It dependes. If your API & controller is either stateless (so you will only ever need one of them), or it's state is not stored in the APIController object (you have no way of creating 2 different API controller) you should make the APIController class a singleton.

There are about a thousand posts out there about when not to use singletons, but this case is one of the rare case when it does make sense.

On the other hand if you can create 2 difference configurations of this APIController, and you may think that sometime in the future you'd possibly want to use more than one of them, you should, either pass it as a parameter to call or better make call a member function of some class that will store this information.

class SomeObject
{
private:
    APIController * api;

public:

   // ...

   void call(context_t context)
   {
      // ...
   }

   // ...
};

Ultimately do what it makes sense to you, but keep in mind that you'll probably need to rewrite your code a couple of times before the final version, so thinking along the lines of "I'll probably only ever need one of this Object" may come back on you one day.

Evan Dark
  • 1,311
  • 7
  • 7
  • I've seen the argument "but this time we really only need one instance ever" a couple times by now, and invariably there is a time where it bites you (the last time was about a database accessor). – Matthieu M. Jun 20 '14 at 17:27
  • Well there are APIs when you need to create an object just to access any functions in the API (like DirectX, if I remember correctly). Then you really do need a singleton object. Any other time I wouldn't recommend it. – Evan Dark Jun 24 '14 at 11:47
  • Why would you need an object there ? If there is no state you do not need an object (free-functions/static methods would suffice), and if there is state then we are back to global state. I've heard lots of complains from Game Devs about this issue of global state in graphics API, they would really prefer having an explicit context object and thus choose *which* context to pass. – Matthieu M. Jun 24 '14 at 12:16
0

It depends on what you mean by "allowed"

Yes, the c++ compiler will let you do it.

No, you shouldn't do it this way.

Consider using a static member of a class rather than a C-style global, but better yet, read about the Singleton Pattern, and you will find several proven approaches to handling this type of problem.

You will also find a lot of discussion about why the Singleton pattern is evil (it is). Rest assured that a C-style global variable is worse. Try to find a way to redesign your system so that you are not locked into to exactly one instance of you APIControler (even though, in practice, only one instance will exist.) The effort to do this usually improves the overall design.

Dale Wilson
  • 9,166
  • 3
  • 34
  • 52