Are static member functions reentrant? - c++

Like the title says:
If I have a class with a static member function, which by itself contains no static variables, can I consider the member function reentrant?

Static member functions are no different from namespace-scope functions (or even member functions) with respect to reentrancy. They are not predisposed either way, it depends entirely on what the function does inside.

The rules for Reentrancy laid out in the Wikipedia article on Reentrancy are as follows:
Reentrant code may not hold any static (or global) non-constant data.
Reentrant code may not modify its own code.
Reentrant code may not call non-reentrant computer programs or routines.
so as long as the member function follows those rules it should be ok.
The article Use reentrant functions for safer signal handling I feel gives a slightly better desciption:
A reentrant function is one that can be used by more than one task
concurrently without fear of data corruption. Conversely, a
non-reentrant function is one that cannot be shared by more than one
task unless mutual exclusion to the function is ensured either by
using a semaphore or by disabling interrupts during critical sections
of code. A reentrant function can be interrupted at any time and
resumed at a later time without loss of data. Reentrant functions
either use local variables or protect their data when global variables
are used.
A reentrant function:
Does not hold static data over successive calls
Does not return a pointer to static data; all data is provided by the caller of the function
Uses local data or ensures protection of global data by making a local copy of it
Must not call any non-reentrant functions
and then goes on to explain how this differs from thread-safety before going the article fully.

If your static member function contains only auto variables you could consider it re-entrant.

Related

Are static free functions thread safe?

I am writing a multithreaded program and have a function that will be called from multiple threads that is a static free function within a cpp file. This function will never be called from outside of the cpp file so I wanted to make it static so that it had internal linkage.
Googling around I found a lot of people saying "static functions are not thread safe" but then when I go to read up about it everyone seems to be talking about static member functions, not static free functions.
Are static free functions thread safe (assuming they don't access any shared state between threads)?
Any function that accesses no shared state is inherently thread safe. You only get a data race when you have unprotected read/writes to shared state. If there is no shared state, you can't have a data race.
This is why purely functional languages are naturally thread safe. If a function doesn't have side effects, then you can call it in as many threads as you want.
Static functions are the same as other functions. It is not the function, it is what the function does.
I think some people are mixing between terms. static function vs function with static variables.
while static function may be safe or not, a function with static variables is not safe without synchronization.
An example of such a function is strtok which keeps in a static variable the continuation point. when several threads use the old strtok, it may cause a mixture between the inputs.

Is it bad practice to declare a C function as static if it can still be executed indirectly (through a callback function)?

I have a C module for an embedded system (foo.c, foo.h) that contains a function my_driver_fn() that is local in scope from an API perspective (e.g. not in foo's public header: any other code that uses its API via #include "foo.h" should not be allowed to call this function). Assume my_driver_fn() is reentrant.
However, foo uses a library libdostuff that needs to be initialized with a few user-supplied callback functions (architecture/hardware specific things) for it to work properly on any platform. In foo, my_driver_fn mentioned above would be one of the functions in question...needed by libdostuff, but not by anyone that uses foo.
Is it bad form, dangerous, disadvantageous, handicapping the compiler in any way, or undefined behavior that the compiler could capitalize on, for these callback functions (my_driver_fn() to be declared as static within foo.c? Given that its address is provided to libdostuff and it is "indirectly" called (though never directly)?
Note: I happen to be writing both foo and libdostuff, and I'm wondering whether it makes more sense for the user-supplied functions to be extern and purely resolved at link-time, or passed into libdostuff via a user-supplied callback table supplied in an initialization function (e.g. libdostuff_init(CallbackTable *user_callbacks) where CallbackTable has a function pointer that would be initialized to point to my_driver_fn)
In my opinion this is good practice. The static refers to the visibility of the name, and nothing else.
If the name is not needed to be used by other translation units, then marking it static reduces the risk of a clash in the "namespace" of externally visible functions .
It is good practice and there are no negative side-effects like poorly-defined behavior.
There are many reasons for using static, like reducing namespace pollution and avoiding accidental/intentional calls. But the main reason is actually private encapsulation design and self-documenting code - to keep functions in the module they belong, so that the outside world need not worry about how and when to call them. They should only care about the external linkage functions you have declared in the public header file.
This is for example exactly how you design ISRs in embedded systems. They should always be declared static and be placed inside the driver controlling the hardware that the ISR relates to. All communication with the ISR, including race condition protection, should be placed encapsulated in that driver. The calling application never speaks directly with the ISR and should not need to worry about re-entrancy etc. Same thing with DMA buffers.
As an example of this, I always design a cyclic timer driver for all my MCU projects, where the API to the caller lets them register simple callback functions. The timer driver then calls the callback when the timer elapses, from inside the ISR. This can then be used as a general-purpose timer for all low priority tasks that need a timer: delays, de-bouncing etc. The caller then only needs to responsibly keep the callback function minimal and specify a time in ms, but the caller doesn't know or care about the timer hardware, and the timer hardware knows nothing of the callback it executes. Loose coupling in both directions. This timer API also serves as a HAL, so you can port the code to another MCU without changing the caller code - only change the underlying driver.
It is good practice. It ensures the function can only be called by the code you have explicitly provided the callback to. If it had external linkage, anything could call it, whether it makes sense or not. It is clearly not impossible to abuse, but does make it more difficult to do accidentally.

Do i need a mutex for a static function?

I have a C++ class with a static function:
class Foo
{
public:
static void bar(int &a)
{
a++;
}
}
EDIT:
The variable passed as argument is only used within the calling scope. So it is not accessed by another thread.
Do i have to use a mutex when i call this function from a seperate thread?
Thanks.
Calling this function requires only thread-local resources, the stack of thread. Therefore the answer is no. If the int variable is accessible by more than the calling thread, you will need a mutex for the variable
Whether a function is static has no bearing on whether calls to it need to be synchronised.
The determining factor is whether the function is re-entrant, and what you do with the data. In this case, the function is re-entrant (as it has no non-local state of its own, or in fact any state at all), and the data is owned/managed by the calling scope, so you will have to decide within the calling scope whether that integer requires protection.
But this is true whether bar is a static member, a non-static member, a free function, a macro, a cat, a black hole, or Jon Skeet's tumble dryer.
I'd like to mention that mutex is not the only thread synchronization primitive available, and in some scenarios far from most approriate one.
Provided synchronization is needed (see two other answers on why it might be needed depending on usage) don't jump into mutex world. For something as straitghtforward as a counter (this is what I see in the code) atomic variables (or, in absence of those, atomic operations on non-atomic types) often provide a better performance and more straightforward code.
In this particular case, incrementing a variable can be easily done in thread-safe way with following C++11 code:
static void bar(std::atomic<int>& a)
{
a.fetch_add(1, std::memory_order_relaxed);
}
memory_order_relaxed used here is really far-fetched, and not neccessarily applicable (however, often good for counters). Used here mostly for the example.

Simultaneous Object Calls

If I have shared an object between 2 threads (by passing in a void pointer to the object) what happens if they both try to call (different) methods at the same time? I'm not worried about the member variables themselves, there's a mutex in place for other reasons that luckily covers that already. The main function are calling disjoint methods so there's no possibility of overlap that way, but I wasn't sure what the behavior would be if main calls thing.a() while thread calls thing.b() at the same time (or even if they just overlap for that matter).
Nothing special would happen, each thread has its own stack, and each call (even if it was to the same function) would have its own call-frame and its own set of arguments and local variables.

Is this way of creating static instance thread safe?

I have the following sample C++ code:
class Factory
{
public:
static Factory& createInstance()
{
static Factory fac;
return fac;
}
private:
Factory()
{
//Does something non-trivial
}
};
Let's assume that createInstance is called by two threads at the same time. So will the resulting object be created properly? What happens if the second thread enters the createInstance call when the first thread is in the constructor of Factory?
C++11 and above: local static creation is thread-safe.
The standard guarantees that:
The creation is synchronized.
Should the creation throws an exception, the next time the flow of execution passes the variable definition point, creation will be attempted again.
It is generally implemented with double-checking:
first a thread-local flag is checked, and if set, then the variable is accessed.
if not yet set, then a more expensive synchronized path is taken, and if the variable is created afterward, the thread-local flag is set.
C++03 and C++98: the standard knows no thread.
There are no threads as far as the Standard is concerned, and therefore there is no provision in the Standard regarding synchronization across threads.
However some compilers implement more than the standard mandates, either in the form of extensions or by giving stronger guarantees, so check out for the compilers you're interested in. If they are good quality ones, chances are that they will guarantee it.
Finally, it might not be necessary for it to be thread-safe. If you call this method before creating any thread, then you ensures that it will be correctly initialized before the real multi-threading comes into play, and you'll neatly side-step the issue.
Looking at this page, I'd say that this is not thread-safe, because the constructor could get called multiple times before the variable is finally assigned. An InterlockedCompareExchange() might be needed, where you create a local copy of the variable, then atomically assign the pointer to a static field via the interlocked function, if the static variable is null.
Of course it's thread safe! Unless you are a complete lunatic and spawn threads from constructors of static objects, you won't have any threads until after main() is called, and the createInstance method is just returning a reference to an already constructed object, there's no way this can fail. ISO C++ guarantees that the object will be constructed before the first use after main() is called: there's no assurance that will be before main is called, but is has to be before the first use, and so all systems will perform the initialisation before main() is called. Of course ISO C++ doesn't define behaviour in the presence of threads or dynamic loading, but all compilers for host level machines provide this support and will try to preserve the semantics specified for singly threaded statically linked code where possible.
The instantiation (first call) itself is threadsafe.
However, subsequent access will not be, in general. For instance, suppose after instantiation, one thread calls a mutable Factory method and another calls some accessor method in Factory, then you will be in trouble.
For example, if your factory keeps a count of the number of instances created, you will be in trouble without some kind of mutex around that variable.
However, if Factory is truly a class with no state (no member variables), then you will be okay.