I'm learning boost::timed_mutex
The follwing code cannot be compiled:
#include <boost/thread.hpp>
#include <boost/chrono.hpp>
#include <iostream>
void wait(int seconds)
{
boost::this_thread::sleep_for(boost::chrono::seconds{seconds});
}
boost::timed_mutex mutex;
void thread1()
{
using boost::this_thread::get_id;
for (int i = 0; i < 5; ++i)
{
wait(1);
boost::unique_lock<boost::timed_mutex> lock{mutex};
std::cout << "Thread " << get_id() << ": " << i << std::endl;
boost::timed_mutex *m = lock.release();
m->unlock();
}
}
void thread2()
{
using boost::this_thread::get_id;
for (int i = 0; i < 5; ++i)
{
wait(1);
boost::unique_lock<boost::timed_mutex> lock{mutex,
boost::try_to_lock};
if (lock.owns_lock() || lock.try_lock_for(boost::chrono::seconds{1}))
{
std::cout << "Thread " << get_id() << ": " << i << std::endl;
}
}
}
int main()
{
boost::thread t1{thread1};
boost::thread t2{thread2};
t1.join();
t2.join();
}
My compile command is:
g++ -std=c++11 unique_lock.cpp -o unique_lock -g -lboost_system -lboost_thread-mt -pthread -lboost_timer
The error is something like the following:
/bin/ld: /tmp/ccRVKHNh.o: undefined reference to symbol '_ZN5boost6chrono12system_clock3nowEv'
/usr/lib64/libboost_chrono.so.1.53.0: error adding symbols: DSO missing from command line
collect2: error: ld returned 1 exit status
What's wrong?
Apparently -lboost_chrono is missing.
Demo
Related
There is a problem when using std::condition_variable and compiling with g++ on Linux which has glibc-2.30. But it does not run on RHEL 7 with glibc-2.17. The reason is std::condition_variable::wait_for() is linked to pthread_cond_clockwait() function, which is introduced in glibc-2.30. The gcc packge was built from source with glibc-2.30.
https://github.com/gcc-mirror/gcc/blob/master/libstdc%2B%2B-v3/include/bits/std_mutex.h :
...
#ifdef _GLIBCXX_USE_PTHREAD_COND_CLOCKWAIT
void
wait_until(mutex& __m, clockid_t __clock, timespec& __abs_time)
{
pthread_cond_clockwait(&_M_cond, __m.native_handle(), __clock,
&__abs_time);
}
#endif
...
https://en.cppreference.com/w/cpp/thread/condition_variable/wait_for :
#include <iostream>
#include <atomic>
#include <condition_variable>
#include <thread>
#include <chrono>
using namespace std::chrono_literals;
std::condition_variable cv;
std::mutex cv_m;
int i;
void waits(int idx)
{
std::unique_lock<std::mutex> lk(cv_m);
if(cv.wait_for(lk, idx*100ms, []{return i == 1;}))
std::cerr << "Thread " << idx << " finished waiting. i == " << i << '\n';
else
std::cerr << "Thread " << idx << " timed out. i == " << i << '\n';
}
void signals()
{
std::this_thread::sleep_for(120ms);
std::cerr << "Notifying...\n";
cv.notify_all();
std::this_thread::sleep_for(100ms);
{
std::lock_guard<std::mutex> lk(cv_m);
i = 1;
}
std::cerr << "Notifying again...\n";
cv.notify_all();
}
int main()
{
std::thread t1(waits, 1), t2(waits, 2), t3(waits, 3), t4(signals);
t1.join();
t2.join();
t3.join();
t4.join();
}
The source code was copied to a file test.cpp and compiled with a small script build.sh.
build.sh:
#!/usr/bin/env bash
/opt/gcc-11.3.0/bin/g++ \
-std=c++17 -O3 -pthread -static-libstdc++ -static-libgcc glibc_test.cpp -o test_glibc
Then test_glibc is copied to RHEL 7 and ldd test_glibc has delivered this issue:
./test_glibc: /lib64/libpthread.so.0: version `GLIBC_2.30' not found (required by ./test_glibc)
The only solution I have found was to modify the configure file in gcc/libstdc++-v3 folder and compile the gcc package again. glibcxx_cv_PTHREAD_COND_CLOCKWAIT=yes is modified to glibcxx_cv_PTHREAD_COND_CLOCKWAIT=no
if ac_fn_cxx_try_compile "$LINENO"; then :
glibcxx_cv_PTHREAD_COND_CLOCKWAIT=no
else
glibcxx_cv_PTHREAD_COND_CLOCKWAIT=no
fi
and
if ac_fn_cxx_try_link "$LINENO"; then :
glibcxx_cv_PTHREAD_COND_CLOCKWAIT=no
else
glibcxx_cv_PTHREAD_COND_CLOCKWAIT=no
fi
So my question, is there any other solution to solve the problem with incompatible newer glibc functions to older versions?
So I'm working on a project for a class and I cannot seem to get things to work. 1) Did I do this right? 2) How do I get rid of the errors?
#include <iostream>
#include <thread>
using namespace std;
void countdown(){
int count;
count = 21;
while (count<=0)
{
count--;
cout << "Count is " << count << '.' << endl;
}
}
int main() {
std::thread t1(countdown);
t1.join();
int count1;
count1 = 0;
while (count1<20)
{
count1++;
cout << "Count is " << count1 << '.' << endl;
}
return 0;
}
Error messages:
g++ -O0 -g3 -Wall -c -fmessage-length=0 -std=c++11 -Wl,--no-as-needed -o "src\\Critical7.o" "..\\src\\Critical7.cpp"
..\src\Critical7.cpp: In function 'int main()':
..\src\Critical7.cpp:27:2: error: 'thread' is not a member of 'std'
std::thread t1(countdown);
^
..\src\Critical7.cpp:28:2: error: 't1' was not declared in this scope
t1.join();
I've tried setting things the way other posts have said but I can't seem to get it to work.
Two modifications are necessary to run the code correctly:
replace while (count<=0) with while(count>=0), else the loop in countdown() exits immediately.
Use the -pthread linker option in order to compile the code.
The following compile error i am facing when i compile a .cc file. i am using apache ignite libraries and c++ libraries to compile and jdk path is specified.
#include <iostream>
#include "ignite/ignite.h"
#include "ignite/ignition.h"
using namespace ignite;
using namespace cache;
int main()
{
IgniteConfiguration cfg;
cfg.jvmInitMem = 512;
cfg.jvmMaxMem = 512;
cfg.springCfgPath = "/home/ignite/DataGridTest.xml";
try
{
Ignite grid = Ignition::Start(cfg);
std::cout << std::endl;
std::cout << ">>> Cache put-get example started." << std::endl;
std::cout << std::endl;
Cache<int, int> cache = grid.GetCache<int, int>("mycache");
cache.Clear();
cache.Put(1, 1);
int orgFromCache = cache.Get(1);
std::cout << ">>> Retrieved value from cache: " << std::endl;
std::cout << orgFromCache << std::endl;
std::cout << std::endl;
Ignition::StopAll(false);
}
catch (IgniteError& err)
{
std::cout << "An error occurred: " << err.GetText() << std::endl;
}
std::cout << std::endl;
std::cout << ">>> Example finished, press 'Enter' to exit ..." << std::endl;
std::cout << std::endl;
return 0;
}
In command line:
gcc -I /usr/java/jdk1.8.0_131/include/ -I
/usr/java/jdk1.8.0_131/include/linux/ -I
$IGNITE_HOME/platforms/cpp/jni/include/ -I
$IGNITE_HOME/platforms/cpp/core/include/ -I
$IGNITE_HOME/platforms/cpp/common/os/linux/include/ -I
$IGNITE_HOME/platforms/cpp/examples/include/ DataGridTest.cc -o DataGridTest -lignite
/usr/bin/ld: /tmp/cc9zxSDP.o: undefined reference to symbol '_ZN6ignite3jni4java12JniErrorInfoD1Ev'
/usr/local/lib//libignite-jni-2.0.0.19668.so.0: error adding symbols: DSO missing from command line
collect2: error: ld returned 1 exit status
Except for the libignite you also need to link to libignite-binary, libignite-common and libignite-jni.
I come from C# coding experience; I am beginning to learn C++ and make use of boost libraries for threading.
I wrote the following class - trying to execute a member function as a thread. Writing the following simple code, i would expect the while loop inside the thread function to execute every second.
#include <boost/chrono/chrono.hpp>
#include <boost/thread/thread.hpp>
#include <iostream>
using namespace boost;
class MyClassWithThread : public boost::enable_shared_from_this<MyClassWithThread>
{
mutex muThreadControl;
condition_variable cvThreadControl;
bool threadToBeStopped = false;
void ThreadFunction()
{
std::cout << "Beginning the Thread" << std::endl;
while(true)
{
bool endIOThread = false;
std::cout << "\nChecking if Thread to be stopped: ";
{
boost::mutex::scoped_lock lock(muThreadControl);
endIOThread = cvThreadControl.wait_for(lock,
boost::chrono::seconds(1),
[this]{return threadToBeStopped;} ) == cv_status::no_timeout;
std::cout << endIOThread << std::endl
}
}
std::cout << "Exiting the Thread" << std::endl;
}
public:
thread threadRunner;
MyClassWithThread()
{
threadRunner = thread(&MyClassWithThread::ThreadFunction, this);
}
};
int main(int argc, char* argv[])
{
MyClassWithThread myclassWithThread;
myclassWithThread.threadRunner.join();
return 0;
}
To build on Linux:
g++ -std=c++11 -pthread cond-wait-test.cpp -o cond-wait-test -lboost_system -lboost_thread -lboost_chrono
However, when i execute the code, all i notice is that the thread execution is blocked at the call to wait_for method; forever. despite the timeout period. Further, the resource monitor of the system shows a processor core is being 100% utilized.
Could anyone please explain whats happening in the code?
As suggested by #Zan Lynx, the culprit was #pragma pack statement. I initially used only #pragma pack(1) to byte align some structures. This affected many of mutex structures to 1 byte alignment.
I changed the #pragma pack(1) statements to #pragma pack(push, 1) #pragma pack(pop). Its all working fine. Hence my problem is solved; i learnt something. Thanks a Lot. ! :-)
Your program will never exit your while loop.
Solution.
Add some kind of termination condition.
bool endIOThread = false;
while(!endIOThread)
{
std::cout << "\nChecking if Thread to be stopped: ";
{
boost::mutex::scoped_lock lock(muThreadControl);
endIOThread = cvThreadControl.wait_for(lock,
boost::chrono::seconds(1),
[this]{return threadToBeStopped;} ) == cv_status::no_timeout;
std::cout << endIOThread << std::endl
}
}
I copied your code and tried it on Linux.
Your code as posted will not compile. I wonder if you tried it?
The problem is that wait_for with the predicate overload returns a bool not a cv_status. The inner loop times out, calls the predicate and returns.
Your code works as expected if I remove the predicate lambda. It also works if I leave the lambda and remove the == comparison with the cv_status.
Perhaps if you do what I did and remove the using namespace boost; line and then make all Boost objects explicit.
Here is my modified version which works for me:
#include <boost/chrono/chrono.hpp>
#include <boost/thread/thread.hpp>
#include <iostream>
class MyClassWithThread : public boost::enable_shared_from_this<MyClassWithThread>
{
boost::mutex muThreadControl;
boost::condition_variable cvThreadControl;
bool threadToBeStopped = false;
void ThreadFunction()
{
std::cout << "Beginning the Thread" << std::endl;
while(true)
{
bool endIOThread = false;
std::cout << "\nChecking if Thread to be stopped: ";
{
boost::mutex::scoped_lock lock(muThreadControl);
#if 1
endIOThread = cvThreadControl.wait_for(lock,
boost::chrono::seconds(1),
[this]{return threadToBeStopped;} );
#else
endIOThread = cvThreadControl.wait_for(lock,
boost::chrono::seconds(1)) == boost::cv_status::no_timeout;
std::cout << endIOThread << std::endl;
#endif
}
}
std::cout << "Exiting the Thread" << std::endl;
}
public:
boost::thread threadRunner;
MyClassWithThread()
{
threadRunner = boost::thread(&MyClassWithThread::ThreadFunction, this);
}
};
int main(int argc, char* argv[])
{
MyClassWithThread myclassWithThread;
myclassWithThread.threadRunner.join();
return 0;
}
Linux GCC build command:
g++ -std=c++11 -pthread cond-wait-test.cpp -o cond-wait-test -lboost_system -lboost_thread -lboost_chrono
So i've got this very basic OOP example and i want to compile it in Xubuntu but I get errors
the CThermo.h file
class CThermo
{
public:
void SetTemp(int newTemp);
int ReturnTemp();
void ChangeTemp(int deltaTemp);
private:
int m_temp;
};
the CThermo.cpp file
#incude "CThermo.h"
void CThermo::SetTemp(int newTemp)
{
m_temp = newTemp;
}
int CThermo::ReturnTemp()
{
return m_temp;
}
void CThermo::ChangeTemp(int deltaTemp)
{
m_temp += deltaTemp;
}
the main.cpp file
#include "CThermo.h"
#include <iostream>
using std::cout;
int main()
{
CThermo roomTemp;
roomTemp.SetTemp(20);
cout << "the temp is : "<< roomTemp.ReturnTemp() << "\n";
roomTemp.ChangeTemp(5);
cout << "after changing the temp, the room temp is : " << roomTemp.ReturnTemp();
cout << "test";
return 0;
}
the command to compile is "g++ main.cpp -o Main"
and this are the errors I get
/tmp/ccXajxEY.o: In function `main':
main.cpp:(.text+0x1a): undefined reference to `CThermo::SetTemp(int)'
main.cpp:(.text+0x26): undefined reference to `CThermo::ReturnTemp()'
main.cpp:(.text+0x6c): undefined reference to `CThermo::ChangeTemp(int)'
main.cpp:(.text+0x78): undefined reference to `CThermo::ReturnTemp()'
collect2: error: ld returned 1 exit status
You have to compile both main.cpp and CThermo.cpp using:
g++ CThermo.cpp main.cpp -o Main