Best way to delete job context objects in a pipelined processor - c++

I'd appreciate it if someone suggests a way to finally delete context objects used represent a job processed through a pipeline of steps.
Here in the following code an object of class text_file_processing_request is created and sent to the io_service. My pipeline here is made up of one step, there could be more steps in real code.
Now, I would like to get opinions on the best way to delete these objects of type text_file_processing_request once they are done with.
Thank you!
#include <iostream>
#include "boost/asio.hpp"
#include "boost/thread.hpp"
using namespace std;
namespace asio = boost::asio;
typedef std::unique_ptr<asio::io_service::work> work_ptr;
typedef boost::function<void(void) > parse_and_aggregate_fun_t;
class file_processing_request{
public:
virtual void process(int num) = 0;
};
class text_file_processing_request : public file_processing_request {
public:
virtual void process(int num) {
cout << "text_file_processing_request::process " << num << endl;
}
};
class processor {
public:
processor(int threads) : thread_count(threads) {
service = new asio::io_service();
work = new work_ptr(new asio::io_service::work(*(service)));
for (int i = 0; i < this->thread_count; ++i)
workers.create_thread(boost::bind(&asio::io_service::run, service));
}
void post_task(parse_and_aggregate_fun_t job){
this->service->post(job);
}
void stop(){
this->work->reset();
}
void wait(){
this->workers.join_all();
}
private:
int thread_count;
work_ptr * work;
asio::io_service* service;
boost::thread_group workers;
};
class job_discoverer {
public:
job_discoverer(processor *p): worker(p){}
void start_producing(){
do {
file_processing_request * cPtr = new text_file_processing_request();
this->worker->post_task(boost::bind(&file_processing_request::process, cPtr, 42));
} while (0);
this->worker->stop(); // no more data to process
}
private:
processor *worker;
};
int main(int argc, char** argv) {
processor *pr = new processor(4);
job_discoverer disocverer(pr);
disocverer.start_producing();
pr->wait();
delete pr;
return 0;
}

Related

Comparison of methods for multithreading with multiple objects in C++

I'm working on C++ code for a 'manager' class that runs a process in multiple member objects in separate threads and returns a set of values. I see three basic ways I can implement this:
create each thread with the member function for the relevant object and a callback mechanism to return the values;
provide an auxiliary function in the manager class that calls the member function for a specified object and create separate threads with this auxiliary function; or
create each thread with the member function for the relevant object (as in method #1) and pass pointers to variables to hold the return values.
My question is, are there compelling reasons to choose one method over the other, in terms of performance or other factors, keeping in mind the fact that the actual application would have an array or vector of an indeterminate number of objects (unlike the examples below)?
An example of the first method would look like this:
#include <thread>
#include <iostream>
#include <functional>
using namespace std;
using namespace std::placeholders;
typedef function<void(string, int)> Callback;
class Processor {
private:
string name;
Callback cb_func;
public:
Processor(string nme, Callback f) : name(nme), cb_func(f) { }
void do_stuff(int lim) { cb_func(name, rand() % lim); }
};
class Manager {
private:
Processor *p0, *p1;
public:
Manager() {
p0 = new Processor("lizard", std::bind(&Manager::report, this, _1, _2));
p1 = new Processor("ferret", std::bind(&Manager::report, this, _1, _2));
}
~Manager() {
delete p0;
delete p1;
}
void manage() {
thread t0 = thread(&Processor::do_stuff, p0, 100);
thread t1 = thread(&Processor::do_stuff, p1, 100);
t0.join();
t1.join();
}
void report(string source, int value) {
cout << source << " reports " << value << endl;
}
};
int main() {
Manager the_dude;
the_dude.manage();
return 0;
}
An example of the second method would look like this:
#include <thread>
#include <iostream>
using namespace std;
class Processor {
private:
string name;
public:
Processor(string nme) : name(nme) { }
int do_stuff(int lim) { return rand() % lim; }
string get_name() { return name; }
};
class Manager {
private:
Processor *p0, *p1;
public:
Manager() {
p0 = new Processor("lizard");
p1 = new Processor("ferret");
}
~Manager() {
delete p0;
delete p1;
}
void work(Processor *p, int lim) {
cout << p->get_name() << " reports " << p->do_stuff(lim) << endl;
}
void manage() {
thread t0 = thread(&Manager::work, this, p0, 100);
thread t1 = thread(&Manager::work, this, p1, 100);
t0.join();
t1.join();
}
};
int main() {
Manager the_dude;
the_dude.manage();
return 0;
}
And an example of the third method would look like this:
#include <thread>
#include <iostream>
using namespace std;
class Processor {
private:
string name;
public:
Processor(string nme) : name(nme) { }
void do_stuff(int lim, string *nme, int *val) { *nme = name; *val = rand() % lim; }
};
class Manager
{
private:
Processor *p0, *p1;
string s0, s1;
int v0, v1;
public:
Manager() {
p0 = new Processor("lizard");
p1 = new Processor("ferret");
}
~Manager() {
delete p0;
delete p1;
}
void manage() {
thread t0 = thread(&Processor::do_stuff, p0, 100, &s0, &v0);
thread t1 = thread(&Processor::do_stuff, p1, 100, &s1, &v1);
t0.join();
t1.join();
report(s0, v0);
report(s1, v1);
}
void report(string source, int value) {
cout << source << " reports " << value << endl;
}
};
int main()
{
Manager the_dude;
the_dude.manage();
return 0;
}

Thread pool not completing all tasks

I have asked a simpler version of this question before and got the correct answer: Thread pools not working with large number of tasks
Now I am trying to run tasks from an object of a class in parallel using a thread pool. My task is simple and only prints a number for that instance of class. I am expecting numbers 0->9 get printed but instead I get some numbers get printed more than once and some numbers not printed at all. Can anyone see what I am doing wrong with creating tasks in my loop?
#include "iostream"
#include "ThreadPool.h"
#include <chrono>
#include <thread>
using namespace std;
using namespace dynamicThreadPool;
class test {
int x;
public:
test(int x_in) : x(x_in) {}
void task()
{
cout << x << endl;
}
};
int main(void)
{
thread_pool pool;
for (int i = 0; i < 10; i++)
{
test* myTest = new test(i);
std::function<void()> myFunction = [&] {myTest->task(); };
pool.submit(myFunction);
}
while (!pool.isQueueEmpty())
{
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
cout << "waiting for tasks to complete" << endl;
}
return 0;
}
And here is my thread pool, I got this definition from "C++ Concurrency in Action" book:
#pragma once
#include <queue>
#include <future>
#include <list>
#include <functional>
#include <memory>
template<typename T>
class threadsafe_queue
{
private:
mutable std::mutex mut;
std::queue<T> data_queue;
std::condition_variable data_cond;
public:
threadsafe_queue() {}
void push(T new_value)
{
std::lock_guard<std::mutex> lk(mut);
data_queue.push(std::move(new_value));
data_cond.notify_one();
}
void wait_and_pop(T& value)
{
std::unique_lock<std::mutex> lk(mut);
data_cond.wait(lk, [this] {return !data_queue.empty(); });
value = std::move(data_queue.front());
data_queue.pop();
}
bool try_pop(T& value)
{
std::lock_guard<std::mutex> lk(mut);
if (data_queue.empty())
return false;
value = std::move(data_queue.front());
data_queue.pop();
return true;
}
bool empty() const
{
std::lock_guard<std::mutex> lk(mut);
return data_queue.empty();
}
};
class join_threads
{
std::vector<std::thread>& threads;
public:
explicit join_threads(std::vector<std::thread>& threads_) : threads(threads_) {}
~join_threads()
{
for (unsigned long i = 0; i < threads.size(); i++)
{
if (threads[i].joinable())
{
threads[i].join();
}
}
}
};
class thread_pool
{
std::atomic_bool done;
threadsafe_queue<std::function<void()> > work_queue;
std::vector<std::thread> threads;
join_threads joiner;
void worker_thread()
{
while (!done)
{
std::function<void()> task;
if (work_queue.try_pop(task))
{
task();
}
else
{
std::this_thread::yield();
}
}
}
public:
thread_pool() : done(false), joiner(threads)
{
unsigned const thread_count = std::thread::hardware_concurrency();
try
{
for (unsigned i = 0; i < thread_count; i++)
{
threads.push_back(std::thread(&thread_pool::worker_thread, this));
}
}
catch (...)
{
done = true;
throw;
}
}
~thread_pool()
{
done = true;
}
template<typename FunctionType>
void submit(FunctionType f)
{
work_queue.push(std::function<void()>(f));
}
bool isQueueEmpty()
{
return work_queue.empty();
}
};
There's too much code to analyse all of it but you take a pointer by reference here:
{
test* myTest = new test(i);
std::function<void()> myFunction = [&] {myTest->task(); };
pool.submit(myFunction);
} // pointer goes out of scope
After that pointer has gone out of scope you will have undefined behavior if you later do myTest->task();.
To solve that immediate problem, copy the pointer and delete the object afterwards to not leak memory:
{
test* myTest = new test(i);
std::function<void()> myFunction = [=] {myTest->task(); delete myTest; };
pool.submit(myFunction);
}
I suspect this could be solved without using new at all, but I'll leave that up to you.

C++ function does not exit at the end of main after return 0

I was implementing a multi-threading database using a thread pool. Everything was fine and the functions can execute all the codes before return 0.
However, the function does not end after the return 0 in main(). I used _Exit(0) to force exit, which is not very nasty. I ran it with valgrind and there is no memory leak until the end of function.
As you might see in the picture, all the threads are detached, so I shouldn't be running into trouble with threads. But what could go run such that the program can't stop?
auto rwfunc = [](int &id,struct rwinfo &_rwinfo){
Qtable.vec_qpvec[_rwinfo.tableid][id].iswriter?
Writer(id,_rwinfo):Reader(id,_rwinfo);};
//my lambda function to insert my function into the thread
this_thread::yield();
if (COPYFLAG){
for (unsigned int i = 0; i < Qtable.tablenum; ++i) {
for (int j = 0; j < info_vec[i].vecsize; ++j) {
pool.push(rwfunc,j,info_vec[i]);
}
}
}
//pushing function into the pool
Minimal reproducible example Definition and Thread pool
#include <getopt.h>
#include <fstream>
#include <iostream>
#include <string>
#include <mutex>
#include <thread>
#include <condition_variable>
#include <sstream>
#include <iostream>
#include <semaphore.h>
#include <queue>
#include <functional>
//#pragma once
#include<thread>
#include<vector>
#include<queue>
#include<mutex>
#include<condition_variable>
#include<functional>
#include<future>
//////////////////////////
#define MAX_THREADS std::thread::hardware_concurrency() - 1;
bool EXITFLAG = false;
bool COPYFLAG = false;
//portable way to null the copy and assignment operators
#define NULL_COPY_AND_ASSIGN(T) \
T(const T& other) {(void)other;} \
void operator=(const T& other) { (void)other; }
/* ThreadPool class
It is a singleton. To prevent spawning
tons of threads, I made it a singleton */
class ThreadPool{
public:
//getInstance to allow the second constructor to be called
static ThreadPool& getInstance(int numThreads){
static ThreadPool instance(numThreads);
return instance;
}
void waitfinish(){
for (int i = 0; i < numThreads; ++i) {
}
Pool.clear();
}
//add any arg # function to queue
template <typename Func, typename... Args >
inline auto push(Func&& f, Args&&... args){
//get return type of the function
typedef decltype(f(args...)) retType;
//package the task
std::packaged_task<retType()> task(std::move(std::bind(f, args...)));
// lock jobqueue mutex, add job to the job queue
std::unique_lock<std::mutex> lock(JobMutex);
//get the future from the task before the task is moved into the jobqueue
std::future<retType> future = task.get_future();
//place the job into the queue
JobQueue.emplace( std::make_shared<AnyJob<retType> > (std::move(task)) );
//notify a thread that there is a new job
thread.notify_one();
//return the future for the function so the user can get the return value
return future;
}
inline int getThreadCount(){
return numThreads;
}
private:
//used polymorphism to store any type of function in the job queue
class Job {
private:
std::packaged_task<void()> func;
public:
virtual ~Job() {}
virtual void execute() = 0;
};
template <typename RetType>
class AnyJob : public Job {
private:
std::packaged_task<RetType()> func;
public:
AnyJob(std::packaged_task<RetType()> func) : func(std::move(func)) {}
void execute() {
func();
}
};
// end member classes
//member variables
int numThreads; // number of threads in the pool
std::vector<std::thread> Pool; //the actual thread pool
std::queue<std::shared_ptr<Job>> JobQueue;
std::condition_variable thread;// used to notify threads about available jobs
std::mutex JobMutex; // used to push/pop jobs to/from the queue
//end member variables
/* infinite loop function */
inline void threadManager() {
while (!EXITFLAG) {
std::unique_lock<std::mutex> lock(JobMutex);
thread.wait(lock, [this] {return !JobQueue.empty(); });
//strange bug where it will continue even if the job queue is empty
if (JobQueue.size() < 1)
continue;
(*JobQueue.front()).execute();
JobQueue.pop();
}
std::cerr<<"thread end!"<<std::endl;
}
/* Constructors */
ThreadPool(); //prevent default constructor from being called
//real constructor that is used
inline explicit ThreadPool(int _numThreads) : numThreads(_numThreads) {
int tmp = MAX_THREADS;
if(numThreads > tmp){
numThreads = tmp;
}
Pool.reserve(numThreads);
std::cerr<<"Thread pool core num: "<<numThreads<<std::endl;
for(int i = 0; i != numThreads; ++i){
Pool.emplace_back(std::thread(&ThreadPool::threadManager, this));
Pool.back().detach();
}
}
/* end constructors */
NULL_COPY_AND_ASSIGN(ThreadPool);
}; /* end ThreadPool Class */
using namespace std;
int COUNTER = 0;
mutex id_mtx;
struct rwinfo{
sem_t &FINISHED;
rwinfo(sem_t &finished):
FINISHED(finished)
{}
};
void work_todo(int &id,struct rwinfo &_rwinfo){
id_mtx.lock();
cout<<"Job "<<id<<" is done."<<endl;
COUNTER++;
cerr<<"COUNTER is now : "<<COUNTER<<endl;
if (COUNTER==10){
sem_post(&_rwinfo.FINISHED);
}
std::this_thread::sleep_for(500ms);
id_mtx.unlock();
}
ThreadPool& pool = ThreadPool::getInstance(8);
int main(int argc, char *argv[]) {
std::ios_base::sync_with_stdio(false);
sem_t FINISHED;
sem_init(&FINISHED,1,0);
auto mylambdafunc = [](int &i,struct rwinfo &_rwinfo){work_todo(i,_rwinfo);};
auto A = rwinfo(FINISHED);
for (int i = 0; i < 10; ++i) {
pool.push(mylambdafunc,i,A);
}
cerr<<"Start waiting"<<endl;
sem_wait(&FINISHED);
cerr<<"wake up"<<endl;
EXITFLAG = true;
cerr<<"Leaving"<<endl;
return 0;
}
Main
int main(int argc, char *argv[]) {
std::ios_base::sync_with_stdio(false);
sem_t FINISHED;
sem_init(&FINISHED,1,0);
auto mylambdafunc = [](int &i,struct rwinfo &_rwinfo){work_todo(i,_rwinfo);};
auto A = rwinfo(FINISHED);
for (int i = 0; i < 10; ++i) {
pool.push(mylambdafunc,i,A);
}
cerr<<"Start waiting"<<endl;
sem_wait(&FINISHED);
cerr<<"wake up"<<endl;
EXITFLAG = true;
cerr<<"Leaving"<<endl;
return 0;
}
This example can sometimes stuck and sometimes return correctly. I guess it is because it is a lot less jobs to do and jobs are a lot faster.
Also,another question. I was writing a mutithreading database. Some queries will change the data table and some will not. I treated it as the classic reader writer problem and queued every query as a job into the job queue of the thread pool.
The strange thing is that, The program runs actually fastest when there is only 1 thread in the thread pool. When it has 8 threads, it works a lot slower. I'm sure that the thread number in the thread pool is at most std::thread::hardware_concurrency() -1
What could be the possible reason?

How to transfer a class type to a function template for new operation as a parameter?

I have a piece of c++ code:
#include <iostream>
#include <string>
#include <map>
static counter = 0;
class Probe
{
private:
int supply_;
Probe(const Probe&);
public:
Probe()
{
supply_ = 10000;
}
int get_supply()
{
return supply_;
}
};
/********************************************************************************
template<class T> T Create(int counter, T& produced)
{
produced[counter] = new ; // ??????????????????????????????????????
return produced;
}
************************************************************************************/
std::map<int, Probe*> CreatInitWorkers(int counter, std::map<int, Probe*> &init_workers)
{
init_workers[counter] = new Probe();
return init_workers;
}
int main()
{
std::map<int, Probe*> workers;
for (int i = 0; i < 12; i++)
{
workers = CreatInitWorkers(worker_counter++, workers);
}
for (auto it : workers)
{
std::cout << it.first << std::endl;
}
}
I want to create a template function (as it shows between the stars) like the CreatInitWorkers function. But I don't know how to transfer the Probe class to the new operation because for my program there are still other classes needed to be there. Is there any way can do it? Thanks.
Something along these lines:
template<class T> T Create(int counter, T& produced)
{
using C = std::remove_pointer_t<std::decay_t<decltype(produced[counter])>>;
produced[counter] = new C();
return produced;
}
Demo

Correct way to create thread_safe shared_ptr without a lock?

I'm trying to create a class with a thread-safe shared_ptr. My use case is that the shared_ptr belongs to an object of the class, and behaves sort of like a singleton (the CreateIfNotExist function can be run by any thread at any point in time).
Essentially if the pointer is null, the first thread that sets it's value wins, and all other threads that are creating it at the same time use the winning thread's value.
Here is what I have so far (note that the only function in question is the CreateIfNotExist() function, rest is for testing purposes):
#include <memory>
#include <iostream>
#include <thread>
#include <vector>
#include <mutex>
struct A {
A(int a) : x(a) {}
int x;
};
struct B {
B() : test(nullptr) {}
void CreateIfNotExist(int val) {
std::shared_ptr<A> newPtr = std::make_shared<A>(val);
std::shared_ptr<A> _null = nullptr;
std::atomic_compare_exchange_strong(&test, &_null, newPtr);
}
std::shared_ptr<A> test;
};
int gRet = -1;
std::mutex m;
void Func(B* b, int val) {
b->CreateIfNotExist(val);
int ret = b->test->x;
if(gRet == -1) {
std::unique_lock<std::mutex> l(m);
if(gRet == -1) {
gRet = ret;
}
}
if(ret != gRet) {
std::cout << " FAILED " << std::endl;
}
}
int main() {
B b;
std::vector<std::thread> threads;
for(int i = 0; i < 10000; ++i) {
threads.clear();
for(int i = 0; i < 8; ++i) threads.emplace_back(&Func, &b, i);
for(int i = 0; i < 8; ++i) threads[i].join();
}
}
Is this the correct way to do this? Is there a better way to ensure that all threads calling CreateIfNotExist() at the same time all use the same shared_ptr?
Something along these lines perhaps:
struct B {
void CreateIfNotExist(int val) {
std::call_once(test_init,
[this, val](){test = std::make_shared<A>(val);});
}
std::shared_ptr<A> test;
std::once_flag test_init;
};