I'm trying to create a deadline class which starts a thread in its constructor. Once the deadline (a time priod) occur within a thread, a function provided as argument should be executed.
The class'es contructor takes that function as a parameter, as well as arguments of that function.
I can provide parameter by value and by reference, but when providing rvalue as parameter, I get compile error, which I don't know how to solve.
#include <thread>
#include <atomic>
#include <future>
#include <iostream>
#include <iomanip>
namespace {
std::atomic<bool> running{true};
template <typename Period>
using duration = std::chrono::duration<int64_t, Period>;
template <typename PromiseType = void>
class deadline {
std::promise<PromiseType> stopper_{};
std::thread thread_{};
public:
deadline() = delete;
template <typename Period, typename Function, typename... Args>
explicit deadline(const duration<Period> &interval, Function&& func, Args&&... args) noexcept {
if (interval.count() > 0) {
std::future<PromiseType> future{ stopper_.get_future() };
using tuple = std::tuple<std::decay_t<Args>...>;
auto decay_copied = std::make_unique<tuple>(std::forward<Args>(args)...);
thread_ = std::thread(
[](std::future<PromiseType>&& future,
const duration<Period> &interval,
Function&& func, decltype(decay_copied)&& params) {
if (future.wait_for(interval) == std::future_status::timeout) {
std::apply(func, *params);
}
}, std::move(future), std::cref(interval), std::forward<Function>(func), std::move(decay_copied));
}
}
deadline(const deadline&) = delete;
deadline(deadline&&) = delete;
deadline& operator=(const deadline&) = delete;
deadline& operator=(deadline&&) = delete;
~deadline() {
stopper_.set_value();
if (thread_.joinable()) {
thread_.join();
}
}
};
}
auto main() -> int {
std::string test1{"test 1"};
std::string test2{"test 2"};
std::string test3{"test 3"};
std::string test4{"test 4"};
using namespace std::chrono_literals;
deadline dl(5s,
[](
std::string test_1
, const std::string& test_2
, std::string& test_3
, std::string&& test_4
) {
std::cout << test_1 << '\n';
std::cout << test_2 << '\n';
std::cout << test_3 << '\n';
test_3 += " modified";
std::cout << test_4 << '\n';
running = false;
}
, test1
, std::cref(test2)
, std::ref(test3)
, std::move(test4)
//, "test 4"
);
while (running.load()) {
std::this_thread::sleep_for(std::chrono::milliseconds(500));
}
std::cout << test1 << '\n';
std::cout << test2 << '\n';
std::cout << test3 << '\n';
std::cout << test4 << '\n';
return 0;
}
The code could be checked here also:
https://godbolt.org/z/fx3a4szoY
Any help is appreciated.
Thanks!
When providing a const value (also a rvalue), it works, it doesn't work if I use std::move.
I am trying to construct a std::thread with a member function that takes no arguments and returns void. I can't figure out any syntax that works - the compiler complains no matter what. What is the correct way to implement spawn() so that it returns a std::thread that executes test()?
#include <thread>
class blub {
void test() {
}
public:
std::thread spawn() {
return { test };
}
};
#include <thread>
#include <iostream>
class bar {
public:
void foo() {
std::cout << "hello from member function" << std::endl;
}
};
int main()
{
std::thread t(&bar::foo, bar());
t.join();
}
EDIT:
Accounting your edit, you have to do it like this:
std::thread spawn() {
return std::thread(&blub::test, this);
}
UPDATE: I want to explain some more points, some of them have also been discussed in the comments.
The syntax described above is defined in terms of the INVOKE definition (§20.8.2.1):
Define INVOKE (f, t1, t2, ..., tN) as follows:
(t1.*f)(t2, ..., tN) when f is a pointer to a member function of a class T and t1 is an object of type T or a reference to an object of
type T or a reference to an object of a type derived from T;
((*t1).*f)(t2, ..., tN) when f is a pointer to a member function of a class T and t1 is not one of the types described in the previous
item;
t1.*f when N == 1 and f is a pointer to member data of a class T and t 1 is an object of type T or a
reference to an object of type T or a reference to an object of a
type derived from T;
(*t1).*f when N == 1 and f is a pointer to member data of a class T and t 1 is not one of the types described in the previous item;
f(t1, t2, ..., tN) in all other cases.
Another general fact which I want to point out is that by default the thread constructor will copy all arguments passed to it. The reason for this is that the arguments may need to outlive the calling thread, copying the arguments guarantees that. Instead, if you want to really pass a reference, you can use a std::reference_wrapper created by std::ref.
std::thread (foo, std::ref(arg1));
By doing this, you are promising that you will take care of guaranteeing that the arguments will still exist when the thread operates on them.
Note that all the things mentioned above can also be applied to std::async and std::bind.
Since you are using C++11, lambda-expression is a nice&clean solution.
class blub {
void test() {}
public:
std::thread spawn() {
return std::thread( [this] { this->test(); } );
}
};
since this-> can be omitted, it could be shorten to:
std::thread( [this] { test(); } )
or just (deprecated)
std::thread( [=] { test(); } )
Here is a complete example
#include <thread>
#include <iostream>
class Wrapper {
public:
void member1() {
std::cout << "i am member1" << std::endl;
}
void member2(const char *arg1, unsigned arg2) {
std::cout << "i am member2 and my first arg is (" << arg1 << ") and second arg is (" << arg2 << ")" << std::endl;
}
std::thread member1Thread() {
return std::thread([=] { member1(); });
}
std::thread member2Thread(const char *arg1, unsigned arg2) {
return std::thread([=] { member2(arg1, arg2); });
}
};
int main(int argc, char **argv) {
Wrapper *w = new Wrapper();
std::thread tw1 = w->member1Thread();
std::thread tw2 = w->member2Thread("hello", 100);
tw1.join();
tw2.join();
return 0;
}
Compiling with g++ produces the following result
g++ -Wall -std=c++11 hello.cc -o hello -pthread
i am member1
i am member2 and my first arg is (hello) and second arg is (100)
#hop5 and #RnMss suggested to use C++11 lambdas, but if you deal with pointers, you can use them directly:
#include <thread>
#include <iostream>
class CFoo {
public:
int m_i = 0;
void bar() {
++m_i;
}
};
int main() {
CFoo foo;
std::thread t1(&CFoo::bar, &foo);
t1.join();
std::thread t2(&CFoo::bar, &foo);
t2.join();
std::cout << foo.m_i << std::endl;
return 0;
}
outputs
2
Rewritten sample from this answer would be then:
#include <thread>
#include <iostream>
class Wrapper {
public:
void member1() {
std::cout << "i am member1" << std::endl;
}
void member2(const char *arg1, unsigned arg2) {
std::cout << "i am member2 and my first arg is (" << arg1 << ") and second arg is (" << arg2 << ")" << std::endl;
}
std::thread member1Thread() {
return std::thread(&Wrapper::member1, this);
}
std::thread member2Thread(const char *arg1, unsigned arg2) {
return std::thread(&Wrapper::member2, this, arg1, arg2);
}
};
int main() {
Wrapper *w = new Wrapper();
std::thread tw1 = w->member1Thread();
tw1.join();
std::thread tw2 = w->member2Thread("hello", 100);
tw2.join();
return 0;
}
Some users have already given their answer and explained it very well.
I would like to add few more things related to thread.
How to work with functor and thread.
Please refer to below example.
The thread will make its own copy of the object while passing the object.
#include<thread>
#include<Windows.h>
#include<iostream>
using namespace std;
class CB
{
public:
CB()
{
cout << "this=" << this << endl;
}
void operator()();
};
void CB::operator()()
{
cout << "this=" << this << endl;
for (int i = 0; i < 5; i++)
{
cout << "CB()=" << i << endl;
Sleep(1000);
}
}
void main()
{
CB obj; // please note the address of obj.
thread t(obj); // here obj will be passed by value
//i.e. thread will make it own local copy of it.
// we can confirm it by matching the address of
//object printed in the constructor
// and address of the obj printed in the function
t.join();
}
Another way of achieving the same thing is like:
void main()
{
thread t((CB()));
t.join();
}
But if you want to pass the object by reference then use the below syntax:
void main()
{
CB obj;
//thread t(obj);
thread t(std::ref(obj));
t.join();
}
now I'm Having problem in repeating the loop after it finished doing the first and i want to try it again without exiting the program? I've been using while loop to do it but still no joy. so i decided to do the if statement. But the Array only accept 4 strings then it exit. Any one who can help? TIA.
#include "stdafx.h"
#include <iostream>
#include <string>
#include <algorithm>
#include <vector>
using namespace std;
template <typename T>
void GetContents(T& Input);
template <typename T>
void DisplayContents(const T& Input);
int main()
{
int PASS = 0;
// To Display the unsorted and sorted Book Titles
std::vector<std::string> books;
GetContents(books);
std::cout << "\nMy original library (number of books: " << books.size() << "):\n\n";
DisplayContents(books);
std::sort(books.begin(), books.end());
std::cout << "\nMy sorted library (number of books: " << books.size() << "):\n\n";
DisplayContents(books);
std::cout << "Press 1 to try again, else to quit: ";
std::cin >> PASS;
std::cout << "\n";
if (PASS == 1)
{
GetContents(books);
}
else
{
return 0;
}
// to input All book titles
template <typename T>
void GetContents(T& Input)
{
const int MAX = 5;
string bookName;
std::cout << "Enter a Book Titles:\n> ";
for (int i = 0; i < MAX; i++)
{
std::getline(std::cin, bookName);
Input.push_back(bookName);
std::cout <<">";
}
}
//Display All input book titles
template <typename T>
void DisplayContents(const T& Input)
{
for (auto iElement : Input)
{
std::cout << iElement << '\n';
}
std::cout << '\n';
system("pause");
}
I'm trying to use the new C++11 move semantics, but the copy constructor gets called every time... Does anyone know what am I doing wrong? I'm using VS2012. Thanks in advance!
MemoryBlock::MemoryBlock(MemoryBlock& other)
: m_capacity(other.m_used), m_used(other.m_used), m_pointer(nullptr) {
std::wcout << L"Copy constructor called" << std::endl;
// ...
}
MemoryBlock& MemoryBlock::operator=(MemoryBlock& other) {
std::wcout << L"Copy assignment called" << std::endl;
if (this != &other) {
// ...
}
return *this;
}
MemoryBlock::MemoryBlock(MemoryBlock&& other)
: m_capacity(other.m_capacity), m_used(other.m_used), m_pointer(other.m_pointer) {
std::wcout << L"Move constructor called" << std::endl;
// ...
}
MemoryBlock& MemoryBlock::operator=(MemoryBlock&& other) {
std::wcout << L"Move assignment called" << std::endl;
if (this != &other) {
// ...
}
return *this;
}
MemoryBlock CreateRequest(const wchar_t *action) {
MemoryBlock request;
// ...
return request;
}
int __cdecl wmain(int argc, wchar_t *argv[]) {
// ...
MemoryBlock request = CreateRequest(argv[1]);
// ...
}
I am trying to create a Runnable interface in c++11 using packaged_task, with child class overriding run() function. I don't know why this code is not compiling. Its giving error related to type argument.
/usr/include/c++/4.8.1/functional:1697:61: error: no type named ‘type’ in ‘class std::result_of()>’
typedef typename result_of<_Callable(_Args...)>::type result_type;
Below is my code snippet. Could someone plz give me some information on this error and whether implementing Runnable this way is a right way to proceed ?
class Runnable {
public:
explicit Runnable() {
task_ = std::packaged_task<int()>(&Runnable::run);
result_ = task_.get_future();
std::cout << "starting task" << std::endl;
}
virtual int run() = 0;
int getResult() {
task_();
return result_.get();
}
virtual ~Runnable() {
std::cout << "~Runnable()" << std::endl;
}
private:
std::future<int> result_;
std::packaged_task<int()> task_;
};
class foo : public Runnable {
int fib(int n) {
if (n < 3) return 1;
else return fib(n-1) + fib(n-2);
}
public:
explicit foo(int n) : n_(n) {}
int run() {
cout << "in foo run() " << endl;
int res = fib(n_);
cout << "done foo run(), res = " << res << endl;
return res;
}
~foo() {}
private:
int n_;
};
int main(int argc, char*argv[]) {
stringstream oss;
oss << argv[1];
int n;
oss >> n;
shared_ptr<foo> obj(new foo(n));
obj->run();
cout << "done main" << endl;
return 0;
}