Reputation: 11651
Say I have a class like this.. This is just an abstract code
class foo
{
public:
int a;
static foo* pfoo;
foo()
{
pfoo = this;
}
fooCar* pFooCar;
void someMethod();
}
Now some other class might do this
foo::pfoo->someMethod();
or
foo::pfoo->a = 14;
Is this practice correct?
Should I make the static variable of the class private and wrap a getter of the static variable in a mutex?
Something like this
class foo
{
private:
static foo* pfoo;
public:
int a;
foo()
{
pfoo = this;
}
static foo* getFoo()
{
lock mutex..
return pfoo
unlock mutex..
}
fooCar* pFooCar;
void someMethod();
}
Any other suggestions ?
Upvotes: 2
Views: 160
Reputation: 462
First of all, your static pfoo
is basically just the singleton pattern, so you can replace that pfoo
stuff with this(Meyers singleton), which is guaranteed safe (if you want to change the pointer afterwards then this doesn't apply):
class foo {
public:
static foo* getFoo() {
static foo singleton;
return &singleton;
}
};
However, anything you do after you receive the pointer is not guaranteed thread-safe. But that all depends on what you need from the code. Thread-safety varies a lot depending on the application, particularly on the number of readers and writers.
Now if you only want a single thread to access the foo
's members at a time then you can just have a single mutex:
class foo {
std::mutex fooMutex;
int bar;
public:
static foo* getFoo() {
static foo singleton;
return &singleton;
}
void setBar(int newBar) {
std::lock_guard guard(fooMutex); //This goes in every function that modifies the data.
bar = newBar;
}
int getBar() {
std::lock_guard guard(fooMutex); //If simultaneous readers are allowed then remove this
return bar;
}
};
It all depends on your use case. This is just the simplest, most naive, and least efficient method of doing this. This does not work if you need to, for example, change the value of bar
depending on its current value.
Upvotes: 1
Reputation: 3392
No, you'll need to wrap the assignment to the static member in an atom step; e.g., critical section, mutex, InterlockedExchangePointer. While it seems like such a simple assignment should be thread safe, it's not; i.e., the assignment is not natively atomic potentially exposing a partially assigned multibyte variable to another thread.
EDIT: sample per op's request and dropped confusing paragraph
Of course, you'll need to setup your mutex prior to using it
foo()
{
pthread_mutex_lock (&mutex);
pfoo = this;
pthread_mutex_unlock (&mutex);
}
static foo* getFoo()
{
foo *retval;
pthread_mutex_lock (&mutex);
retval = pfoo;
pthread_mutex_unlock (&mutex);
return retval;
}
Upvotes: 0
Reputation: 1979
No. Static variable initialization isn't thread-safe itself. In general case you should always use mutexes/spinlocks when you access to shared variables. It's not atomic.
Upvotes: 0
Reputation: 1334
Depends on your design requirement. If there are objects of same class working on some shared data across threads, then you would need to explicitly handle the synchronize threads access to shared data.
In such cases exposing member variable via getters and setters with locks would be correct.
Upvotes: 0