I'm getting an compilation error, related to std::invoke, and also another that can not specialize the template for invoke.
This is the code:
#pragma once
#include <thread>
#include <iostream>
#include <vector>
#include <string>
#include <chrono>
class ThreadLoader {
private:
unsigned int id;
void _loadFile(const std::string& filepath) {
std::this_thread::sleep_for(std::chrono::seconds(1));
std::cout << "Loading " << filepath << "\n";
}
public:
static unsigned int counter;
ThreadLoader() {
id = counter;
counter++;
}
void loadFile(const std::string& filepath) {
std::thread t(&ThreadLoader::_loadFile, std::ref(filepath), this);
t.join();
}
friend std::ostream& operator<<(std::ostream& os, const ThreadLoader& t) {
return os << t.id << std::endl;
}
};
unsigned int ThreadLoader::counter = 0;
The error appears when I tried to call the loadFile function.
I already checked this. I think followed the accepted answer, however, the error persists. I think that I'm doing something wrong in std::thread t(&ThreadLoader::_loadFile, std::ref(filepath), this);, but I don't find what is it.
You have your parameters the wrong way round, it should be:
std::thread t(&ThreadLoader::_loadFile, this, std::ref(filepath));
Related
I am currently practicing the use of multiple threads in C++. The program is simplified as follow. In this case, I have a global variable Obj, and within each task, a get function is processed by thread and thread detach will be called after.
In practice, get may take a great amount of time to run. If there are many tasks, get will be called repetitively (since each task has its own get function). I wonder if I can design a program where when one task has already obtained the data using get function and the data has been wrote to obj.text, then the rest of tasks can directly access or wait for the data from obj.text.
Can I use std::shared_ptr, std::future, std::async in c++ to implement this? If so, how to design the program? Any advice is greatly appreciated.
#include <chrono>
#include <future>
#include <iostream>
#include <memory>
#include <thread>
#include <vector>
using namespace std;
class Info {
public:
Info() { Ids = 10; };
int Ids;
std::string text;
};
Info Objs;
class Module {
public:
Module() {}
virtual void check(int &id){};
virtual void get(){};
};
class task1 : public Module {
public:
task1() { std::cout << "task1" << std::endl; }
void check(int &id) override {
thread s(&task1::get, this);
s.detach();
};
// The function will first do some other work (here, I use sleep to represent
// that) then set the value of Objs.text
void get() override {
// The task may take 2 seconds , So use text instead
std::this_thread::sleep_for(std::chrono::seconds(5));
Objs.text = "AAAA";
std::cout << Objs.text << std::endl;
};
};
class task2 : public Module {
public:
task2() { std::cout << "task2" << std::endl; }
void check(int &id) override {
thread s(&task2::get, this);
s.detach();
};
// The function will first do some other work (here, I use sleep to represent
// that) then set the value of Objs.text
void get() {
std::this_thread::sleep_for(std::chrono::seconds(5));
Objs.text = "AAAA";
std::cout << Objs.text << std::endl;
};
};
int main() {
std::vector<std::unique_ptr<Module>> modules;
modules.push_back(std::make_unique<task1>());
modules.push_back(std::make_unique<task2>());
for (auto &m : modules) {
m->check(Objs.Ids);
}
std::this_thread::sleep_for(std::chrono::seconds(12));
return 0;
}
It is a plain producer-consumer problem.
You have multiple “get()” producers. And did not implemented consumers yet.
First, you should have multiple “Info” for multithread. If there is only one Info, multithread programming is useless. I recommend “concurrent_queue”.
Second, “detach()” is not a good idea. You can’t manage child threads. You’d better use “join()”
My code sample follows. I used Visual Studio 2022
#include <chrono>
#include <iostream>
#include <thread>
#include <vector>
#include <concurrent_queue.h>
using namespace std;
class Info {
public:
Info() { Ids = 10; };
int Ids;
std::string text;
};
concurrency::concurrent_queue<Info> Objs;
void producer()
{
while (true) {
Info obj;
std::this_thread::sleep_for(std::chrono::seconds(5));
obj.text = "AAAA\n";
Objs.push(obj);
}
}
void consumer()
{
while (true) {
std::this_thread::sleep_for(std::chrono::seconds(1));
Info obj;
bool got_it = Objs.try_pop(obj);
if (got_it) {
std::cout << obj.text;
}
}
}
int main() {
const int NUM_CORES = 6;
std::vector<std::thread> threads;
for (int i = 0; i < NUM_CORES / 2; ++i)
threads.emplace_back(producer);
for (int i = 0; i < NUM_CORES / 2; ++i)
threads.emplace_back(consumer);
for (auto& th : threads) th.join();
}
[It is not necessary to follow the links to understand the question].
I combined the implementation of the singleton pattern in this answer, together with the synchronized file writing of this other answer.
Then I wanted to see if the interface of SynchronizedFile could provide a variadic templated write method, but I couldn't figure out how to properly combine this with the std::lock_guard.
Below is a non-working example. In this case it doesn't work because (I think) the two threads manage to pump stuff into the buffer i_buf in a non-synchronized way, resulting in a garbled LOGFILE.txt.
If I put the std::lock_guard inside the general template of write then the program doesn't halt.
#include <iostream>
#include <mutex>
#include <sstream>
#include <fstream>
#include <string>
#include <memory>
#include <thread>
static const int N_LOOP_LENGTH{10};
// This class manages a log file and provides write method(s)
// that allow passing a variable number of parameters of different
// types to be written to the file in a line and separated by commas.
class SynchronizedFile {
public:
static SynchronizedFile& getInstance()
{
static SynchronizedFile instance;
return instance;
}
private:
std::ostringstream i_buf;
std::ofstream i_fout;
std::mutex _writerMutex;
SynchronizedFile () {
i_fout.open("LOGFILE.txt", std::ofstream::out);
}
public:
SynchronizedFile(SynchronizedFile const&) = delete;
void operator=(SynchronizedFile const&) = delete;
template<typename First, typename... Rest>
void write(First param1, Rest...param)
{
i_buf << param1 << ", ";
write(param...);
}
void write()
{
std::lock_guard<std::mutex> lock(_writerMutex);
i_fout << i_buf.str() << std::endl;
i_buf.str("");
i_buf.clear();
}
};
// This is just some class that is using the SynchronizedFile class
// to write stuff to the log file.
class Writer {
public:
Writer (SynchronizedFile& sf, const std::string& prefix)
: syncedFile(sf), prefix(prefix) {}
void someFunctionThatWritesToFile () {
syncedFile.write(prefix, "AAAAA", 4343, "BBBBB", 0.2345435, "GGGGGG");
}
private:
SynchronizedFile& syncedFile;
std::string prefix;
};
void thread_method()
{
SynchronizedFile &my_file1 = SynchronizedFile::getInstance();
Writer writer1(my_file1, "Writer 1:");
for (int i = 0; i < N_LOOP_LENGTH; ++ i)
writer1.someFunctionThatWritesToFile();
}
int main()
{
std::thread t(thread_method);
SynchronizedFile &my_file2 = SynchronizedFile::getInstance();
Writer writer2(my_file2, "Writer 2:");
for (int i = 0; i < N_LOOP_LENGTH; ++i)
writer2.someFunctionThatWritesToFile();
t.join();
std::cout << "Done" << std::endl;
return 0;
}
How could I successfully combine these three ideas?
The program deadlocks because write calls itself recursively while still holding the lock.
Either use a std::recursive_mutex or release the lock after writing your data out but before calling write.
E: Unlocking doesn't do the job, I didn't think this through...
E: Or lock once and defer to another private method to do the write.
template<typename... Args>
void write(Args&&... args)
{
std::unique_lock<std::mutex> lock(_writerMutex);
_write(std::forward<Args>(args)...);
}
template<typename First, typename... Rest>
void _write(First&& param1, Rest&&... param) // private method
{
i_buf << std::forward<First>(param1) << ", ";
_write(std::forward<Rest>(param)...);
}
void _write()
{
i_fout << i_buf.str() << std::endl;
i_buf.clear();
}
class Function
{
public:
std::string Name;
void call(std::string x);
Function(std::string Nam)
{
Name = Nam;
}
};
std::vector<Function> funcs;
void Load_FuncLib()
{
Function print("print");
Function add("add");
print.call(std::string x)
{
std::cout<< x <<"\n";
}
add.call(std::string x)
{
std::cout<< std::stoi(x) + std::stoi(x) << "\n";
}
funcs.push_back(print);
funcs.push_back(add);
funcs.at(0).call("Hello world");
}
I want it to run the function print.call("Hello world"); but it will not work as I don't know how to set a function, which is already declared, nor do I know how to call it using a vector.
You most likely want to achieve something like this?
#include <unordered_map>
#include <iostream>
#include <string>
#include <functional>
int main() {
std::unordered_map<std::string, std::function<void (const std::string&)>> funcs;
funcs["print"] = [](const std::string& str) {
std::cout << str << '\n';
};
funcs["add"] = [](const std::string& str) {
int i = std::stoi(str);
std::cout << i + i << '\n';
};
funcs["print"]("Hello, World!");
funcs["add"]("12");
}
https://ideone.com/Ke4aEK
At any time you can reset a certain value of the hash map with another function.
Also, depending on your needs, you may use std::function or just plain function pointers.
#include <boost/ref.hpp>
//#include <boost/bind.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/lambda/lambda.hpp>
#include <boost/lambda/bind.hpp>
#include <boost/mem_fn.hpp>
using namespace std;
using namespace boost::lambda;
class Base {
public:
Base () {}
bool toBeRemoved() const {
return true;
}
};
class status : public Base {
std::string name_;
bool ok_;
public:
status(const std::string& name):name_(name),ok_(true) {}
void break_it() {
ok_=false;
}
bool is_broken() const {
return ok_;
}
void report() const {
std::cout << name_ << " is " <<
(ok_ ? "working nominally":"terribly broken") << '\n';
}
std::string getStatus() const {
return ok_ ? "1" : "0";
}
};
class some_class {
public:
int test() {
std::vector<boost::shared_ptr<status> > s_statuses = getStatus(); //some func
std::set<string> s;
std::transform(s_statuses.begin(), s_statuses.end(), std::inserter(s, s.begin()), boost::lambda::bind(boost::mem_fn(&status::getStatus), boost::ref(*_1)));
// approach #2
// std::transform(s_statuses.begin(), s_statuses.end(), std::inserter(s, s.begin()), boost::lambda::bind(boost::mem_fn(&status::getStatus), boost::ref(*_1), _1));
// approach #3
// std::transform(s_statuses.begin(), s_statuses.end(), std::inserter(s, s.begin()), boost::bind(&status::getStatus), _1));
std::copy(s.begin(), s.end(), ostream_iterator<string>(std::cout, "-"));
std::cout << endl;
return 0;
}
}
For all the approaches above, I am getting the error "can call member function without object" on the line containing the bind call. I have tried using boost::lambda::bind and boost::bind as well. Though this way of using bind works if objects are defined, for example in main function. I assume I am making some silly mistake here, but I am not able to figure out why these all approaches working, or it could be the case that this is not the right way of doing at all.
Could someone please help me resolve this on how to properly use boost bind for non-static member of class which are stored in stl containers ?
Thanks,
You should just need to use boost::mem_fn. (Note, you could also use std::mem_fn if available.)
std::transform(s_statuses.begin(), s_statuses.end(), std::inserter(s, s.begin()), std::mem_fn(&status::getStatus));
Firstly,I want to inform you that my overall/main target is to execute certain functions using their function name(string) as an argument,I defined a function as below:
(I want to generate a unique number for each string data that I inserted as argument to a function)
#include <iostream>
#include <string>
#include <hash_set>
using namespace std;
void Func_Execution(string &s){
int k=stdext::hash_value(s);
#if(_MSC_VER ==1500)
switch (k)
{
case -336300864: GETBATTERYCALLSIGNS();
break;
case -1859542241:GETGUNIDS();
break;
case 323320073:Foo(); // here int k=323320073 for string s="Foo"
break;
case 478877555:Bar();
break;
defalut :Exit();
break;
}
#endif
}
Here I call Func_Execution function as below:
void main(){
string s="Foo";
Func_Execution(s);
}
I want to know that is there any efficient(considering perfomance/time consuming) and effective mechanism to generate a unique numerical value for certain string(character pattern) rather than using stdext::hash_value() function?(Also notice I want to implement switch-case too)
Have you considered something like
#include <functional>
#include <iostream>
#include <unordered_map>
#include <string>
using std::cout;
using std::endl;
using std::function;
using std::string;
using std::unordered_map;
class Registry {
public:
static void Execute(const string& function) {
if (functions_.find(function) != functions_.end()) {
functions_[function]();
}
}
static int Register(const string& function_name, function<void()> f) {
functions_.emplace(function_name, f);
return functions_.size();
}
static void Dump() {
for (auto& i : functions_) {
cout << i.first << endl;
}
}
private:
Registry() {};
static unordered_map<string, function<void()>> functions_;
};
unordered_map<string, function<void()>> Registry::functions_;
#define REGISTER_FUNCTION(F) \
namespace { \
const int REGISTERED__##F = Registry::Register(#F, &F); \
}
void foo() {
cout << "foo" << endl;
}
REGISTER_FUNCTION(foo);
void bar() {
cout << "bar" << endl;
}
REGISTER_FUNCTION(bar);
int main() {
Registry::Execute("foo");
Registry::Execute("foo");
Registry::Execute("unknown");
Registry::Dump();
return 0;
}
It should serve well for your use case. I just hacked it together, there's probably a bug somewhere, but it compiles and runs (c++11).
Don't use hash_value() for fingerprinting (which is what you are describing). If you really know all your possible strings ahead of time, use your own perfect hash function and then measure the results to see if it is worth it.