Using boost::asio::post for a function that takes in parameters - c++

I'm new to using boost, and threadpools. I want to pass a function to a threadpool that takes a variable as a parameter. In this simple example I'm just passing in an integer. My understanding is post is going to call an available thread in the thread pool to do something. The code compiles if I set up printProduct to not take in any variables, but that's not what I'm eventually trying to do.
References to relevant documentation would be very helpful (I haven't successfully found much discussion of boost::asio::post), as well as advice on how to solve the problem. Thanks!
#include <cstdlib>
#include <iostream>
#include <pthread.h>
#include <boost/version.hpp> // version is 1.72
#include <boost/asio.hpp>
#include <boost/asio/io_service.hpp>
#include <boost/bind.hpp>
#include <boost/thread/thread.hpp>
#include <boost/thread/thread_pool.hpp>
#include <boost/asio/thread_pool.hpp>
#include <boost/asio/post.hpp>
#include <boost/lockfree/queue.hpp>
using namespace std;
int printProduct(int endval){
// int endval = 1000000;
int prod = 1;
for (int i=0;i<endval;i++){
prod = prod * i;
}
return prod;
}
int main() {
boost::asio::thread_pool tp(8);
for (int i =0; i<200; i++){
// issue is how to pass the parameter into post
boost::asio::post(tp, printProduct,i);
// boost::asio::post(tp, printProduct(i));
}
}

boost::asio::post takes any callable object. Requirements for such object you can find here.
There are many ways to achive what you want:
[1] lambda expressions
boost::asio::post(tp, [i]{ printProduct(i); });
[2] bind
boost::asio::post(tp, std::bind(printProduct,i));
[3] custom functor class
struct Wrapper {
int i;
Wrapper(int i) : i(i) {}
void operator()() {
printProduct(i);
}
};
boost::asio::post(Wrapper{i});

Related

How to declare a <vector> object and use push_back inside a class?

I'm trying to build a class named "Tombola" which should contain as private variable an empty vector. This should be filled at runtime through the class member Tombola.estrai(), which generates a random number and insert it inside the vector named "order" by the method order.push_back(number). This is the class definition in the tombola.h header:
#ifndef TOMBOLA_H
#define TOMBOLA_H
#include <cstdlib>
#include <vector>
using namespace std;
class Tombola {
private:
bool on_off[90];
int tabellone[9][10];
int x_max = 9;
int y_max = 10;
vector<int> order;
public:
Tombola();
~Tombola();
void nuovo();
int estrai();
bool completato();
void stampa();
void stampa_tab();
};
#endif
And this is the implementation of constructor/destructor and Tombola::estrai() inside tombola.cc:
#include "tombola.h"
#include <cstdlib>
#include <cmath>
#include <ctime>
#include <vector>
#include <iostream>
using namespace std;
Tombola::Tombola () {
vector<int> ord;
order = ord;
int z=1;
for(int i=0;i<90;i++) {
on_off[i] = false;
}
for(int j=0;j<=x_max;j++) {
for (int k=0;k<=y_max;k++) {
tabellone[j][k] = z;
z++;
}
}
}
Tombola::~Tombola() {
cout << "Tombola is destroyed" << endl;
}
int Tombola::estrai() {
srand(time(NULL));
int estrazione = int(ceil(rand()/double(RAND_MAX)*90));
on_off[estrazione]==true;
order.push_back(estrazione);
return order.back();
}
and this is the call to the method in the main.cpp file:
#include "tombola.h"
#include <cstdlib>
#include <iostream>
#include <vector>
#include <ctime>
using namespace std;
int main () {
Tombola natale;
cout << natale.estrai();
}
When I compile the program everything goes fine, but when I execute the main I get a segmentation fault error which seems to be due to some sort of allocation error when trying to store the item inside the order vector, as reported by the debugger. Could someone explain to me how to solve the error and why the error occours? Thank you.
The reason of segmentation fault is in the constructor. You have to change for(int j=0;j<=x_max;j++) to for(int j=0;j<x_max;j++) in order not to cross the bounds of the array.
for(int j=0;j<x_max;j++) {
for (int k=0;k<y_max;k++) {
tabellone[j][k] = z;
z++;
}
}
However, there are also some minor issues in the code that are worth being mentioned
declaring default-initialized ord vector and assigning it to order is pointless because order is already default-initialized.(See member initializer list for more information).
using namespace std; in a header file is a terrible idea, because if you had a large codebase, and had multiple source files where you want to include that header, everywhere the using statement will be applied, which probably is not desired.

C++ Compilation error about running io_context in different thread

I am trying to use the asio::io_context in multiple threads.
#include <iostream>
#include <vector>
#include <asio.hpp>
#include <thread>
#include <future>
#include <functional>
int main()
{
asio::io_context ctx;
std::vector<std::future<asio::io_context::count_type>> tasks;
for(int i = 0; i < 3; ++i)
{
tasks.push_back(std::async(std::launch::async, std::bind(&asio::io_context::run, &ctx));
}
for(auto &task: tasks){tasks.get();}
return 0;
}
However, I am getting a compilation error
asio_blah.cpp: In function ‘int main()’:
asio_blah.cpp:101:94: error: no matching function for call to ‘bind(<unresolved overloaded function type>, asio::io_context*)’
tasks.push_back(std::async(std::launch::async, std::bind(&asio::io_context::run, &ctx));
Not sure whey the compiler is not able to figure the member function pointer ( I believe the member func type is asio::io_context::count_type (asio::io_context*)() and the function signature should visible to the compiler since asio.hpp is included) and report the error unresolved overloaded function type.
Any suggestions to fix the error?
You may go for lambda something like this:
#include <iostream>
#include <vector>
#include <boost/asio.hpp>
#include <thread>
#include <future>
#include <functional>
using namespace boost;
int main()
{
asio::io_context ctx;
std::vector<std::future<asio::io_context::count_type>> tasks;
for(int i = 0; i < 3; ++i)
{
tasks.push_back(std::async(std::launch::async, [&ctx]() {
return ctx.run();
}));
}
for(auto &task: tasks){task.get();}
return 0;
}
Edit:
As rightly said by Miles Budnek, io_context::run has multiple overloads. You cannot take a pointer to it without forcing overload resolution with a cast.
If you really want to use std::bind, go for casting.
My opinion is same as that of others. GO FOR LAMBDA!!!

Why is my setter method producing a bad access error

Bad access means that i am trying to access memory that doesn't exists I have tried and tried to allocate memory for this class, but have failed everywhere. I do not know where the error is actual coming from. It only tells me that my setter method is when the program crashes. In the setFName() method is where the error occurs. But in the main method is where it actually occurrs.
nurse.hpp
#ifndef Nurse_hpp
#define Nurse_hpp
#include <stdio.h>
#include <string>
#include <stdlib.h>
using namespace std;
class nurse{
private:
string firstName;
public:
nurse() {
firstName = "jim";
}
string getFName() {return firstName;}
void setFName(string fName) {firstName = fName;} // Thread 1: bad access 0x0
};
#endif /* Nurse_hpp */
here is where the error is actually happening
main.cpp
#include <cstdint> // ::std::uint64_t type
#include <cstddef> // ::std::size_t type
#include <iostream>
#include <fstream>
#include <stdlib.h>
#include "nurseHolder.hpp"
using namespace std;
nurseHolder *l = new nurseHolder();
int main() {
return 0;
}
and finally here is the class that is causing the issue
nurseHolder.hpp
#ifndef Nurses_hpp
#define Nurses_hpp
#include <stdio.h>
#include <vector>
#include <stdlib.h>
#include "Nurse.cpp"
using namespace std;
class nurseHolder{
private:
int nurse_cnt;
int nurse_cap;
vector<nurse> nurse_list;
public:
nurseHolder() {
nurse_cnt = 0;
nurse_cap = 10;
for(int i= 0; i < 11; i++){
nurse_list[i].setFName("na");
}
}
vector<nurse> &getNurseList() { return nurse_list;}
};
#endif /* Nurses_hpp */
I tried to make this compact as possible sorry if its a lot of code.
here is what I changed to make the code work:
nurseHolder() {
nurse_cnt = 0;
nurse_cap = 10;
for(int i= 0; i < 11; i++){
nurse l;
nurse_list.pushback(l);
}
}
Is this a correct way to do this?
Your vector nurse_list has size 0. So you cannot use [] operator to set names.
There are two ways you can correct this:
Set an initial size to the vector and use [] to set names.
Use push_back to add elements to the vector.
First method.
nurse_list.resize(noOfTotalNurses).
nurse_list[i].setFName("name");
Second method.
nurse tNurse; //local nurse object
tNurse.setFName("name");
nurse_list.push_back(tNurse);

implementing map<mpz_t, double> in c++

For some reason, I need to have a map from arbitrary huge number to double and I tried to implement it with c++98 (and I have to) and Xcode but it doesn't work:
#include <iostream>
#include <string>
#include <map>
#include <vector>
#include <set>
#include "gurobi_c++.h"
#include <sstream>
#include "boost/tuple/tuple.hpp"
#include "boost/tuple/tuple_comparison.hpp"
#include "boost/tuple/tuple_io.hpp"
#include <cmath>
#include <gmp.h>
using namespace std;
using namespace ::boost::tuples;
using namespace ::boost;
int main()
{
map<mpz_t, double>J;
mpz_t a,b,c,n;
string tempstring;
int xrange=5,yrange=5,component=5;
mpz_set_str(n,"11", 10);
J[n]=-1;
return 0;
}
The error shown is: Array initializer must be an initializer list. Could someone help me with it? Thank you:)
Here's the detail error page:
I don't know the details of mpz_t. However, it appears to be an array.
You can get around the problem by defining a class to be used as the key in your map.
I am able to create an executable using the following code with g++ 4.8.2.
#include <map>
using namespace std;
typedef int (mpz_t)[2];
struct MyKey
{
// Add a proper implementation of a constructor
// with mpz_t.
MyKey(mpz_t in) {}
// Add a proper implementation of copy constructor.
MyKey(MyKey const& copy) {}
// Add a proper implementation of assignment operator.
MyKey& operator=(MyKey const& rhs)
{
return *this;
}
bool operator<(MyKey const& rhs) const
{
// Add a proper implementation.
return false;
}
mpz_t n;
};
int main()
{
map<MyKey, double> J;
mpz_t n;
J[n] = 1.0;
return 0;
}

How to pass pointer to a class instance's function in C++?

I'm trying to get a pointer to a function of an instance of my object. Here is my code:
#include <iostream>
#include <cstdlib>
#include <vector>
#include <algorithm>
#include <numeric>
using namespace std;
class Dice {
int face;
public:
Dice () {
face = rand() % 6 + 1;
}
int roll() {
face = rand() % 6 + 1;
return face;
}
};
int main()
{
Dice mydice;
vector<int> v(1000);
generate(v.begin(),v.end(),mydice.roll);
}
My compiler barks at me at the generate line with cryptic messages =) Please point out how to properly tell generate to call mydice.roll() to populate vector v.
Give it an object:
generate(..., std::bind(&Dice::roll, &mydice));
std::bind is in <functional> and binds arguments so that a function can be called without supplying them.
Another possible approach: make use of the () operator to define your dice class itself as a functional. Include this in your class: int operator()() { return roll(); } , then you can simply call your generator with generate(v.begin(),v.end(), mydice); .