Is it somehow possible to pass an std::unique_ptr as a parameter to a boost::thread constructor? If not, what is the best workaround?
A small example:
// errors: g++ uniqueptr_thread.cpp -std=c++0x
#include <iostream>
#include <memory>
#include <boost/thread.hpp>
class TestThread{
public:
void operator()(std::unique_ptr<int> val){
std::cout << "parameter: " << val << std::endl;
}
};
int main(int argc, char* argv[]){
std::unique_ptr<int> ptr(new int(5));
boost::thread th( new TestThread(), std::move(ptr));
}
This compiles and runs for me:
#include <iostream>
#include <memory>
#include <thread>
class TestThread{
public:
void operator()(std::unique_ptr<int> val){
std::cout << "parameter: " << *val << std::endl;
}
};
int main()
{
std::unique_ptr<int> ptr(new int(5));
std::thread th( TestThread(), std::move(ptr));
th.join();
}
But it has to be in C++0x mode. I don't know if the boost move emulation is good enough to do this or not.
A std::unique_ptr is, as the name suggests, unique. There can be only one!
Now, if your thread function takes a std::unique_ptr&&, and you use std::move to move the parameter in the thread function, then you can pass the std::unique_ptr. But then your copy will be empty, since you moved it to the other thread.
If std::move does not work, then your compiler or standard library may have bugs in it. I imagine that transferring ownership across threads like this isn't a common occurrence. And C++11 is still fairly new.
Are you sure your problem is with the unique_ptr? Why does your example use new to create your functor? That line should just read:
boost::thread th(TestThread(), std::move(ptr));
Related
I'm readin Scott Meyrse C++ and now I'm at the section about deigning interfaces. The following code is supposed to be invalid:
std::tr1::shared_ptr<Investment> // attempt to create a null
pInv(0, getRidOfInvestment); // shared_ptr with a custom deleter;
// this won’t compile
He gave the following explanation:
The tr1::shared_ptr constructor insists on its first parameter being a
pointer, and 0 isn’t a pointer, it’s an int. Yes, it’s convertible to
a pointer, but that’s not good enough in this case; tr1::shared_ptr
insists on an actual pointer.
I tried similar example myself http://coliru.stacked-crooked.com/a/4199bdf68a1d6e19
#include <iostream>
#include <memory>
struct B{
explicit B(void *){ }
};
void del(int*){ }
int main()
{
B b(0);
std::shared_ptr<int*> ptr(0, del);
}
and it compiles and runs fine even in spite of passing 0 as the first argument.
What did he mean actually? Isn't that relevant already?
One is from #include <tr1/memory>; the other is from #include <memory>. There is a difference:
http://coliru.stacked-crooked.com/a/f76ea0ef17227d9d
#include <iostream>
#include <tr1/memory>
#include <memory>
struct B{
explicit B(void *){ }
};
void del(int*){ }
int main()
{
B b(0);
std::tr1::shared_ptr<int*> ptr(0, del);
std::shared_ptr<int*> ptr2(0, del);
}
It gives the error for the tr1 version but not the current standard version.
I'm coming back to c++ from a long absence, and am picking up c++11 and boost::asio at the same time.
After GotW #93 and #94, I'm naturally fired up about using auto.
Imagine my disapointment when this doesn't compile:
auto io = boost::asio::io_service{};
but I must use this instead:
boost::asio::io_service io{};
Why does the second compile, but the first not? The error I'm getting is
Call to implicitly-deleted copy constructor of 'boost::asio::io_service'
boost::asio::deadline::timer exhibits the same behavior, but boost::posix_time::seconds does not.
(I'm using xcode + clang + boost 1_55_0).
Full compiling example, modified from the boost asio tutorial:
#include <iostream>
#include <memory>
#include <boost/asio.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
namespace asio = boost::asio;
int main(int argc, const char * argv[]) {
using error_code = const boost::system::error_code;
asio::io_service io{};
asio::deadline_timer t{io, boost::posix_time::seconds{2}};
int count = 0;
std::function<void (const error_code&)> fn = [&](const error_code& e) {
if (count < 5) {
std::cout << "Hello World" << std::endl;
++(count);
t.expires_at(t.expires_at() + boost::posix_time::seconds{1});
t.async_wait(fn);
}
};
t.async_wait(fn);
io.run();
std::cout << "Final count is " << count << std::endl;
return 0;
}
The class asio::io_service derives from noncopyable, which means the copy constructor has been intentionally made inaccessible. This statement won't work for the same reason:
boost::asio::io_service io = boost::asio::io_service{};
In this instance, the problem is not because of the auto keyword, but lack of access to the required constructor. The tutorial code uses the normal constructor, which is public, and so compiles fine.
The error is pretty self-explanatory, it has nothing to do with the use of auto. The following code will produce a similar error message:
struct foo
{
foo() = default;
foo(foo const&) = delete;
};
foo f = foo{};
The last line above requires an accessible copy-constructor (even if the compiler elides the copy).
boost::asio::io_service's copy-constructor is implicitly deleted, probably due to the presence of one or more non-copyable data members or base classes. You already have the right solution to fix the error:
asio::io_service io{};
As we know, using boehm-gc in multi-thread requires calling GC_register_my_thread with stack base from GC_get_stack_base. but It seems not to work well with C++11's thread library, such as std::thread... How can I use boehm-gc with C++11's thread library?
(I use VS2013)
edit: This is tested code. std::thread is good, but std::future doesn't work (stop on _CrtIsValidHeapPointer
#include <iostream>
#include <thread>
#include <future>
#define GC_THREADS
#include <gc.h>
#include <gc_cpp.h>
#pragma comment(lib, "gcmt-lib")
void foo()
{
GC_stack_base sb;
GC_get_stack_base(&sb);
GC_register_my_thread(&sb);
int *ptr;
for (int i = 0; i < 10; i++)
{
ptr = new (GC) int;
*ptr = 1;
}
GC_unregister_my_thread();
}
int main()
{
GC_INIT();
GC_allow_register_threads();
std::cout << "test for std::thread";
std::thread thrd(foo);
thrd.join();
std::cout << " [sucs]\n";
std::cout << "test for std::future";
std::future<void> fu = std::async(std::launch::async, foo);
fu.get();
std::cout << " [sucs]\n";
std::cin.get();
}
edit: here is a capture of stack trace (Sorry that it isn't English, but I think it doesn't matter, anyway)
and here is a debug message
HEAP[TestGC.exe]: Invalid address specified to RtlValidateHeap( 00E80000, 00C92F80 )
While debugging, I found The error occurs after fu.get().
edit: The error doesn't occur with /MD(or /MDd)...
(I think GC might touch library's pointers (namespcae Concurrency), but it is just guess;;)
Before you start using the collector and before you create the threads make sure that you issue both
GC_INIT, and
GC_allow_register_threads
Then in every thread follow it up with,
GC_get_stack_base/GC_register_my_thread, and eventually
GC_unregister_my_thread.
You didn't say what you are compiling with but it works for gcc 4.8 (with -std=c++11).
EDIT: The OP was able to resolve the issue by addressing the instruction above and compiling the code with the /MD[d] flags for the multi-threaded dynamic MSVCR100 runtime. The issue remained unresolved for the multithreaded statically compiled runtime.
Using Visual Studio 2013 RC and C++, I'm trying to pass an std::unique_ptr to a function that has been bound using std::bind. However, I'm having trouble because VS doesn't seem to like it when I try this. Here's what I'm trying to compile:
#include <memory>
#include <iostream>
#include <functional>
void func(std::unique_ptr<int> arg)
{
std::cout << *arg << std::endl;
}
int main()
{
std::function<void (std::unique_ptr<int>)> bound =
std::bind(&func, std::placeholders::_1);
std::unique_ptr<int> ptr(new int(42));
bound(std::move(ptr));
return 0;
}
This compiles in GCC 4.8.1, but not in VS2013 RC. I've always had problems with move semantics in VS, but I'd really like to use std::unique_ptr instead of std::shared_ptr or raw pointers.
One workaround I've found is to change the function signature to accept an std::unique_ptr&, which does compile in VS and GCC, but doesn't make the intent of func taking ownership of the std::unique_ptr particularly clear, and also prevents me from safely asynchronously calling the function unless I do something particularly ugly:
#include <memory>
#include <iostream>
#include <functional>
#include <future>
#include <string>
void func(std::unique_ptr<int>& arg)
{
std::cout << *arg << std::endl;
}
int main()
{
std::function<void (std::unique_ptr<int>&)> bound =
std::bind(&func, std::placeholders::_1);
std::unique_ptr<int> ptr(new int(42));
std::promise<void> prom;
std::async(
[&bound, &ptr, &prom]
{
std::unique_ptr<int> movedPtr = std::move(ptr);
prom.set_value();
bound(std::move(movedPtr));
});
prom.get_future().wait();
// Wait here
std::string dummy;
std::cin >> dummy;
}
Is there a way to get around this without changing func's signature?
Thanks!
I had the same problem with VS 2012 recently. I believe this is a bug in MSVC; at least in MSVC++11 the pseudo-variadic expansion seems to forward the parameters by value to some internal function. Seems this hasn't been improved.
As a workaround, I'm using lambdas instead, but another hack is required to make it work:
std::function<void (std::unique_ptr<int>)> bound =
[] (std::unique_ptr<int> arg) { func(std::move(arg)); };
still doesn't compile. But if you add any captured value (even one that isn't used), it compiles:
int x;
std::function<void (std::unique_ptr<int>)> bound =
[x] (std::unique_ptr<int> arg) { func(std::move(arg)); };
You have to move the parameter into the bound call to func also. Not only in the invocation of bound
bound(std::move(ptr));
but also in the binding:
std::function<void(std::unique_ptr<int>)> bound =
std::bind(func,
std::bind(std::move<std::unique_ptr<int>&>,
std::placeholders::_1));
This is compiling in VS2013 (update 4) for me.
Functions bound with std::bind do not forward arguments, it copies them to the function. As a result, std::bind doesn't work with move-only types as of c++11. This problem is the idea behind proposals for "more perfect forwarding" (like this one). There's a newer one, but I can't seem to find it right now.
I don't know why it doesn't compile of I erase the comment in line
/*******************************/
waitThread.push_front(workerID);
/******************************/
Only if I leave the comment, it compiles...otherwise, I get a long exception ending with "declared here"...
/usr/include/c++/4.6/thread:126:5: error: declared here
maybe there is some problem with the definition of ...
Can you explain me?
/* g++ -std=c++0x -o manyThreads manyThreads.cpp -pthread */
#include <thread>
#include <iostream>
#include <mutex>
#include <time.h>
#include <list>
std::list<std::thread::id> myList;
std::mutex mutex;
std::list<std::thread> waitThread;
void insertList(std::thread::id identifier) {
mutex.lock();
myList.push_front(identifier);
mutex.unlock();
}
int main() {
std::list<std::thread::id>::iterator id;
std::list<std::thread>::iterator threadsIter;
int counter;
for(counter=0; counter<6; counter++) {
std::thread workerID(insertList, workerID.get_id());
/*******************************/
waitThread.push_front(workerID);
/******************************/
}
for(threadsIter=waitThread.begin(); threadsIter !=waitThread.end();threadsIter++) {
threadsIter->join();
}
for(id=myList.begin(); id != myList.end(); id++) {
std::cout << *id << "\n";
}
return 0;
}
std::thread is not copyable so you can't call push_front with it. It makes no sense to copy a thread, what would it do?
You can perhaps move the thread onto the list using
waitThread.push_front(std::move(workerID));
which will of course invalidate the thread object after that line.
However this line looks strange too :-
std::thread workerID(insertList, workerID.get_id());
I doubt it's valid to call get_id on an object that isn't constructed at that point.
std::thread is not copyable so you would have to move it in:
waitThread.push_front(std::move(workerID));
alternatively, you can move it by passing a temporary:
waitThread.push_front(std::thread(insertList, workerID.get_id());
It's not a comment, but a valid and (probably) essential statement in your program:
/*******************************/ -- comment
waitThread.push_front(workerID); -- statement
/******************************/ --comment