need to know that
boost::thread_group tgroup;
loop 10 times
tgroup.create_thread( boost::bind( &c , 2, 2, ) )
<==
tgroup.join_all()
What can i do at the <== location above to continuously print the number of threads who have completed there jobs
You can use an atomic counter: See it Live On Coliru
#include <boost/thread/thread.hpp>
#include <boost/atomic.hpp>
static boost::atomic_int running_count(20);
static void worker(boost::chrono::milliseconds effort)
{
boost::this_thread::sleep_for(effort);
--running_count;
}
int main()
{
boost::thread_group tg;
for (int i = 0, count = running_count; i < count; ++i) // count protects against data race!
tg.create_thread(boost::bind(worker, boost::chrono::milliseconds(i*50)));
while (running_count > 0)
{
std::cout << "Monitoring threads: " << running_count << " running\n";
boost::this_thread::sleep_for(boost::chrono::milliseconds(100));
}
tg.join_all();
}
Example output:
Monitoring threads: 19 running
Monitoring threads: 17 running
Monitoring threads: 15 running
Monitoring threads: 13 running
Monitoring threads: 11 running
Monitoring threads: 9 running
Monitoring threads: 7 running
Monitoring threads: 5 running
Monitoring threads: 3 running
Monitoring threads: 1 running
Another way would be to use a semaphore
The easiest way would be to print thread id at the end of job "c":
void c()
{
//some code here
some_safe_print << boost::this_thread::get_id();
}
That way, when thread will finish, the last instruction would be to print it's id.
Related
I am using strand to serialize certain processing within some objects. However, when the object dies, the strand element somehow refuses go away. Like a soul in purgatory, it manages to live in memory and causes memory usage to increase over days. I have managed to replicate the problem in a sample code.
I am creating 5 families, each with one parent and a child. The parent object contains the child and a strand object to ensure the processing happens in serial fashion. Each family is issued 3 processing tasks and they do it in the right order irrespective of the thread they run on. I am taking memory heap snapshot in VC++ before and after the object creation and processing. The snapshot comparison shows that the strand alone manages to live even after Parent and Child object have been destroyed.
How do I ensure strand object is destroyed? Unlike the sample program, my application runs for years without shutdown. I will be stuck with millions of zombie strand objects within a month.
#include <boost/thread.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/asio/strand.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <boost/noncopyable.hpp>
#include <boost/asio/io_service.hpp>
#include <boost/bind.hpp>
#include <boost/make_shared.hpp>
#include <boost/asio/yield.hpp>
#include <boost/log/attributes/current_thread_id.hpp>
#include <iostream>
boost::mutex mtx;
class Child : public boost::noncopyable, public boost::enable_shared_from_this<Child>
{
int _id;
public:
Child(int id) : _id(id) {}
void process(int order)
{
boost::this_thread::sleep_for(boost::chrono::seconds(2));
boost::lock_guard<boost::mutex> lock(mtx);
std::cout << "Family " << _id << " processing order " << order << " in thread " << std::hex << boost::this_thread::get_id() << std::endl;
}
};
class Parent : public boost::noncopyable, public boost::enable_shared_from_this<Parent>
{
boost::shared_ptr<Child> _child;
boost::asio::io_service::strand _strand;
public:
Parent(boost::asio::io_service& ioS, int id) : _strand(ioS)
{
_child = boost::make_shared<Child>(id);
}
void process()
{
for (int order = 1; order <= 3; order++)
{
_strand.post(boost::bind(&Child::process, _child, order));
}
}
};
int main(int argc, char* argv[])
{
boost::asio::io_service ioS;
boost::thread_group threadPool;
boost::asio::io_service::work work(ioS);
int noOfCores = boost::thread::hardware_concurrency();
for (int i = 0; i < noOfCores; i++)
{
threadPool.create_thread(boost::bind(&boost::asio::io_service::run, &ioS));
}
std::cout << "Take the first snapshot" << std::endl;
boost::this_thread::sleep_for(boost::chrono::seconds(10));
std::cout << "Creating families" << std::endl;
for (int family = 1; family <= 5; family++)
{
auto obj = boost::make_shared<Parent>(ioS,family);
obj->process();
}
std::cout << "Take the second snapshot after all orders are processed" << std::endl;
boost::this_thread::sleep_for(boost::chrono::seconds(60));
return 0;
}
The output looks like this:
Take the first snapshot
Creating families
Take the second snapshot after all orders are processed
Family 3 processing order 1 in thread 50c8
Family 1 processing order 1 in thread 5e38
Family 4 processing order 1 in thread a0c
Family 5 processing order 1 in thread 47e8
Family 2 processing order 1 in thread 5f94
Family 3 processing order 2 in thread 46ac
Family 2 processing order 2 in thread 47e8
Family 5 processing order 2 in thread a0c
Family 1 processing order 2 in thread 50c8
Family 4 processing order 2 in thread 5e38
Family 2 processing order 3 in thread 47e8
Family 4 processing order 3 in thread 5e38
Family 1 processing order 3 in thread 50c8
Family 5 processing order 3 in thread a0c
Family 3 processing order 3 in thread 46ac
I took the first heap snapshot before creating families. I took the second snapshot few seconds after all the 15 lines were printed (5 familes X 3 tasks). The heap comparison shows the following:
All the Parent and Child objects have gone away, but all the 5 strand objects lives on...
Edit: For those who don't understand shared_ptr, the objects don't die at the end of the loop. Since the reference of the child has been passed to 3 process tasks, at least child live a charmed life until all the tasks are completed for a given family. Once all references are cleared, Child object will die.
That's by design. A strand uses a pool of mutexes which live until the io_service dies.
But the pool size is limited currently to 193.
So you should not see more than 193 of those hanging around. See also issue #259.
According to the documentation
the currently-running fiber retains control until it invokes some
operation that passes control to the manager
I can think about only one operation - boost::this_fiber::yield which may cause control switch from fiber to fiber. However, when I run something like
bf::fiber([](){std::cout << "Bang!" << std::endl;}).detach();
bf::fiber([](){std::cout << "Bung!" << std::endl;}).detach();
I get output like
Bang!Bung!
\n
\n
Which means control was passed between << operators from one fiber to another. How it could happen? Why? What is the general definition of controll passing from fiber to fiber in the context of boost::fiber library?
EDIT001:
Cant get away without code:
#include <boost/fiber/fiber.hpp>
#include <boost/fiber/mutex.hpp>
#include <boost/fiber/barrier.hpp>
#include <boost/fiber/algo/algorithm.hpp>
#include <boost/fiber/algo/work_stealing.hpp>
namespace bf = boost::fibers;
class GreenExecutor
{
std::thread worker;
bf::condition_variable_any cv;
bf::mutex mtx;
bf::barrier barrier;
public:
GreenExecutor() : barrier {2}
{
worker = std::thread([this] {
bf::use_scheduling_algorithm<bf::algo::work_stealing>(2);
// wait till all threads joining the work stealing have been registered
barrier.wait();
mtx.lock();
// suspend main-fiber from the worker thread
cv.wait(mtx);
mtx.unlock();
});
bf::use_scheduling_algorithm<bf::algo::work_stealing>(2);
// wait till all threads have been registered the scheduling algorithm
barrier.wait();
}
template<typename T>
void PostWork(T&& functor)
{
bf::fiber {std::move(functor)}.detach();
}
~GreenExecutor()
{
cv.notify_all();
worker.join();
}
};
int main()
{
GreenExecutor executor;
std::this_thread::sleep_for(std::chrono::seconds(1));
int i = 0;
for (auto j = 0ul; j < 10; ++j) {
executor.PostWork([idx {++i}]() {
auto res = pow(sqrt(sin(cos(tan(idx)))), M_1_PI);
std::cout << idx << " - " << res << std::endl;
});
}
while (true) {
boost::this_fiber::yield();
}
return 0;
}
Output
2 - 1 - -nan
0.503334 3 - 4 - 0.861055
0.971884 5 - 6 - 0.968536
-nan 7 - 8 - 0.921959
0.9580699
- 10 - 0.948075
0.961811
Ok, there were a couple of things I missed, first, my conclusion was based on misunderstanding of how stuff works in boost::fiber
The line in the constructor mentioned in the question
bf::use_scheduling_algorithm<bf::algo::work_stealing>(2);
was installing the scheduler in the thread where the GreenExecutor instance was created (in the main thread) so, when launching two worker fibers I was actually initiating two threads which are going to process submitted fibers which in turn would process these fibers asynchronously thus mixing the std::cout output. No magic, everything works as expected, the boost::fiber::yield still is the only option to pass control from one fiber to another
I'm trying to launch new threads as soon as work in previous worker_thread has started, but maybe ended or not. I've replaced started and ended work with time delays. My code is:
#include <iostream>
#include <string>
#include <mutex>
#include <condition_variable>
#include <future>
#include <atomic>
#include <chrono>
#include <thread>
std::mutex m;
std::condition_variable cv;
bool started = false;
void worker_thread()
{
std::unique_lock<std::mutex> lk(m);
static std::atomic<int> count(1);
std::this_thread::sleep_for(std::chrono::milliseconds{(count % 5) * 100});
std::cerr << "Start Worker thread: " << count << "\n";
started = true;
lk.unlock();
cv.notify_one();
std::this_thread::sleep_for(std::chrono::milliseconds{3000});
std::cerr << "Exit Worker thread: " << count << "\n";
++count;
}
int main()
{
while(1) {
std::async(std::launch::async, worker_thread);
std::unique_lock<std::mutex> lk(m);
cv.wait(lk, []{return started;});
started = false;
}
}
The output looks like that:
Start Worker thread: 1
Exit Worker thread: 1
Start Worker thread: 2
Exit Worker thread: 2
Start Worker thread: 3
Exit Worker thread: 3
Start Worker thread: 4
Exit Worker thread: 4
Start Worker thread: 5
Exit Worker thread: 5
which isn't the behavior I wanted. What I wanted was something like (not exactly) this:
Start Worker thread: 1
Start Worker thread: 2
Start Worker thread: 3
Start Worker thread: 4
Exit Worker thread: 1
Exit Worker thread: 3
Exit Worker thread: 4
Exit Worker thread: 2
Start Worker thread: 5
Exit Worker thread: 5
Currently the next thread is only started when work is finished in previous thread. But I want to start next thread as soon as work is started in previous thread and not wait for it's end, only wait for start.
std::async returns a std::future holding result of function execution. In your case, it is a temporary object which is immideatly destroyed. The documentation for std::future says:
these actions will not block for the shared state to become ready, except that it may block if all of the following are true:
✔ the shared state was created by a call to std::async
✔ the shared state is not yet ready
✔ this was the last reference to the shared state
All of those are true, so destruction of that future will block until worker function will finish executing.
You can create detached thread to avoid this problem:
std::thread(worker_thread).detach();
I am trying to do a program that has to run 2 tasks periodically.
That is, for example, run task 1 every 10 seconds, and run task 2 every 20 seconds.
What I am thinking is to create two threads, each one with a timer. Thread 1 launches a new thread with task 1 every 10 seconds. and Thread 2 launches a new thread with task 2 every 20 seconds.
My doubt is, how to launch a new task 1 if the previous task 1 hasn't finished?
while (true)
{
thread t1 (task1);
this_thread::sleep_for(std::chrono::seconds(10));
t1.join();
}
I was trying this, but this way it will only launch a new task 1 when the previous one finishes.
EDIT:
Basically I want to implement a task scheduler.
Run task1 every X seconds.
Run task2 every Y seconds.
I was thinking in something like this:
thread t1 (timer1);
thread t2 (timer2);
void timer1()
{
while (true)
{
thread t (task1);
t.detach()
sleep(X);
}
}
the same for timer2 and task2
Perhaps you could create a periodic_task handler that is responsible for scheduling one task every t seconds. And then you can launch a periodic_task with a specific function and time duration from anywhere you want to in your program.
Below I've sketched something out. One valid choice is to detach the thread and let it run forever. Another is to include cancellation to allow the parent thread to cancel/join. I've included functionality to allow the latter (though you could still just detach/forget).
#include <condition_variable>
#include <functional>
#include <iostream>
#include <mutex>
#include <thread>
class periodic_task
{
std::chrono::seconds d_;
std::function<void()> task_;
std::mutex mut_;
std::condition_variable cv_;
bool cancel_{false};
public:
periodic_task(std::function<void()> task, std::chrono::seconds s)
: d_{s}
, task_(std::move(task))
{}
void
operator()()
{
std::unique_lock<std::mutex> lk{mut_};
auto until = std::chrono::steady_clock::now();
while (true)
{
while (!cancel_ && std::chrono::steady_clock::now() < until)
cv_.wait_until(lk, until);
if (cancel_)
return;
lk.unlock();
task_();
lk.lock();
until += d_;
}
}
void cancel()
{
std::unique_lock<std::mutex> lk{mut_};
cancel_ = true;
cv_.notify_one();
}
};
void
short_task()
{
std::cerr << "short\n";
}
void
long_task(int i, const std::string& message)
{
std::cerr << "long " << message << ' ' << i << '\n';
}
int
main()
{
using namespace std::chrono_literals;
periodic_task task_short{short_task, 7s};
periodic_task task_long{[](){long_task(5, "Hi");}, 13s};
std::thread t1{std::ref(task_short)};
std::this_thread::sleep_for(200ms);
std::thread t2{std::ref(task_long)};
std::this_thread::sleep_for(1min);
task_short.cancel();
task_long.cancel();
t1.join();
t2.join();
}
You want to avoid using thread::join() it, by definition, waits for the thread to finish. Instead, use thread::detach before sleeping, so it doesn't need to wait.
I'd suggest reading up on it http://www.cplusplus.com/reference/thread/thread/detach/
I'm using boost::asio::io_service as a basic thread pool. Some threads get added to io_service, the main thread starts posting handlers, the worker threads start running the handlers, and everything finishes. So far, so good; I get a nice speedup over single-threaded code.
However, the main thread has millions of things to post. And it just keeps on posting them, much faster than the worker threads can handle them. I don't hit RAM limits, but it's still kind of silly to be enqueuing so many things. What I'd like to do is have a fixed-size for the handler queue, and have post() block if the queue is full.
I don't see any options for this in the Boost ASIO docs. Is this possible?
I'm using the semaphore to fix the handlers queue size. The following code illustrate this solution:
void Schedule(boost::function<void()> function)
{
semaphore.wait();
io_service.post(boost::bind(&TaskWrapper, function));
}
void TaskWrapper(boost::function<void()> &function)
{
function();
semaphore.post();
}
You can wrap your lambda in another lambda which would take care of counting the "in-progress" tasks, and then wait before posting if there are too many in-progress tasks.
Example:
#include <atomic>
#include <chrono>
#include <future>
#include <iostream>
#include <mutex>
#include <thread>
#include <vector>
#include <boost/asio.hpp>
class ThreadPool {
using asio_worker = std::unique_ptr<boost::asio::io_service::work>;
boost::asio::io_service service;
asio_worker service_worker;
std::vector<std::thread> grp;
std::atomic<int> inProgress = 0;
std::mutex mtx;
std::condition_variable busy;
public:
ThreadPool(int threads) : service(), service_worker(new asio_worker::element_type(service)) {
for (int i = 0; i < threads; ++i) {
grp.emplace_back([this] { service.run(); });
}
}
template<typename F>
void enqueue(F && f) {
std::unique_lock<std::mutex> lock(mtx);
// limit queue depth = number of threads
while (inProgress >= grp.size()) {
busy.wait(lock);
}
inProgress++;
service.post([this, f = std::forward<F>(f)]{
try {
f();
}
catch (...) {
inProgress--;
busy.notify_one();
throw;
}
inProgress--;
busy.notify_one();
});
}
~ThreadPool() {
service_worker.reset();
for (auto& t : grp)
if (t.joinable())
t.join();
service.stop();
}
};
int main() {
std::unique_ptr<ThreadPool> pool(new ThreadPool(4));
for (int i = 1; i <= 20; ++i) {
pool->enqueue([i] {
std::string s("Hello from task ");
s += std::to_string(i) + "\n";
std::cout << s;
std::this_thread::sleep_for(std::chrono::seconds(1));
});
}
std::cout << "All tasks queued.\n";
pool.reset(); // wait for all tasks to complete
std::cout << "Done.\n";
}
Output:
Hello from task 3
Hello from task 4
Hello from task 2
Hello from task 1
Hello from task 5
Hello from task 7
Hello from task 6
Hello from task 8
Hello from task 9
Hello from task 10
Hello from task 11
Hello from task 12
Hello from task 13
Hello from task 14
Hello from task 15
Hello from task 16
Hello from task 17
Hello from task 18
All tasks queued.
Hello from task 19
Hello from task 20
Done.
you could use the strand object to put the events and put a delay in your main ? Is your program dropping out after all the work is posted? If so you can use the work object which will give you more control over when your io_service stops.
you could always main check the state of the threads and have it wait untill one becomes free or something like that.
//links
http://www.boost.org/doc/libs/1_40_0/doc/html/boost_asio/reference/io_service__strand.html
http://www.boost.org/doc/libs/1_40_0/doc/html/boost_asio/reference/io_service.html
//example from the second link
boost::asio::io_service io_service;
boost::asio::io_service::work work(io_service);
hope this helps.
Maybe try lowering the priority of the main thread so that once the worker threads get busy they starve the main thread and the system self limits.