c++ pseudocode class:
Simple class which has a member variable, and mutex to control access to it.
I'm curious about the pro's and con's of managing the data and it's access.
In a multithreaded enviroment, is it wrong to use the approach to accessing and locking the member mutex in cbMethodA()?
I've seen samples where the members are accessed directly, and it seems incorrect to do that. The class exposes access via a public method for a reason.
Also, dereferencing a mutex to then lock it doesn't seem like best practice. Any comments?
Thanks
class A
{
public:
A():val(0);
~A();
int getVal(void);
static void cbMethodA();
static void cbMethodB();
private:
Mutex m_mutex;
int val;
}
int A::getVal(){
{
int returnVal = 0;
lockMutex(m_mutex);
returnVal = m_val;
unlock(mutex);
return returnVal;
}
void A::cbMethodA(void *ptr)
{
A* ptr = static_cast<A*> (ptr);
//get val
lockMutex(ptr->m_mutex);
//read val
int tempVal = ptr->m_val;
unlockMutex(ptr->m_mutex);
//do something with data
}
void A::cbMethodB(void *ptr)
{
A* ptr = static_cast<A*> (ptr);
//get val
int tempVal = ptr->getVal();
//process val....
}
This seems like a direct application of SPOT (Single Point Of Truth), a.k.a. DRY (Don't Repeat Yourself), two names for a single important idea. You've created a function for accessing val that performs some tasks that should always go along with accessing it. Unless there is some private, implementation-specific reason to access the member field directly, you should probably use the getter method you define. That way, if you change the synchronization mechanism that protects val, you only need to update one piece of code.
I can't think of any reason why "dereferencing a mutex to lock it" would be a bad thing, repeating yourself is a bad thing.
Related
Given the following example code:
int var;
int mvar;
std::mutex mvar_mutex;
void f(){
mvar_mutex.lock();
mvar = var * var;
mvar_mutex.unlock();
}
I want to express that mvar_mutex is bound to the variable mvar and protects only that variable. mvar_mutex should not protect var because it is not bound to it. Hence the compiler would be allowed to transform the above code into the below code:
int var;
int mvar;
std::mutex mvar_mutex;
void f(){
int r = var * var; //possible data race created if binding is not known
mvar_mutex.lock();
mvar = r;
mvar_mutex.unlock();
}
This might reduce contention on the lock as less work is being done while holding it.
For int this can be done using std::atomic<int> mvar; and removing mvar_mutex, but for other types such as std::vector<int> this is not possible.
How do I express the mutex-variable binding in a way that C++ compilers understand it and do the optimization? It should be allowed to reorder any variable up or down across mutex boundaries for any variable that is not bound to that mutex
Since the code is being generated using clang::ASTConsumer and clang::RecursiveASTVisitor I am willing to use non-standard extensions and AST manipulations as long as clang (ideally clang 4.0) supports them and the resulting code does not need to be elegant or human-readable.
Edit since this seems to be causing confusion: The above transformation is not legal in C++. The described binding of mutex to variable doesn't exist. The question is about how to implement that or achieve the same effect.
If you wish to achieve that the std::mutex will only be held until an operation is performed on the protected object, you can write a wrapper class as follows:
#include <cstdio>
#include <mutex>
template<typename T>
class LockAssignable {
public:
LockAssignable& operator=(const T& t) {
std::lock_guard<std::mutex> lk(m_mutex);
m_protected = t;
return *this;
}
operator T() const {
std::lock_guard<std::mutex> lk(m_mutex);
return m_protected;
}
/* other stuff */
private:
mutable std::mutex m_mutex;
T m_protected {};
};
inline int factorial(int n) {
return (n > 1 ? n * factorial(n - 1) : 1);
}
int main() {
int var = 5;
LockAssignable<int> mvar;
mvar = factorial(var);
printf("Result: %d\n", static_cast<int>(mvar));
return 0;
}
In the example above the factorial will be calculated in advance and the m_mutex will be acquired only when the assignment or the implicit conversion operator being called on mvar.
Assembly Output
For the primitive data types you can use std::atomic with std::memory_order_relaxed.
The documentation states that:
there are no synchronization or ordering constraints imposed on other
reads or writes, only this operation's atomicity is guaranteed
In the following example, the atomicity of the assignation is guaranteed, but the compiler should be able to move the operations.
std::atomic<int> z = {0};
int a = 3;
z.store(a*a, std::memory_order_relaxed);
For objects, I thought of several solutions, but:
There is no standard way to remove ordering requirements from std::mutex.
It is not possible to create a std::atomic<std::vector>.
It is not possible to create a spinlock using std::memory_order_relaxed (see the example).
I have found some answers that state that:
If the function is not visible in the compilation unit, the compiler generates a barrier because it does not know which variables it uses.
If the function is visible and there is a mutex, the compiler generates a barrier.
For example, see this and this
So, in order to express that mvar_mutex is bound to the variable, you can use some classes as stated by the other answers but I do not think it is possible to fully allow the reordering of the code.
I want to express that mvar_mutex is bound to the variable mvar and protects only that variable.
You can't do this. A mutex actually guards the critical region of machine instructons between the acquisition and release. Only by convention is that associated with a particular instance of shared data.
To avoid doing unnecessary steps inside the critical region, keep the critical regions as simple as possible. In a critical region, only with local variables which the compiler can "see" are obviously not shared with other threads, and with one set of shared data belonging to that mutex. Try not to access other data in the critical region that might be suspected of being shared.
If you could have your proposed language feature, it would only introduce the possibility of error into a program. All it does is take code which is now correct, and make some of it incorrect (in exchange for the promise of some speed: that some code stays correct and is faster, because extraneous computations are moved out of the critical region).
It's like taking a language which already has a nice order of evaluation, in which a[i] = i++ is well defined, and screwing it up with unspecified evaluation order.
How about a locked var template ?
template<typename Type, typename Mutex = std::mutex>
class Lockable
{
public:
Lockable(_Type t) : var_(std::move(t));
Lockable(_Type&&) = default;
// ... could need a bit more
T operator = (const T& x)
{
std::lock_guard<Lockable> lock(*this);
var_ = x;
return x;
}
T operator *() const
{
std::lock_guard<Lockable> lock(*this);
return var_;
}
void lock() const { const_cast<Lockable*>(this)->mutex_.lock(); }
void unlock() const { const_cast<Lockable*>(this)->mutex_.unlock().; }
private:
Mutex mutex_;
Type var_;
};
locked by assignment operator
Lockable<int>var;
var = mylongComputation();
Works great with lock_guard
Lockable<int>var;
std::lock_guard<Lockable<int>> lock(var);
var = 3;
Practical on containers
Lockable<std::vector<int>> vec;
etc...
You can use folly::Synchronized to make sure that the variable is only accessed under a lock:
int var;
folly::Synchronized<int> vmar;
void f() {
*mvar.wlock() = var * var;
}
I want to express that mvar_mutex is bound to the variable mvar and
protects only that variable.
This is not how a mutex works. It doesn't "bind" to anything in order to protect it. You are still free to access this object directly, in complete disregard with any sort of thread safety whatsoever.
What you should do is hide away the "protected variable" so that it is not directly accessible at all, and write an interface that manipulates it that goes through the mutex. This way you ensure that access to the underlying data is protected by that mutex. It can be a single object, it can be a functional group of objects, it can be a collection of many objects, mutexes and atomics, designed to minimize blocking.
Given the following:
class ReadWrite {
public:
int Read(size_t address);
void Write(size_t address, int val);
private:
std::map<size_t, int> db;
}
In read function when accessing an address which no previous write was made to I want to either throw exception designating such error or allow that and return 0, in other words I would like to either use std::map<size_t, int>::operator[]() or std::map<size_t, int>::at(), depending on some bool value which user can set. So I add the following:
class ReadWrite {
public:
int Read(size_t add) { if (allow) return db[add]; return db.at(add);}
void Write(size_t add, int val) { db[add] = val; }
void Allow() { allow = true; }
private:
bool allow = false;
std::map<size_t, int> db;
}
The problem with that is:
Usually, the program will have one call of allow or none at the beginning of the program and then afterwards many accesses. So, performance wise, this code is bad because it every-time performs the check if (allow) where usually it's either always true or always false.
So how would you solve such problem?
Edit:
While the described use case (one or none Allow() at first) of this class is very likely it's not definite and so I must allow user call Allow() dynamically.
Another Edit:
Solutions which use function pointer: What about the performance overhead incurred by using function pointer which is not able to make inline by the compiler? If we use std::function instead will that solve the issue?
Usually, the program will have one call of allow or none at the
beginning of the program and then afterwards many accesses. So,
performance wise, this code is bad because it every-time performs the
check if (allow) where usually it's either always true or always
false. So how would you solve such problem?
I won't, The CPU will.
the Branch Prediction will figure out that the answer is most likely to be same for some long time so it will able to optimize the branch in the hardware level very much. it will still incur some overhead, but very negligible.
If you really need to optimize your program, I think your better use std::unordered_map instead of std::map, or move to some faster map implementation, like google::dense_hash_map. the branch is insignificant compared to map-lookup.
If you want to decrease the time-cost, you have to increase the memory-cost. Accepting that, you can do this with a function pointer. Below is my answer:
class ReadWrite {
public:
void Write(size_t add, int val) { db[add] = val; }
// when allowed, make the function pointer point to read2
void Allow() { Read = &ReadWrite::read2;}
//function pointer that points to read1 by default
int (ReadWrite::*Read)(size_t) = &ReadWrite::read1;
private:
int read1(size_t add){return db.at(add);}
int read2(size_t add) {return db[add];}
std::map<size_t, int> db;
};
The function pointer can be called as the other member functions. As an example:
ReadWrite rwObject;
//some code here
//...
rwObject.Read(5); //use of function pointer
//
Note that non-static data member initialization is available with c++11, so the int (ReadWrite::*Read)(size_t) = &ReadWrite::read1; may not compile with older versions. In that case, you have to explicitly declare one constructor, where the initialization of the function pointer can be done.
You can use a pointer to function.
class ReadWrite {
public:
void Write(size_t add, int val) { db[add] = val; }
int Read(size_t add) { (this->*Rfunc)(add); }
void Allow() { Rfunc = &ReadWrite::Read2; }
private:
std::map<size_t, int> db;
int Read1(size_t add) { return db.at(add); }
int Read2(size_t add) { return db[add]; }
int (ReadWrite::*Rfunc)(size_t) = &ReadWrite::Read1;
}
If you want runtime dynamic behaviour you'll have to pay for it at runtime (at the point you want your logic to behave dynamically).
You want different behaviour at the point where you call Read depending on a runtime condition and you'll have to check that condition.
No matter whether your overhad is a function pointer call or a branch, you'll find a jump or call to different places in your program depending on allow at the point Read is called by the client code.
Note: Profile and fix real bottlenecks - not suspected ones. (You'll learn more if you profile by either having your suspicion confirmed or by finding out why your assumption about the performance was wrong.)
I have a very similiar question asked already 2012.
Critical Sections and return values in C++
I'd like to access a container thread safe aswell but instead return a cached version by reference.
struct Container {
const Data& getSomeData() const {
EnterCriticalSection(& myCritSec);
if (update) {
cache.calulatefromcontainer();
}
// fill retobj with data from structure
LeaveCriticalSection(& myCritSec);
return cache;
}
private:
mutable Data cache;
};
The problem is, that "return cache" line isn't protected anymore. Is it possible to return "cache" thread safe by reference?
You have to think what your critical section is actually protecting.
In your code, it looks like myCritSec is protecting the container. But notably, it is not protecting the cache member variable. That is not because the return cache; line but because you are returning a reference to it, so it could be used unrestricted by client code while other thread calls getSomeData() again and modifies it.
One solution would be to return a copy of the data.
Another solution would be that every public function usable to get information from Data will somehow use the myCritSec of the parent container. The problem with this approach is that it would be very easy to fall into races. For example:
class Data
{
public:
int getA() const
{
int res;
EnterCriticalSection(parentCS);
res = getAunlocked();
LeaveCriticalSection(parentCS);
return res;
}
int getB() const
{
int res;
EnterCriticalSection(parentCS);
res = getBunlocked();
LeaveCriticalSection(parentCS);
return res;
}
};
And then in the user code:
const Data &data = container.getSomeData();
if (data.getA() == data.getB()) // <--- RACE!!!
{
}
Since the call to getA() and getB() are each locking and unlocking the CS, another thread might modify the data just in between and create a race condition.
Trying to learn something new every day I'd be interested if the following is good or bad design.
I'm implementing a class A that caches objects of itself in a static private member variable std::map<> cache. The user of A should only have access to pointers to elements in the map, because a full copy of A is expensive and not needed. A new A is only created if it is not yet available in the map, as construction of A needs some heavy lifting. Ok, here's some code:
class B;
class A {
public:
static A* get_instance(const B & b, int x) {
int hash = A::hash(b,x);
map<int, A>::iterator found = cache.find(hash);
if(found == cache.end())
found = cache.insert(make_pair(hash, A(b,x))).first;
return &(found->second);
}
static int hash(B & b, int x) {
// unique hash function for combination of b and x
}
// ...
private:
A(B & b, int x) : _b(b), _x(x) {
// do some heavy computation, store plenty of results
// in private members
}
static map<int, A> cache;
B _b;
int _x; // added, so A::hash() makes sense (instead of B::hash())
// ...
};
Is there anything that is wrong with the code above? Are there any pitfalls,
do I miss memory management problems or anything else?
Thank you for your feedback!
The implementation is intended to only allow you to create items via get_instance(). You should ideally make your copy-constructor and assignment operator private.
It would not be thread-safe. You can use the following instead:
const boost::once_flag BOOST_ONCE_INIT_CONST = BOOST_ONCE_INIT;
struct AControl
{
boost::once_flag onceFlag;
shared_ptr<A> aInst;
void create( const B&b, int x )
{
aInst.reset( new A(b, x) );
}
AControl() : onceFlag( BOOST_ONCE_INIT_CONST )
{
}
A& get( const B&b, int x )
{
boost::call_once( onceFlag, bind( &AOnceControl::create, this, b, x ) );
return *aInst;
}
};
Change the map to
map
Have a mutex and use it thus:
AControl * ctrl;
{
mutex::scoped_lock lock(mtx);
ctrl = &cache[hash];
}
return ctrl->get(b,x);
Ideally only get_instance() will be static in your class. Everything else is private implementation detail and goes into the compilation unit of your class, including AControl.
Note that you could do this a lot simpler by just locking through the entire process of looking up in the map and creating but then you are locking for longer whilst you do the long construction process. As it is this implements record-level locking once you have inserted the item. A later thread may find the item uninitialised but the boost::once logic will ensure it is created exactly once.
Any time you use globals (in this case the static map) you have to worry about concurrency issues if this is used across multiple threads. For example, if two threads were trying to get a particular instance at once, they could both create an object resulting in duplicates. Even worse, if they both tried to update the map at the same time it could get corrupted. You'd have to use mutexes to control access to the container.
If it's single-threaded only then there's no issue until someone decides it needs to be made multi-threaded in the future.
Also as a style note, while names starting with underscore+lower case letter are technically legal, avoid any symbols starting with underscores will avoid possibly accidentally breaking the rules and getting weird behavior.
I think these are 3 separate things that you mix together inside A:
the class A itself (what its intances are supposed to do).
poolling of instances for cache purposes
having such a static singlton pool for a certain type
I think they should be separate in the code, not all together inside A.
That means:
write your class A without any consideration of how it should be allocated.
write a generic module to perform pool cache of objects, along the lines of:
*
template< typename T > class PoolHashKey { ... };
template< typename T > class PoolCache
{
//data
private: std::map< .... > map_;
//methods
public: template< typename B > PoolKey< T > get_instance( B b );
public: void release_instance( PoolKey< T > );
// notice that these aren't static function members
};
create a singleton instance of PoolCache somewhere and use it:
*
PoolCache<A>& myAPool()
{
static PoolCache<A> s;
return s;
//you should use some safe singleton idiom.
}
int main()
{
B b;
PoolKey<A> const aKey( myAPool().get_instance( b );
A* const a( aKey.get() );
//...
myAPool().release_instance( aKey ); //not using it anymore
/*or else the destructor of PoolKey<A> should probably do some reference count and let the pool know this instace isn't needed anymore*/
}
I just got burned by a bug that is partially due to my lack of understanding, and partially due to what I think is suboptimal design in our codebase. I'm curious as to how my 5-minute solution can be improved.
We're using ref-counted objects, where we have AddRef() and Release() on objects of these classes. One particular object is derived from the ref-count object, but a common function to get an instance of these objects (GetExisting) hides an AddRef() within itself without advertising that it is doing so. This necessitates doing a Release at the end of the functional block to free the hidden ref, but a developer who didn't inspect the implementation of GetExisting() wouldn't know that, and someone who forgets to add a Release at the end of the function (say, during a mad dash of bug-fixing crunch time) leaks objects. This, of course, was my burn.
void SomeFunction(ProgramStateInfo *P)
{
ThreadClass *thread = ThreadClass::GetExisting( P );
// some code goes here
bool result = UseThreadSomehow(thread);
// some code goes here
thread->Release(); // Need to do this because GetExisting() calls AddRef()
}
So I wrote up a little class to avoid the need for the Release() at the end of these functions.
class ThreadContainer
{
private:
ThreadClass *m_T;
public:
ThreadContainer(Thread *T){ m_T = T; }
~ThreadContainer() { if(m_T) m_T->Release(); }
ThreadClass * Thread() const { return m_T; }
};
So that now I can just do this:
void SomeFunction(ProgramStateInfo *P)
{
ThreadContainer ThreadC(ThreadClass::GetExisting( P ));
// some code goes here
bool result = UseThreadSomehow(ThreadC.Thread());
// some code goes here
// Automagic Release() in ThreadC Destructor!!!
}
What I don't like is that to access the thread pointer, I have to call a member function of ThreadContainer, Thread(). Is there some clever way that I can clean that up so that it's syntactically prettier, or would anything like that obscure the meaning of the container and introduce new problems for developers unfamiliar with the code?
Thanks.
use boost::shared_ptr
it is possible to define your own destructor function, such us in next example: http://www.boost.org/doc/libs/1_38_0/libs/smart_ptr/sp_techniques.html#com
Yes, you can implement operator ->() for the class, which will recursively call operator ->() on whatever you return:
class ThreadContainer
{
private:
ThreadClass *m_T;
public:
ThreadContainer(Thread *T){ m_T = T; }
~ThreadContainer() { if(m_T) m_T->Release(); }
ThreadClass * operator -> () const { return m_T; }
};
It's effectively using smart pointer semantics for your wrapper class:
Thread *t = new Thread();
...
ThreadContainer tc(t);
...
tc->SomeThreadFunction(); // invokes tc->t->SomeThreadFunction() behind the scenes...
You could also write a conversion function to enable your UseThreadSomehow(ThreadContainer tc) type calls in a similar way.
If Boost is an option, I think you can set up a shared_ptr to act as a smart reference as well.
Take a look at ScopeGuard. It allows syntax like this (shamelessly stolen from that link):
{
FILE* topSecret = fopen("cia.txt");
ON_BLOCK_EXIT(std::fclose, topSecret);
... use topSecret ...
} // topSecret automagically closed
Or you could try Boost::ScopeExit:
void World::addPerson(Person const& aPerson) {
bool commit = false;
m_persons.push_back(aPerson); // (1) direct action
BOOST_SCOPE_EXIT( (&commit)(&m_persons) )
{
if(!commit)
m_persons.pop_back(); // (2) rollback action
} BOOST_SCOPE_EXIT_END
// ... // (3) other operations
commit = true; // (4) turn all rollback actions into no-op
}
I would recommend following bb advice and using boost::shared_ptr<>. If boost is not an option, you can take a look at std::auto_ptr<>, which is simple and probably addresses most of your needs. Take into consideration that the std::auto_ptr has special move semantics that you probably don't want to mimic.
The approach is providing both the * and -> operators together with a getter (for the raw pointer) and a release operation in case you want to release control of the inner object.
You can add an automatic type-cast operator to return your raw pointer. This approach is used by Microsoft's CString class to give easy access to the underlying character buffer, and I've always found it handy. There might be some unpleasant surprises to be discovered with this method, as in any time you have an implicit conversion, but I haven't run across any.
class ThreadContainer
{
private:
ThreadClass *m_T;
public:
ThreadContainer(Thread *T){ m_T = T; }
~ThreadContainer() { if(m_T) m_T->Release(); }
operator ThreadClass *() const { return m_T; }
};
void SomeFunction(ProgramStateInfo *P)
{
ThreadContainer ThreadC(ThreadClass::GetExisting( P ));
// some code goes here
bool result = UseThreadSomehow(ThreadC);
// some code goes here
// Automagic Release() in ThreadC Destructor!!!
}