boehm-gc with C++11's thread library - c++

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.

Related

Implementing Boost.thread

I am learning boost c++ and thus I was trying this piece of code which deals with boost threads
#include <boost/thread.hpp>
#include <boost/chrono.hpp>
#include <iostream>
void wait(int seconds)
{
boost::this_thread::sleep_for(boost::chrono::seconds(seconds));
}
void thread()
{
for(int i = 0; i < 5; i++)
{
wait(2);
std::cout << i << std::endl;
}
}
int main()
{
boost::thread t(thread);
t.join();
return 0;
}
But when I compile this code on VS2008 I get the following errors:
LINK : fatal error LNK1104: cannot open file 'boost_thread-vc90-mt-1_58.lib'
What I understood is this error is due to configuration issues but I don't know how to get rid of it. Can somebody help me in solving this error?
First of all you need to compile boost (if you didn't).
Secondly you need to properly add this library to project, look at this answer.

Does the C++ standard support processes?

I know C++11 added support for threads. For example:
#include <iostream>
#include <thread>
void bar()
{
std::cout << "bar()\n";
}
int main()
{
std::thread thread(bar);
thread.join();
return 0;
}
However, is there a way to execute the bar function in a separate process? If not, is there any discussion on whether such a feature should be added?
Note: I'm aware of the possibility of using platform independent libraries and I'm just curious if C++ supports this directly or will in the future.
No, the c++ standard (particularly C++11) doesn't have any notion of a process (hence I can't give you a more reasonable reference here as a search result from the most popular and currently most up to date c++ documentation site).
I'm also not aware that process support is planned for the next standard version C++-17 (aka C++-1z). At least the Wikipedia Site doesn't mention it.
There is a popular implementation that was proposed for boost, but that never was drawn for a C++ standard proposal.
You usually can't write portable code to run on bare metal systems, where only one process exists.
However, is there a way to execute the bar() function in a separate process?
The simplest option to do that is to fallback to fork() and wait() as specified by the POSIX Open Group:
#include <iostream>
#include <unistd.h>
#include <sys/wait.h>
void bar()
{
std::cout << "bar()\n";
}
int main(int argc, char **argv)
{
pid_t pid = fork();
if (pid == 0)
{
// child process
bar();
}
else if (pid > 0)
{
// parent process
wait(NULL);
}
else
{
// fork failed
std::cerr << "fork() failed!" << std::endl;
return 1;
}
return 0;
}
Though I don't see much of a point to create an extra process to execute a simple function. Creating a process creates a lot of overhead you don't want in such case.
Well, if you want to start another program using functions from the exec() function family that's a different use case.
I'd recommend sticking to std::threads for your example.
Boost started supporting processes in version 1.64.0 (April 2017).
https://www.boost.org/doc/libs/1_70_0/doc/html/process.html
The fact that it is a Boost feature is a source of hope for its inclusion in a future C++ standard.
There was a proposal in 2019, but the momentum seems to have stalled a bit since.
See this GitHub issue for progress about it.

Boost thread c2064 error when trying to compile

I'm quite new to the stack overflow, in fact this is my first post, So hello everyone. So let's get to the point.
Using boost library thread ver. 1.54.0
Using VS2010 32 Bit - Professional
I have built the libraries for the boost thread,
not using precompiled headers in vs C++ settings,
linked the library to the project,
here is the code
#include <boost\thread\thread_only.hpp>
#include <iostream>
#include <conio.h>
#pragma comment(lib, "libboost_thread-vc100-mt-gd-1_54.lib")
#define BOOST_LIB_NAME libboost_thread-vc100-mt-gd-1_54.lib
struct callable
{
void blah();
};
void callable::blah()
{
std::cout << "Threading test !\n";
}
boost::thread createThread()
{
callable x;
return boost::thread(x);
}
int main()
{
createThread();
_getch();
return 0;
}
after all this I get this error
Error 1 error C2064: term does not evaluate to a function taking 0 arguments ..\..\boost_1_54_0\boost\thread\detail\thread.hpp 117 1 BoostTrial
Could you help me to get this example to work. Reason why I am using this example is because I have another app which has been set up exactly the same way and it's not working because of this error :-( my goal is to get the multithreading to work and then I can take it from there.
Thanks for your time.
You need to implement operator() in callable.
Don't forget to either join() or detach() thread to prevent abnormal program termination.
See boost::thread tutorial for more examples.
#include <boost\thread\thread_only.hpp>
#include <iostream>
#pragma comment(lib, "libboost_thread-vc100-mt-gd-1_54.lib")
using namespace boost;
struct callable
{
void operator()()
{
std::cout << "Threading test !\n";
}
};
boost::thread createThread()
{
callable x;
return boost::thread(x);
}
int main()
{
boost::thread th = createThread();
th.join();
}
Example with std::thread;

Most basic parallelization with C++11 theads fail

I try to use C++11 theading library using g++ 4.7.
First I have a question: is it expected for a next release to not be required to link by hand the pthread library ?
So my program is :
#include <iostream>
#include <vector>
#include <thread>
void f(int i) {
std::cout<<"Hello world from : "<<i<<std::endl;
}
int main() {
const int n = 4;
std::vector<std::thread> t;
for (int i = 0; i < n; ++i) {
t.push_back(std::thread(f, i));
}
for (int i = 0; i < n; ++i) {
t[i].join();
}
return 0;
}
I compile with:
g++-4.7 -Wall -Wextra -Winline -std=c++0x -pthread -O3 helloworld.cpp -o helloworld
And it returns:
Hello world from : Hello world from : Hello world from : 32
2
pure virtual method called
terminate called without an active exception
Erreur de segmentation (core dumped)
What is the problem and how to solve it ?
UPDATE:
Now using mutex:
#include <iostream>
#include <vector>
#include <thread>
#include <mutex>
static std::mutex m;
void f(int i) {
m.lock();
std::cout<<"Hello world from : "<<i<<std::endl;
m.unlock();
}
int main() {
const int n = 4;
std::vector<std::thread> t;
for (int i = 0; i < n; ++i) {
t.push_back(std::thread(f, i));
}
for (int i = 0; i < n; ++i) {
t[i].join();
}
return 0;
}
It returns :
pure virtual method called
Hello world from : 2
terminate called without an active exception
Abandon (core dumped)
UPDATE 2:
Hum... It works with my default GCC (g++4.6) but it fails with the version of gcc I compiled by hand (g++4.7.1). Was there an option I forgot to compile g++ 4.7.1 ?
General edit:
In order to prevent use of cout by multiple threads simultaneously, that will result in character interleaving, proceed as follows:
1) declare before the declaration of f():
static std::mutex m;
2) then, guard the "cout" line between:
m.lock();
std::cout<<"Hello world from : "<<i<<std::endl;
m.unlock();
Apparently, linking against the -lpthread library is a must, for some unclear reasons. At least on my machine, not linking against -lpthread results in a core dump. Adding -lpthread results in proper functionality of the program.
The possibility of character interleaving if locking is not used when accessing cout from different threads is expressed here:
https://stackoverflow.com/a/6374525/1284631
more exactly: "[ Note: Users must still synchronize concurrent use of these objects and streams by multiple threads if they wish to avoid interleaved characters. — end note ]"
OTOH, the race condition is guaranteed to be avoided, at least in the C++11 standard (beware, the gcc/g++ implementation of this standard is still at experimental level).
Note that the Microsoft implementation (see: http://msdn.microsoft.com/en-us/library/c9ceah3b.aspx credit to #SChepurin) is stricter than the standard (apparently, it guarantees character interleaving is avoided), but this might not be the case for the gcc/g++ implementation.
This is the command line that I use to compile (both updated and original code versions, everything works well on my PC):
g++ threadtest.cpp -std=gnu++11 -lpthread -O3
OTOH, without the -lpthread, it compiles but I have a core dump (gcc 4.7.2 on Linux 64).
I understand that you are using two different versions of the gcc/g++ compiler on the same machine. Just be sure that you use them properly (not mixing different library versions).

Ridiculously slow unique_ptr dtor call when debugger is attached (msvc)

struct test_struct
{
test_struct() {}
~test_struct() {}
};
#include <vector>
#include <memory>
#include <cstdio>
int main()
{
printf("ctor begin\n");
{
std::vector<std::unique_ptr<test_struct>> test_vec;
const int count = 100000;
for (auto i = 0; i < count; i++) {
test_vec.emplace_back(new test_struct);
}
printf("dtor begin\n");
}
printf("dtor end\n");
}
I'm using VS2010, and found some ridiculous performance issue. The code above works well both in debug and release build (ctrl+f5), but when debugger is attached(f5), dtor call for unique_ptr class is intolerably slow. The result machine code is fairly optimized, so I don't expect that it's compiler issue rather than debugger's, but I don't know how to deal with it. My question is
Is this problem able to be reproduced on your machine?
What's the reason of this behaviour?
Is there any workaround?
The slowdown is caused by memory checking that occurs whenever memory is freed. However, this is a special system-/debugger-level heap, and isn't anything you can control from within your program.
There's a great article on the issue. To summarize: you have to set an environment variable to disable it!
Luckily, you can set project-specific environment variables from the Debugging options in the Project Settings for your project, so that the environment variable is only applied to your program.
I used this simplified program to test:
#include <iostream>
#include <memory>
#include <vector>
int main()
{
std::cout << "ctor begin" << std::endl;
{
std::vector<std::unique_ptr<int>> test_vec;
for (unsigned i = 0; i < 100000; i++)
test_vec.emplace_back(new int);
std::cout << "dtor begin" << std::endl;
}
std::cout << "dtor end" << std::endl;
}
By setting _NO_DEBUG_HEAP=1 as an environment variable (either system-wide, which I won't recommend, or through the Debugging options), the code runs in roughly the same amount of time irrespective of whether or not the debugger is attached.