I am trying to use boost::latch in my program to block waiting until all the threads finish or time out. My code is as follows. ctpl is a thread pool library adopted from https://github.com/vit-vit/CTPL.
#include <boost/thread/latch.hpp>
#include <CTPL/ctpl.h>
#include <mutex>
#include <iostream>
using namespace std;
int main(int argc, char **argv) {
ctpl::thread_pool outer_tp(100);
ctpl::thread_pool inner_tp(5, 5000);
auto out_func = [&inner_tp](int outer_id, int outer_invoke_idx) {
int num_batch = 20;
boost::latch latch_(num_batch);
auto func = [&latch_, &outer_invoke_idx](int inner_id, int inner_invoke_idx) {
try {
std::cout << "outer: " << outer_invoke_idx << ", inner: " << inner_invoke_idx << endl;
} catch (exception &ex) { cout << "error: " << ex.what() << endl; }
latch_.count_down();
};
for (int i = 0; i < num_batch; ++i) {
inner_tp.push(func, i);
}
latch_.wait_for(boost::chrono::milliseconds(1));
};
for (int i = 0; i < 5000; ++i) outer_tp.push(out_func, i);
outer_tp.stop(true);
return 0;
}
g++ -std=c++11 test.cpp -lboost_system -lpthread -lboost_chrono -lboost_thread
However I get the following error message.
bool boost::latch::count_down(boost::unique_lock&): Assertion `count_ > 0' failed.
If I use latch_.wait() instead of latch_.wait_for() or set very long wait time, the code works without error. Hence I guess 'time out' leads to this error issue. Does any one know how to fix the error.
There seem to be few issues with your code. I think that referring to latch_ in inner thread by reference is one of them. Replacing that with shared_ptr to boost::latch fixes that. Another issue is similar but with outer_invoke_idx. Fixing those and waiting for inner_tp to finish seems to make your test work just fine.
Here is modified test case that works for me:
#include <boost/thread/latch.hpp>
#include <memory>
#include <CTPL/ctpl.h>
#include <mutex>
#include <iostream>
using namespace std;
int main(int argc, char **argv) {
ctpl::thread_pool outer_tp(100);
ctpl::thread_pool inner_tp(5, 5000);
auto out_func = [&inner_tp](int outer_id, int outer_invoke_idx) {
int num_batch = 20;
auto latch_ = std::make_shared<boost::latch>(num_batch);
auto func = [latch_, outer_invoke_idx](int inner_id, int inner_invoke_idx) {
try {
std::cout << "outer: " << outer_invoke_idx << ", inner: " << inner_invoke_idx << endl;
} catch (exception &ex) { cout << "error: " << ex.what() << endl; }
latch_->count_down();
};
for (int i = 0; i < num_batch; ++i) {
inner_tp.push(func, i);
}
latch_->wait_for(boost::chrono::milliseconds(1));
};
for (int i = 0; i < 5000; ++i) outer_tp.push(out_func, i);
outer_tp.stop(true);
inner_tp.stop(true);
std::cout << "EXITING!!!" << std::endl;
return 0;
}
Related
My problem is that is access the kinect with the following code:
#include "libfreenect.hpp"
#include <iostream>
freenect_context* ctx;
freenect_device* dev;
void freenect_threadfunc(freenect_device* dev, void* v_depth, uint32_t timestamp){
short* d = (short*) v_depth;
std::cout << d[0] << std::endl;
}
int main(int argc, char const *argv[])
{
if(freenect_init(&ctx, NULL) < 0){
std::cout << "freenect_init() failed!" << std::endl;
}
if (freenect_open_device(ctx, &dev, 0) < 0){
std::cout << "No device found!" << std::endl;
freenect_shutdown(ctx);
}
freenect_set_depth_callback(dev, freenect_threadfunc);
freenect_set_depth_mode(dev, freenect_find_depth_mode(FREENECT_RESOLUTION_MEDIUM, FREENECT_DEPTH_11BIT));
freenect_start_depth(dev);
while (true) {
}
return 0;
}
But for some reason i don't know, the callback function ´freenect_threadfunc´ doesn't execute. When executing freenect-glview which is a example provided by Openkinect, everything works fine.
Thank you for your help.
This is about C ++ library boost.
The managed_mapped_file :: shrink_to_fit function works differently on Linux and Windows.
On Linux, this function succeeds even if the target instance exists.
However, on Windows, this function will fail if the target instance exists.
Is this correct behavior?
It seems correct to do the same behavior, is this a bug?
I put the sample code below.
Compilation environment
boost:version.1.65.1
Windows
VisualStudio2017
WSL(Ubuntu16.04)
Linux
UbuntuServer17.10,
Clang++5.0,
g++7.2.0
Compile with
clang++-5.0 -std=c++1z ./test.cpp -o test -lpthread
#define BOOST_DATE_TIME_NO_LIB
#include <boost/interprocess/managed_mapped_file.hpp>
#include <boost/interprocess/file_mapping.hpp>
#include <boost/interprocess/allocators/allocator.hpp>
#include <vector>
#include <iostream>
namespace bip = boost::interprocess;
using intAlloc = bip::allocator<int, bip::managed_mapped_file::segment_manager>;
using intVec = std::vector<int, intAlloc>;
int main() {
bip::managed_mapped_file *p_file_vec;
intVec *vecObj;
std::string fileName = "tmp.dat";
size_t fileSize = 1024 * 1024 * 1;
bip::file_mapping::remove(fileName.c_str());
p_file_vec = new bip::managed_mapped_file(bip::create_only, fileName.c_str(), fileSize);
vecObj = p_file_vec->construct<intVec>("myVecName")(p_file_vec->get_allocator<int>());
for (size_t i = 0; i < 10; i++)
{
vecObj->push_back(1 + 100);
}
p_file_vec->flush();
try
{ //Fail when execute on Windows(WSL),but Success on Linux(Ubuntu17.10).
std::cout << "try to shrink:pointer has existed yet!" << std::endl;
bip::managed_mapped_file::shrink_to_fit(fileName.c_str());
std::cout << "success to shrink!" << std::endl;
}
catch (const boost::interprocess::interprocess_exception &ex)
{
std::cerr << "fail to shrink!" << std::endl;
std::cerr << ex.what() << std::endl;;
}
std::cout <<"please pless enter key."<< std::endl;
std::cin.get();
try
{ //Success when execute on Windows(WSL) and Linux(Ubuntu17.10).
delete p_file_vec;
std::cout << "try to shrink:pointer has deleted!" << std::endl;
bip::managed_mapped_file::shrink_to_fit(fileName.c_str());
std::cout << "success to shrink!" << std::endl;
}
catch (const std::exception& ex)
{
std::cerr << "fail to shrink!" << std::endl;
std::cerr << ex.what() << std::endl;;
}
std::cout << "please pless enter key." << std::endl;
std::cin.get();
}
Don't use new and delete in C++ (rule of thumb).
Apart from that
delete p_file_vec;
does NOT delete anything physical. It effectively disconnects from the mapped file. This is also why shrink_to_fit works: the documentation explicitly says:
If the application can find a moment where no process is attached it can grow or shrink to fit the managed segment.
And here
So, in short: the behaviour is correct on both platforms. It's just UNDEFINED what happens in your case when you shrink while the mapped file is in use (on Ubuntu).
Fixed Code:
Live On Coliru
#include <boost/interprocess/managed_mapped_file.hpp>
#include <iostream>
#include <vector>
namespace bip = boost::interprocess;
using intAlloc = bip::allocator<int, bip::managed_mapped_file::segment_manager>;
using intVec = std::vector<int, intAlloc>;
int main() {
std::string const fileName = "tmp.dat";
bip::file_mapping::remove(fileName.c_str());
{
bip::managed_mapped_file file_vec(bip::create_only, fileName.c_str(), 1l << 20);
auto *vecObj = file_vec.construct<intVec>("myVecName")(file_vec.get_allocator<int>());
for (size_t i = 0; i < 10; i++) {
vecObj->push_back(1 + 100);
}
}
try { // Success when execute on Windows(WSL) and Linux(Ubuntu17.10).
std::cout << "try to shrink:pointer has deleted!" << std::endl;
bip::managed_mapped_file::shrink_to_fit(fileName.c_str());
std::cout << "success to shrink!" << std::endl;
} catch (const std::exception &ex) {
std::cerr << "fail to shrink!" << std::endl;
std::cerr << ex.what() << std::endl;
;
}
}
I am trying to use libuv to launch a process in a cross-platform way. To test the library, I have written a small C++ application that calls sleep 1 and then exits. The problem is that sometimes (~5% of the time) it crashes with the following error from libuv:
EFAULT bad address in system call argument
Here is my code:
#include <iostream>
#include <string>
#include <memory>
#include <cstring>
#include <uv.h>
char* a;
char* b;
char** args;
std::string error_to_string(int const& error) {
return std::string(uv_err_name(error)) +
" " +
std::string(uv_strerror(error));
}
void on_exit(uv_process_t* req, int64_t exit_status, int term_signal) {
std::cout << "I'm back! " << std::endl;
std::cout << "exit_status " << exit_status
<< " term_signal " << term_signal << std::endl;
uv_close((uv_handle_t*)req, nullptr);
}
int main(int argc, const char** argv) {
auto* loop = new uv_loop_t();
uv_loop_init(loop);
auto* process = new uv_process_t();
uv_process_options_t options = {};
a = new char[100];
b = new char[100];
strcpy(a, "sleep\0");
strcpy(b, "1\0");
args = new char*[2];
args[0] = a;
args[1] = b;
options.exit_cb = on_exit;
options.file = "sleep";
options.args = args;
std::cout << "Going to sleep..." << std::endl;
int const r = uv_spawn(loop, process, &options);
if (r < 0) {
std::cout << error_to_string(r) << std::endl;
return 1;
}
uv_run(loop, UV_RUN_DEFAULT);
return 0;
}
I am using libuv 1.11.0, Clang 4.0.1 and C++ 14.
Can you spot my mistake?
Your args array is set up wrong. It should be:
args = new char*[3];
args[0] = a;
args[1] = b;
args[2] = NULL;
Otherwise uv_spawn doesn't know where the end of the array is.
This question is a follow up for this question. I want threads to perform some work and pass handle to the next thread in order. When trying to execute the following code, I get
Unhandled exception at 0x0F7C1F5F (msvcp120d.dll) in ConsoleApplication9.exe: 0xC0000005 : Access violation reading location 0x00000004.
#include "stdafx.h"
#include <iostream>
#include <thread>
#include <mutex>
#include <chrono>
#include <condition_variable>
std::mutex* m_pMutexs;
std::condition_variable* m_pCVs;
int m_pCurrentWorker;
void func(int i)
{
int cvCurrentInd = i;
std::mutex* pCurMutex = &m_pMutexs[cvCurrentInd];
std::condition_variable* pCuCV = (std::condition_variable*)(m_pCurrentWorker + i*sizeof(std::condition_variable));
std::unique_lock<std::mutex> lk(m_pMutexs[i]);
while (i != m_pCurrentWorker)
{
pCuCV->wait(lk);
}
std::cout << "entered thread " << std::this_thread::get_id() << std::endl;
std::this_thread::sleep_for(std::chrono::seconds(rand() % 10));
std::cout << "leaving thread " << std::this_thread::get_id() << std::endl;
m_pCurrentWorker++;
lk.unlock();
pCuCV->notify_one();
}
int _tmain(int argc, _TCHAR* argv[])
{
m_pMutexs = new std::mutex[3];
m_pCVs = new std::condition_variable[3];
m_pCurrentWorker = 0;
srand((unsigned int)time(0));
std::thread t1(func,0);
std::thread t2(func,1);
std::thread t3(func,2);
t1.join();
t2.join();
t3.join();
return 0;
}
Have no idea what you're trying to do but
You're casting integer to pointer?
std::condition_variable* pCuCV = (std::condition_variable*)(m_pCurrentWorker + i*sizeof(std::condition_variable));
I think you should write instead:
std::condition_variable* pCuCV = &m_pCVs[i];
The whole function could be something like this:
void func(int i)
{
std::mutex* pCurMutex = &m_pMutexs[i];
std::condition_variable* pCuCV = &m_pCVs[i];
std::unique_lock<std::mutex> lk(m_pMutexs[i]);
while (i != m_pCurrentWorker) {
pCuCV->wait(lk);
}
std::cout << "entered thread " << std::this_thread::get_id() << std::endl;
std::this_thread::sleep_for(std::chrono::seconds(rand() % 2));
std::cout << "leaving thread " << std::this_thread::get_id() << std::endl;
m_pCurrentWorker++;
lk.unlock();
if (m_pCurrentWorker > 2) {
return;
}
pCuCV = &m_pCVs[m_pCurrentWorker];
pCuCV->notify_one();
}
I did some further research and it seems that the code the original questions is not thread-safe
I'm working on a project using C++.
I want a TimerHandler to be called after a specified time, but at the same time I don't want to block the current thread or any code after io.run() in the following code:
#include <iostream>
#include <string>
#include <boost/format.hpp>
#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
class TimerTest
{
public:
static void PrintOutTimerHandler(const boost::system::error_code&, const std::string& message)
{
std::cout << "PrintOutTimerHandler called: " << ", message: " << message << std::endl;
}
void run()
{
boost::asio::io_service io;
boost::asio::deadline_timer dt(io, boost::posix_time::seconds(5));
std::cout << "Start:\t" << std::endl;
dt.async_wait(boost::bind(PrintOutTimerHandler, boost::asio::placeholders::error, std::string("here is the message")));
// Do some job here
for (int i = 0; i < 1000000; ++i)
++i, --i;
std::cout << "End:\t" << std::endl;
io.run();
std::cout << "When to reach here 1: " << std::endl;
}
};
int main()
{
TimerTest tt;
tt.run();
std::cout << "When to reach here 2: " << std::endl;
return 0;
}
/* Current output:
Start:
End:
PrintOutTimerHandler called: , message: here is the message
When to reach here 1:
When to reach here 2:
*/
/* Expected output:
Start:
End:
When to reach here 1:
When to reach here 2:
PrintOutTimerHandler called: , message: here is the message
*/
I think I made myself clear. My questions are:
If this can be solved without
introducing a new thread, like Flex
ActionScript, that's is the best, but
I guess not (I guess ActionScript is
using a hidden thread);
If we have to
introduce an extra thread to do the
job, would you mind writing down the
pseudo code for me?
Thanks.
Peter
Here is an example . Run the io_service in a separate thread
asio::io_service io_service;
asio::thread t(boost::bind(&asio::io_service::run, &io_service));
or run it in a thread group
boost::thread_group threads;
for (std::size_t i = 0; i < my_thread_count; ++i)
threads.create_thread(boost::bind(&asio::io_service::run, &io_service));
Remember that your main thread should always run because when it exists all threads spawned will also exit.
I hope this helps.
I misunderstood what OrcunC said, but actually he is correct. Here is the modified version for your reference:
#include <iostream>
#include <string>
#include <boost/format.hpp>
#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <boost/thread.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
class TimerTest
{
public:
static void PrintOutTimerHandler(const boost::system::error_code&, const std::string& message)
{
std::cout << "PrintOutTimerHandler called: " << ", message: " << message << std::endl;
}
TimerTest(unsigned int timeout)
: dt(io, boost::posix_time::milliseconds(timeout))
{
}
void run()
{
std::cout << "Start:\t" << std::endl;
dt.async_wait(boost::bind(PrintOutTimerHandler, boost::asio::placeholders::error, std::string("here is the message")));
boost::thread thrd(boost::bind(&boost::asio::io_service::run, &io));
// Do some job here
for (int i = 0; i < 1000000; ++i)
++i, --i;
std::cout << "End:\t" << std::endl;
std::cout << "When to reach here 1: " << std::endl;
}
boost::asio::io_service io;
boost::asio::deadline_timer dt;
};
int main()
{
TimerTest tt(5000);
tt.run();
std::cout << "When to reach here 2: " << std::endl;
// Keep the main thread active for testing purpose. Otherwise,
// once the TimerTest object is destroyed when exiting the main() function,
// the sub thread spawed in tt.run() will also exit;
Sleep(10000);
}
/* Current output and Expected output:
Start:
End:
When to reach here 1:
When to reach here 2:
PrintOutTimerHandler called: , message: here is the message
*/