I have a C++ library, which supposed to do some computations on multiple threads. I made independent threads code (i.e. there are no shared variables between them), except for one array. The problem is, I don't know how to make it thread-safe.
I looked at mutex lock/unlock (QMutex, as I'm using Qt), but it doesn't fit for my task - while one thread will lock the mutex, other threads will wait!
Then I read about std::atomic, which looked like exactly what I needed. Nevertheless, I tried to use it in the following way:
std::vector<std::atomic<uint64_t>> *myVector;
And it produced compiler error (use of deleted function 'std::atomic::atomic(const std::atomic&)'). Then I found the solution - use special wrapper for std::atomic. I tried this:
struct AtomicUInt64
{
std::atomic<uint64_t> atomic;
AtomicUInt64() : atomic() {}
AtomicUInt64 ( std::atomic<uint64_t> a ) : atomic ( atomic.load() ) {}
AtomicUInt64 ( AtomicUInt64 &auint64 ) : atomic ( auint64.atomic.load() ) {}
AtomicUInt64 &operator= ( AtomicUInt64 &auint64 )
{
atomic.store ( auint64.atomic.load() );
}
};
std::vector<AtomicUInt64> *myVector;
This thing compiles succesfully, but when I can't fill the vector:
myVector = new std::vector<AtomicUInt64>();
for ( int x = 0; x < 100; ++x )
{
/* This approach produces compiler error:
* use of deleted function 'std::atomic<long long unsigned int>::atomic(const std::atomic<long long unsigned int>&)'
*/
AtomicUInt64 value( std::atomic<uint64_t>( 0 ) ) ;
myVector->push_back ( value );
/* And this one produces the same error: */
std::atomic<uint64_t> value1 ( 0 );
myVector->push_back ( value1 );
}
What am I doing wrong? I assume I tried everything (maybe not, anyway) and nothing helped. Are there any other ways for thread-safe array sharing in C++?
By the way, I use MinGW 32bit 4.7 compiler on Windows.
Here is a cleaned up version of your AtomicUInt64 type:
template<typename T>
struct MobileAtomic
{
std::atomic<T> atomic;
MobileAtomic() : atomic(T()) {}
explicit MobileAtomic ( T const& v ) : atomic ( v ) {}
explicit MobileAtomic ( std::atomic<T> const& a ) : atomic ( a.load() ) {}
MobileAtomic ( MobileAtomic const&other ) : atomic( other.atomic.load() ) {}
MobileAtomic& operator=( MobileAtomic const &other )
{
atomic.store( other.atomic.load() );
return *this;
}
};
typedef MobileAtomic<uint64_t> AtomicUInt64;
and use:
AtomicUInt64 value;
myVector->push_back ( value );
or:
AtomicUInt64 value(x);
myVector->push_back ( value );
your problem was you took a std::atomic by value, which causes a copy, which is blocked. Oh, and you failed to return from operator=. I also made some constructors explicit, probably needlessly. And I added const to your copy constructor.
I would also be tempted to add store and load methods to MobileAtomic that forwards to atomic.store and atomic.load.
You're trying to copy a non-copyable type: the AtomicUInt64 constructor takes an atomic by value.
If you need it to be initialisable from atomic, then it should take the argument by (const) reference. However, in your case, it doesn't look like you need to initialise from atomic at all; why not initialise from uint64_t instead?
Also a couple of minor points:
The copy constructor and assignment operator should take their values by const reference, to allow temporaries to be copied.
Allocating the vector with new is a rather odd thing to do; you're just adding an extra level of indirection with no benefit.
Make sure you never resize the array while other threads might be accessing it.
This line
AtomicUInt64 ( std::atomic<uint64_t> a ) : atomic ( atomic.load() ) {}
You're completely ignoring the argument you pass in, You probably want it to be a.load() and you probably want to take elements by const reference so they aren't copied.
AtomicUInt64 (const std::atomic<uint64_t>& a) : atomic (a.load()) {}
As for what you're doing, I'm not sure if it is correct. The modification of the variables inside the array will be atomic, but if the vector is modified or reallocated (which is possible with push_back), then there's nothing to guarantee your array modifications will work between threads and be atomic.
Related
This question already has answers here:
What is move semantics?
(11 answers)
Closed 2 years ago.
Consider the following code:
class c
{
large_type_t i;
public:
// the most simple variant
c( large_type_t i ): i( i ) { }
// move the parameter copied
c( large_type_t i ): i( std::move( i ) ) { }
// copy is done directly in interaction with our class member from original
c( const large_type_t &i ): i( i ) { }
// parameter was constructed in the call, just treat as rvalue
c( large_type_t &&i ): i( std::move( i ) ) { }
// this is here just to show all possible combinations in case someone in the future sees this question and someone answering it wants to explain everything
c( large_type_t &&i ): i( i ) { }
};
What is the best way to do this? Are these all going to boil down to the same code anyway and it doesn't matter? I feel that I am fundamentally not understanding the purpose of move.
Move constructors (or move assignments) provide the means for your program to avoid spending excessive time copying the contents of one object to another, if the copied-from object will no longer be used afterwards. For example, when an object is to be the returned value of a method or function.
This is more obvious when you have an object with, say, dynamically allocated content.
Example:
class MyClass {
private:
size_t _itemCount ;
double * _bigBufferOfDoubles ;
public:
// ... Initial contructor, creating a big list of doubles
explicit MyClass( size_t itemCount ) {
_itemCount = itemCount ;
_bigBufferOfDoubles = new double[ itemCount ];
}
// ... Copy constructor, to be used when the 'other' object must persist
// beyond this call
MyClass( const MyClass & other ) {
//. ... This is a complete copy, and it takes a lot of time
_itemCount = other._itemCount ;
_bigBufferOfDoubles = new double[ _itemCount ];
for ( int i = 0; i < itemCount; ++i ) {
_bigBufferOfDoubles[ i ] = other. _bigBufferOfDoubles[ i ] ;
}
}
// ... Move constructor, when the 'other' can be discarded (i.e. when it's
// a temp instance, like a return value in some other method call)
MyClass( MyClass && other ) {
// ... Blazingly fast, as we're just copying over the pointer
_itemCount = other._itemCount ;
_bigBufferOfDoubles = other._bigBufferOfDoubles ;
// ... Good practice to clear the 'other' as it won't be needed
// anymore
other._itemCount = 0 ;
other._bigBufferOfDoubles = null ;
}
~MyClass() {
delete [] _bigBufferOfDoubles ;
}
};
// ... Move semantics are useful to return an object 'by value'
// Since the returned object is temporary in the function,
// the compiler will invoke the move constructor of MyClass
MyClass someFunctionThatReturnsByValue() {
MyClass myClass( 1000000 ) ; // a really big buffer...
return myClass ; // this will call the move contructor, NOT the copy constructor
}
// ... So far everything is explicitly handled without an explicit
// call to std::move
void someOtherFunction() {
// ... You can explicitly force the use of move semantics
MyClass myTempClass( 1000000 ) ;
// ... Say I want to make a copy, but I don't want to invoke the
// copy contructor:
MyClass myOtherClass( 1 ) ;
myOtherClass = std::move( myTempClass ) ;
// ... At this point, I should abstain from using myTempClass
// as its contents have been 'transferred' over to myOtherClass.
}
What is the best way to do this?
The simplest variant. The reason: Because it is the simplest variant.
Trivial types do not have copy constructors nor move constructors, and "moving" them is same as copying.
Are these all going to boil down to the same code anyway and it doesn't matter?
If optimisation and in particular inline expansion is involved, then probably yes. You can verify whether that is the case for your program by comparing the resulting assembly. Assuming no (or poor) optimisation, the simplest variant is potentially fastest.
Regarding your edit: For non-trivial types, the second variant is best because it moves from rvalue arguments instead of copying.
All of those are different and it very much depends on what large_type_t i; is.
Does it manage dynamically allocated data? If yes and it supports both moving and copy construction then following two constuctors should be used:
c( const large_type_t &i ): mi( i ) { };
c( large_type_t &&i ): mi( std::move( i ) ) {};
Although, it is potentially a mildly less efficient way, but you can use a single constructor for both purposes:
c( large_type_t i): mi( std::move( i ) ) { };
For the above, without std::move it will likely result in unnecessary copying and memory allocations.
If it doesn't manage any dynamically allocated data - then usually moving/copying is the same thing (for exotic types figure it yourself since it's too dependent on circumstances). Thus you only need copy constructor:
c( const large_type_t &i ): mi( i ) { };
For small trivial types, you'd better use the most basic form:
c( small_type_t i ): mi( i ) { };
I have a std::vector<Enemy*> enemies and when i create a new Enemy i do enemies.push_back(this). This works for what i'm doing, but i'm wondering if there is a way to have the vector not need pointers to the enemies. I've tried just std::vector<Enemy> but it seems to cause a bunch of problems i can't figure out.
ie. - had to change to enemies.push_back(*this), and it caused some linker errors for some reason.
looping through with the following works, but removing the pointers creates issues:
void Enemy::updateEnemies(sf::RenderWindow &window) {
for(std::vector<Enemy*>::iterator it = enemies.begin(); it < enemies.end(); it++) {
(*it)->update(window);
}
}
Wondering if someone could point me in the direction of using a vector without pointers and loop through it, updating the objects inside it with the same function..
everbody is saying it in comments - but its the answer
use smart pointers
if you dont know how to do that then google
You life is much easier, safer, faster,...
And they are really easy to use - the main trick with using them is to trust them and dont try to get clever or 'help' them
My practice is to make sure the class implements (and makes public) all of the following: a default constructor, a copy constructor, an assignment operator, and a destructor. Then there's no problem with things like std::vector<Enemy>. (The default constructor isn't even necessary for vectors, but can be handy for various other things.)
One caveat, though: when you push_back() an Enemy into your vector, it's actually a copy of the original instance that gets stored. This raises a few gotchas: first, changes to the original (e.g. to the member data of the variable e in the main() scope of my example below) will not affect the copy stored in the vector. If you're accustomed to working with vectors-of-pointers, this may be surprising. Second, the implicit construction of copies and the copying of member data will take time, which may or may not have a significant effect on performance. Third, implicit construction and copying may trigger side-effects (you should simply avoid these in your design, wherever possible).
Here's an example:
#include <vector>
#include <iostream>
class Enemy
{
public:
Enemy() : mEvilness( 1 ) {} // default (i.e. parameterless) constructor
Enemy( const Enemy& other ) { Copy( other ); } // copy constructor
Enemy& operator=( const Enemy& other ) { return Copy( other ); } // assignment operator
~Enemy() {} // destructor
Enemy( int evilness ) : mEvilness( evilness ) {} // standard constructor
void Gloat( void ) const
{
std::cout << "muahaha";
for( int i = 0; i < mEvilness; i++ ) std::cout << "ha";
std::cout << "!\n";
}
int mEvilness;
private:
// common helper method for copy constructor and assignment operator:
Enemy& Copy( const Enemy& other )
{
mEvilness = other.mEvilness; // make copies of any other member data here
return *this;
}
};
typedef std::vector< Enemy > EnemyHorde;
void AllGloat1( const EnemyHorde& h ) // doesn't matter if you pass by reference...
{
for( EnemyHorde::const_iterator it = h.begin(); it != h.end(); it++ )
it->Gloat();
}
void AllGloat2( EnemyHorde h ) // ...or value (but this will take more CPU time)
{
for( EnemyHorde::const_iterator it = h.begin(); it != h.end(); it++ )
it->Gloat();
}
int main( int argc, const char* argv[] )
{
EnemyHorde h;
Enemy e( 1 );
h.push_back( e );
h.push_back( Enemy( 2 ) ); // even transient Enemy instances get copied and stored
h.push_back( Enemy( 3 ) );
AllGloat1( h );
std::cout << "\n";
e.mEvilness++; // this will have no effect on the output because h contains a *copy* of e
AllGloat2( h );
return 0;
}
If you want a well-founded answer you have to go one step back - to the design. As far as i see the Enemy objects are registering themselves via constructor in a kind of global list. So far so good.
But how these object are produced ? In this example in Enemy can be construct everywhere
On the stack as local
By new (smartpointer)
As an element in a vector, list, deque ...
...
Depending on this, the Enemy-object cant do any reliable statements about its storage. But one thing that all objects share and what is always accessible from inside the object - is the address ('this'). So the solution via pointer is the only solution that is universal for all constructed Enemy-objects. (References are in this context also "a kind of pointer", and other more complicate constructs may also rely on pointers).
A std::vector cant work because you get 2 different objects. To change one of them does not effect the other. That wont work. And it is not possible to switch to smart pointers without changing your design.
There are 2 common solutions:
Managing the listing from 'inside' Enemy in a generally way like in the given example. Expandable with more features like auto delete entries via destructor.....
Managing the listing from 'outside'. Enemy-objects dont register themselves, the generator of the Enemy-objects is responsible for to do it proper (the design pattern 'factory' is a good solution in this case). And you can use smart pointers what is a good idea in most cases.
There are also some more solutions (including some good solutions) unmentioned, they exceed the scope of the question.
You don't need pointers (most of the time) in C++.
A copy will be made when using the std::vector::push_back() method.
Example:
Enemy evil_wizard;
std::vector<Enemy> enemy_container;
enemy_container.push_back(evil_wizard);
Enemy Evil_knight;
enemy_container.push_back(Evil_knight);
Enemy pink_elephant;
enemy_container.push_back(pink_elephant);
My method can return some kind of pointer ( for example boost::shared_ptr ) and this pointer may be NULL. Is there is any way to enforce users of my code to check, if it is empty or not ?
Some example of such things - scals's Option container, may be boost has something like boost::option ?
You can do the following:
return a smart pointer type that throws an exception if accessed and set to NULL.
throw an exception instead of returning a NULL pointer
return a std::optional (or boost::optional) which expresses intent (i.e. "value may be missing") much better than a pointer
The usual solution is to wrap the return value in a class, which
contains a flag which is set if the pointer is checked or
copied, and whose destructor crashes if the flag wasn't set.
Something like:
template <typename T>
class MustBeChecked
{
T* myValue;
mutable bool myHasBeenChecked;
public:
MustBeChecked( T* value )
: myValue( value )
, myHasBeenChecked( false )
{
}
MustBeChecked( MustBeChecked const& other )
: myValue( other.myValue )
, myHasBeenChecked( false )
{
other.myHasBeenChecked = true;
}
~MustBeChecked()
{
assert( myHasBeenChecked );
}
bool operator==( nullptr_t ) const
{
myHasBeenChecked = true;
return myValue == nullptr;
}
bool operator!=( nullptr_t ) const
{
myHasBeenChecked = true;
return myValue != nullptr;
}
operator T*() const
{
assert( myHasBeenChecked );
return myValue;
}
};
To be frank, I find this to be overkill in most cases. But I've
seen it used on some critical systems.
The reality here is that the callers of your function already have to check. If they try to access the shared pointer without checking, then a seg-fault is coming their way if the underlying pointer is NULL.
You don't specify if you're writing a library, or some code within a project. Nor do you specify any details of the context this code lives in -- all of these might decide which approach I'd take in this situation -- but broadly speaking, all of utnapistim's suggestions are good ones.
Weak pointers are like smartpointers, except that references from weak
pointers do not prevent garbage collection, and weak pointers must
have their validity checked before they are used.
In our project (Linderdaum Engine http://www.linderdaum.com) we use intrusive pointers. To avoid circular references and islands of isolation we have implemented weak intrusive pointers the following way:
namespace LPtr
{
clPtr<iObject> GetObjectsGraphPtrWrapper( sEnvironment* Env, iObject* Obj, size_t Generation );
};
/// Intrusive weak smart pointer
template <class T> class clWeakPtr
{
public:
/// default constructor
clWeakPtr(): Env( NULL ), FObject( NULL ), FGeneration( 0 ) {}
explicit clWeakPtr( T* Ptr )
: Env( Ptr ? Ptr->Env : NULL )
, FObject( Ptr )
, FGeneration( Ptr ? Ptr->FGeneration : 0 ) {}
explicit clWeakPtr( const clPtr<T>& Ptr )
: Env( Ptr ? Ptr->Env : NULL )
, FObject( Ptr.GetInternalPtr() )
, FGeneration( Ptr ? Ptr->FGeneration : 0 ) {}
clPtr<T> Lock() const
{
clPtr<iObject> P = LPtr::GetObjectsGraphPtrWrapper( Env, FObject, FGeneration );
return P.DynamicCast<T>();
}
private:
sEnvironment* Env;
T* FObject;
size_t FGeneration;
};
GetObjectsGraphPtrWrapper is here just for the sake of forward declarations and does roughly this:
LMutex Lock( &FObjectsGraphMutex );
clObjectsGraph::const_iterator i = std::find( Env->ObjectsGraph.begin(), Env->ObjectsGraph.end(), Obj );
if ( i == Env->ObjectsGraph.end() ) return clPtr<iObject>();
bool IsSame = Obj->FGeneration == Generation;
bool IsAlive = Obj->GetReferenceCounter() > 0;
return ( IsSame && IsAlive ) ? clPtr<iObject>( Obj ) : clPtr<iObject>();
Generation is global in the scope of sEnvironment and is atomic-incremented every time a new object is instantiated.
My questions are:
1) Is it safe to implement weak-references like this?
2) Are there any ways to optimize the clWeakPtr::Lock()?
1) It seems safe indeed, but any modification of the graph will have some contention with LPtr::GetObjectsGraphPtrWrapper
2) a read-write lock could help, at least you'll be able to call several Lock() in parallel
The problem with your solution is that it defeats the locality that non-intrusive weak pointers bring.
Depending on the concurrency level, it might become a problem as each call to Lock() will prevent any object creation and as well any other Lock() call without a read-write lock.
I have been working on replacing raw pointers with reference-counted pointers that expose only a const version of the underlying one. My objective is to reduce memory usage (and time spent unnecessarily constructing and destructing complex objects) without putting myself in a situation where any code has access to memory that it does not own. I am aware of the circular reference problem with reference counting, but my code should never create such a situation.
Requiring const-ness works because I am using a system in which classes generally expose no non-const members, and rather than altering an object you must call a method on it that returns a new object that results from the alteration. This is probably a design pattern, but I do not know it by name.
My problem has come when I have a method that returns pointer to an object of its type, which is sometimes itself. Previously it looked something like this:
Foo * Foo::GetAfterModification( const Modification & mod ) const
{
if( ChangesAnything( mod ) )
{
Foo * asdf = new Foo;
asdf.DoModification( mod );
return asdf;
}
else
return this;
}
I cannot see a good way to make this return a smart pointer. The naive approach would be something like return CRcPtr< Foo >( this ), but this breaks the ownership semantics because what I am returning and whomever previously owned the object now each think they have ownership but do not know about each other. The only safe thing to do would be return CRcPtr< Foo >( new Foo( *this ) ), but that defeats my intention of restricting unnecessary memory use.
Is there some way to safely return a smart pointer without allocating any additional memory? My suspicion is that there is not. If there were, how would it work if the object had been allocated on the stack? This question seems related, but is not the same because he can just make his functions take raw pointers as parameters and because he is using the boost library.
For reference, my home-rolled smart pointer implementation is below. I am sure it could be more robust, but it is more portable than depending on boost or tr1 being available everywhere, and until this issue it has worked well for me.
template <class T>
class CRcPtr
{
public:
explicit CRcPtr( T * p_pBaldPtr )
{
m_pInternal = p_pBaldPtr;
m_iCount = new unsigned short( 1 );
}
CRcPtr( const CRcPtr & p_Other )
{ Acquire( p_Other ); }
template <class U>
explicit CRcPtr( const CRcPtr< U > & p_It )
{
m_pInternal = dynamic_cast< T * >( p_It.m_pInternal );
if( m_pInternal )
{
m_iCount = p_It.m_iCount;
(*m_iCount)++;
}
else
m_iCount = new unsigned short( 1 );
}
~CRcPtr()
{ Release(); }
CRcPtr & operator=( const CRcPtr & p_Other )
{
Release();
Acquire( p_Other );
}
const T & operator*() const
{ return *m_pInternal; }
const T * operator->() const
{ return m_pInternal; }
const T * get() const
{ return m_pInternal; }
private:
void Release()
{
(*m_iCount)--;
if( *m_iCount == 0 )
{
delete m_pInternal;
delete m_iCount;
m_pInternal = 0;
m_iCount = 0;
}
}
void Acquire( const CRcPtr & p_Other )
{
m_pInternal = p_Other.m_pInternal;
m_iCount = p_Other.m_iCount;
(*m_iCount)++;
}
template <class U>
friend class CRcPtr;
T * m_pInternal;
unsigned short * m_iCount;
};
template <class U, class T>
CRcPtr< U > ref_cast( const CRcPtr< T > & p_It )
{ return CRcPtr< U >( p_It ); }
Edit: Thanks for the replies. I was hoping to avoid using boost or tr1, but I recognize that not using well tested libraries is generally unwise. I am fairly sure that what I have implemented is not similar to std::auto_ptr, but rather is similar to tr1::shared_ptr except that it only exposes a const version of the internal pointer and lacks some of the features in the official version. I really would like to avoid an intrusive scheme like the one proposed by Gian Paolo. I am aware that my implementation is not threadsafe, but this is a single-threaded application.
Take a look at the source for Boost shared pointers. If you derive a class from enable_shared_from_this<T>, you can then call the shared_from_this() member function to do that sort of thing.
As far as semantics go, the great thing about immutability is that you can safely share data between objects, threads, and not have to worry about people changing values you depend on. You shouldn't need to worry about ownership so long as your refcounting scheme is correct (I didn't read yours, but use Boost anyway).
As eluded to by Ferruccio, you need some form of shared pointer. Ie, one that can be shared (safely!) between multiple objects. One way to make this work is to derive all your objects (at least those that are intended for use with the shared pointer) from a class that implements the actual reference count. That way, the actual pointer itself carries the current count with it, and you share the pointer between as many different objects as you like.
What you currently have is very similar to std::auto_ptr and you are bumping into the same issues with ownership. Google it and you should find some useful info.
Be aware that there are additional complications with shared pointers: in particular in multi-threaded environments your reference counting must be atomic and self assignment must be handled to avoid incrementing the internal count such that the object is never destroyed.
Again google is your friend here. Just look for info on shared pointers in C++ and you'll find tonnes of info.