How to call a function once, and only once ...?

I often want to run a particular function only once, but I need to call it from another function that is called repeatedly. For example, taking a picture of something for later use. I usually do this by setting a global boolean.

I wonder if the way I do this is actually the best way?

I seem to remember that global variables are bad, and global Boolean variables are even worse!

In any case, this is how I usually run a single method only once:

In my original set of variables ...

private var myStatus:Boolean = false; 

Then in a function that is often called ...

 if (!myStatus) { doMyFunction(); myStatus = true; } 

It seems pretty logical to me, but is that right?

UPDATE Based on what I learned from your answers, instead of checking the global boolean variable, I now first check if the XML node exists (I store the images within the XML before any write to the disk occurs), and if it not so, i will add a new node with base64 encoded data. I still set the boolean flag so that I can later overwrite the blank image with custom edited image data if necessary. It works great. Thank you all for your help!

Now I also feel more comfortable using this particular (unsafe) system in certain situations.

+6
language-agnostic loops boolean
source share
7 answers

When you call a function, it should do what you expect from it with the arguments you give it. If you call a function twice the same way, you should expect this function to give you the same results or do the same.

It is probably best to move this dependency “once” to the logic that calls your function many times. If you only need to call the function once, then it is called only once. Alternatively, pass different arguments to the function to indicate that you are doing something else.

+7
source share

It really depends on what you mean. If your code will be called from more than one thread, then you have a race condition, which may mean that doMyFunction could be called many times. This is because more than one thread can check myStatus , see that it is false, and then call doMyFunction . You can improve the situation a bit by setting the variable:

 if (!myStatus) { myStatus = true; doMyFunction(); } 

but this only narrows the window for problems, does not eliminate it.

To eliminate the condition of the race, you need a lock.

+5
source share

In C / C ++, you can usually keep the fact that doMyFunction () is called only after encapsulation using a static variable:

 void doMyFunction() { // gets called only once. // side effects go here. } void functionThatGetsCalledALot() { static bool called = false; if (!called) { doMyFunction(); called = true; } // do more stuff } 

This avoids the use of globals, but has the same effect, and the static var is declared correctly where appropriate, so it is clear what is happening. Please note that this is not thread safe, so you will need a lock if you have threads.

+4
source share

It is not thread safe. This may not matter to you, but you said "language-agnostic": you probably would not want to use this template in a general-purpose library for Java.

This is a difficult question to answer in an agnostic language, because the available alternatives are very dependent on the language. For example, on POSIX you have pthread_once if you need thread safety. In C, you have static local variables to get this boolean from a global scope. In any OO language, if you take a “something” snapshot for later use, then there may be a suitable object corresponding to a “something” (or snapshot) that could hold the flag.

+2
source share

I see nothing wrong with your approach. Keep in mind that there is not always a “right” thing ... there are definitely wrong things, but what is right can be subjective, and it can also depend heavily on system requirements.

0
source share

I do not see another way. The only thing that comes to mind about how to improve this is thread safety. But this is only necessary if you have several threads calling the function.

0
source share

In Perl 5.10 or later, you must use the state variable.

 use 5.010; sub test{ state $once = 1; if( $once ){ $once = undef; say 'first'; } else { say 'not first'; } } test for 1..5; 

exits

  first
 not first
 not first
 not first
 not first
0
source share

All Articles