A& instA1()
{
static A a;
a.init();
return a;
}
A& instA2()
{
static A a = [](){
A a = new A();
a.init();
return a;
}();
return a;
}
about use
// thread1
A& a1 = instA1();
A& a2 = instA2();
// thread2
A& a1 = instA1();
A& a2 = instA2();
**A::init() is not a multithread safe fun. **
In C++11, about get a single A, the instA1 is multithread not safe , and ** instA2 is multithread safe?**
Related
I am trying to construct a child class object from a base class object. I have tried the below code.
class A
{
public:
A();
A(A&& objectName) = default;
virtual void setint(int i);
virtual void getint();
int var;
};
class B: public A
{
public:
virtual void getint();
B(A&& objectName);
int j= 20;
};
A::A()
{
}
void A::setint(int i)
{
var = i;
}
void A::getint()
{
qDebug()<<"From A Var"<<var;
}
void B::getint()
{
qDebug()<<"From B j"<<j;
qDebug()<<"From B Var"<<var;
}
B::B(A&& objectName): A(std::move(objectName))
{
}
And in my Main.cpp I am doing this
#include <memory>
int main(int argc, char *argv[])
{
A *obj = new A();
obj->setint(10);
obj->getint();
A *obj1 = new B(std::move(*obj));
obj->getint();
obj1->getint();
return 0;
}
The result I get is
From A Var 10
From A Var 10
From B j 20
From B Var 10
My question is why am I getting the value of Var after A *obj1 = new B(std::move(*obj)); this line. I thought the object pointed by obj must have been destructed.
Let me copy paste from this answer: https://stackoverflow.com/a/15663912/512225
std::move doesn't move from the object. It just returns an rvalue reference whose referand is the object, making it possible to move from the object.
Anyway your code is terrible. I hope you know. If you don't, ask for a review.
class test
{
void thread1()
{
int i = 0;
while(true){
for(unsigned int k = 0;k < mLD.size(); k++ )
{
mLD[k] = i++;
}
}
}
void thread2()
{
std::cout << "thread2 address : " << &mLD << "\n";
C();
}
void B()
{
std::cout << "B address : " << &mLD << "\n";
for(unsigned int k = 0;k < mLD.size(); k++ )
{
if(mLD[k]<=25)
{
}
}
}
void C()
{
B();
std::cout << "C address : " << &mLD << "\n";
double distance = mLD[0]; // <---- segmetation fault
}
std::array<double, 360> mLD;
};
cout result --->
thread2 address : 0x7e807660
B address : 0x7e807660
C address : 0x1010160 (sometimes 0x7e807660 )
Why mLD's address changed ....?
even i change std::array to std::array<std::atomic<double>360>, the result is the same.
Most probably, the object you referred is destroyed at the point of call to C, which points to a synchronization issue. You need to extend the lifetime of the object referred by thread(s), until the threads done executing their routine. To accomplish this, you can have something like this;
#include <thread>
#include <array>
#include <iostream>
struct foo{
void callback1(){
for(auto & elem: storage){
elem += 5;
}
}
void callback2(){
for(const auto & elem: storage){
std::cout << elem << std::endl;
}
}
std::array<double, 300> storage;
};
int main(void){
foo f;
std::thread t1 {[&f](){f.callback1();}};
std::thread t2 {[&f](){f.callback2();}};
// wait until both threads are done executing their routines
t1.join();
t2.join();
return 0;
}
The instance of foo, f lives in scope of main() function, so its' lifetime is defined by from the line it defined to end of the main's scope. By joining both threads, we block main from proceeding further until both threads are done executing their callback functions, hence the lifetime of f extended until callbacks are done.
The second issue is, the code needs synchronization primitives, because storage variable is shared between two independent execution paths. The final code with proper synchronization can look like this;
#include <thread>
#include <array>
#include <iostream>
#include <mutex>
struct foo{
void callback1(){
// RAII style lock, which invokes .lock() upon construction, and .unlock() upon destruction
// automatically.
std::unique_lock<std::mutex> lock(mtx);
for(auto & elem: storage){
elem += 5;
}
}
void callback2(){
std::unique_lock<std::mutex> lock(mtx);
for(const auto & elem: storage){
std::cout << elem << std::endl;
}
}
std::array<double, 300> storage;
// non-reentrant mutex
mutable std::mutex mtx;
};
int main(void){
foo f;
std::thread t1 {[&f](){f.callback1();}};
std::thread t2 {[&f](){f.callback2();}};
// wait until both threads are done executing their routines
t1.join();
t2.join();
return 0;
}
I'm trying to copy an object back from the device to host, and it works, but if the object contains a pointer to something i can't find the right way of calling cudaMemcpy.
This is a simplified code to show what i'm trying to do. The cudaMemcpy returns with cudaSuccess but the temp variable stays "empty".
class A {
public:
int *s;
};
__global__ void MethodA(A *a) {
printf("%d\n", a->s[2]);
}
int main() {
A *a = new A();
int asd[] = { 0, 1, 2, 3, 4 };
a->s = asd;
A *d_a;
cudaMalloc((void**)&d_a, sizeof(A));
cudaMemcpy(d_a, a, sizeof(A), cudaMemcpyHostToDevice);
int * temp;
cudaError e;
e = cudaMalloc((void**)&temp, sizeof(int) * 5);
e = cudaMemcpy(temp, a->s, sizeof(int) * 5, cudaMemcpyHostToDevice);
e = cudaMemcpy(&(d_a->s), &temp, sizeof(int*), cudaMemcpyHostToDevice);
MethodA << <1, 1 >> > (d_a);
cudaMemcpy(a, d_a, sizeof(A), cudaMemcpyDeviceToHost);
e = cudaMemcpy(&temp, a->s, sizeof(int) * 5, cudaMemcpyDeviceToHost);
a->s = temp;
cudaFree(d_a);
delete(a);
return 0;
}
The problem is here:
e = cudaMemcpy(&(d_a->s), &temp, sizeof(int*), cudaMemcpyHostToDevice);
d_a is a pointer to a device object, you cannot dereference it on the host.
You'll have to first copy s to the device, then create an object of type A on the host which has a pointer to the device copy of s, and then copy this object on the device.
This is a known issue with CUDA, and happens often with structures like linked lists or trees, that's one of the reasons why Nvidia is investing a lot of effort in improving unified memory. If you can use that, and it doesn't decrease the performance of your application, it could save you a lot of trouble with problems like this.
Here is your example with the problems fixed:
class A {
public:
int *s;
};
__global__ void MethodA(A *a) {
printf("%d\n", a->s[2]);
a->s[2] = 6;
}
int main() {
A *a = new A();
int asd[] = { 0, 1, 2, 3, 4 };
a->s = asd;
A *a_with_d_s = new A();
cudaMalloc(&(a_with_d_s->s), sizeof(int) * 5);
cudaMemcpy(a_with_d_s->s, a->s, sizeof(int) * 5, cudaMemcpyHostToDevice);
A *d_a;
cudaMalloc(&d_a, sizeof(A));
cudaMemcpy(d_a, a_with_d_s, sizeof(A), cudaMemcpyHostToDevice);
MethodA << <1, 1 >> > (d_a);
// note that if we call the following line, a->s will point to device
// memory!
//cudaMemcpy(a, d_a, sizeof(A), cudaMemcpyDeviceToHost);
cudaMemcpy(a->s, a_with_d_s->s, sizeof(int) * 5, cudaMemcpyDeviceToHost);
printf("%d\n", a->s[2]);
cudaFree(d_a);
cudaFree(a_with_d_s->s);
delete(a);
delete(a_with_d_s);
return 0;
}
Prints out:
2
6
I have a shared object of type:
struct A {
int x;
int y;
int z;
};
A obj;
There is 2 threads running in parallel.
Thread #1 modifies object's members:
// .. some code before
obj.x = 42;
obj.y = 42;
obj.z = 42;
// .. now thread #2 can read obj
Thread #2 reads object's members:
// .. some code before
int x = obj.x;
int y = obj.y;
int z = obj.z;
// .. some code after
How to synchronize the flow most efficiently that the thread #2 reads object's members only after thread #1 modified them all?
Use std::atomic here.
boost::atomic<int> x { INT_MAX };
// thread1:
while (x.load(memory_order_acquire) == INT_MAX);
// thread2:
x.store(42,memory_order_release);
EDIT add runnable example
main.cpp
#include <iostream>
#include <chrono>
#include <thread>
#include <atomic>
struct Foo {
Foo(): x_(0) {}
std::atomic<int> x_;
};
using namespace std;
int main() {
Foo foo;
thread th1(
[&]() {
cout << "thread1 Waiting for thread2 setting value for x" << endl;
while (foo.x_.load(memory_order_acquire) == 0);
int current = foo.x_.load(memory_order_acquire);
cout << "thread 1 print current value of x is " << current << endl;
});
thread th2(
[&]() {
std::chrono::milliseconds dura( 2000 );
std::this_thread::sleep_for( dura );
cout << "thread2 set up value for x" << endl;
foo.x_.store(42,memory_order_release);
});
th1.join();
th2.join();
return 0;
}
CMakeLists.txt
cmake_minimum_required(VERSION 2.8.4)
project(atomicExample)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++ -std=c++11")
set(SOURCE_FILES main.cpp)
add_executable(atomicExample ${SOURCE_FILES})
You can use std::mutex to synchronize critical sections of your code. std::lock_guard locks a mutex and releases it when the lock_guard goes out of scope. I've also added a condition variable to ensure that thread2() waits for thread1() to finish assigning values to obj before continuing.
Example:
#include <mutex>
#include <condition_variable>
struct A {
int x;
int y;
int z;
};
A obj;
std::mutex m;
std::condition_variable cv;
bool thread1Done = false;
void thread1()
{
std::lock_guard<std::mutex> lock( m );
obj.x = 42;
obj.y = 42;
obj.z = 42;
thread1Done = true;
cv.notifyAll();
}
void thread2()
{
std::unique_lock<std::mutex> lock( m );
while ( !thread1Done ) {
cv.wait( lock );
}
int x = obj.x;
int y = obj.y;
int z = obj.z;
}
Seems like Visual C++'s std::function<> doesn't handle functions with rvalue refs as arguments. Can anyone suggest a workaround?
#include <functional>
using namespace std;
class Object { };
void f(Object&&) { }
auto g = [](Object&&){ };
function<void(Object&&)> h;
int main()
{
Object o;
f(move(o));
g(move(o));
// Uncomment any one of the following lines, and we get an error from the instantiation
// of std::function: "error C2664: You cannot bind an lvalue to an rvalue reference"
//h(move(o));
//h = g;
//h = f;
return 0;
}
This is Visual Studio 2010. I am not using /Za (so it is not this problem).
Update after some research: The code compiles in Clang, so I am pretty sure it is a Microsoft bug. It might be this one, fixed in VC11: 649274
Correction to the update: The MS bug is not fixed in VC11. From the link:
our first opportunity will be the "out of band" release between VC11 and VC12 that Herb Sutter
announced at the GoingNative 2012 conference.
I'm not sure what workaround you'd like here. Assuming you cannot change the call expression of the function object and the target signature, you can wrap the rvalue reference and pass the wrapped object (a temporary) via const ref.
Essentially, the call expands to: f( wrap(move(o)) );
I suspect there's a problem with perfect forwarding, because binding i = bind(&f); does not work; therefore I've introduced an intermediate step performing perfect forwarding, such that the call is resolved to: f( move( (Object&)wrap( move(o) ) ) );
#include <iostream>
#include <functional>
using namespace std;
struct Object { int m; };
// target function with fixed signature (assuming we cannot change that)
void f(Object&& p) { p.m = 42; std::cout << p.m; };
// was surprised I didn't find any method to chain functions in the StdLib
// so here's my own:
template < typename F1, typename F2, typename P1 >
auto chain2(F1 f1, F2 f2, P1&& p1)
-> decltype( f1(f2( std::forward<P1>(p1) )) )
{
return f1( f2( std::forward<P1>(p1) ) );
}
// a special bind version; mostly syntactic sugar
// note you can also deduce the first template parameter; would be more work
// and not necessary here
template < typename P1, typename F1, typename F2 >
auto bind_chain(F1 f1, F2 f2)
-> decltype( std::bind( &chain2<F1,F2,P1>, f1, f2, std::placeholders::_1 ) )
{
return std::bind( &chain2<F1,F2,P1>, f1, f2, std::placeholders::_1 );
}
// as `std::move` is overloaded, we make things a little bit simpler;
// we later will need to get a function pointer on this, that's why
// I'd like to avoid too much overloading
template < typename T >
// for a certain reason, cannot use && here --------v, clang++3.2 accepts it
typename std::remove_reference<T>::type && my_move(T& p)
{
return std::move(p);
}
struct wrapper
{
Object&& m;
wrapper(Object&& p) : m(std::move(p)) {}
operator Object&() const { return m; }
// alternatively:
// operator Object&&() const { return std::move(m); }
};
int main()
{
Object o;
// we'll need to call the functor with an const ref
function<void(wrapper const&)> i;
// chaining the conversion to rvalue ref with the target function
i = bind_chain<wrapper const&>( &f, &my_move<Object> );
i( move(o) );
return 0;
}