I am trying to build a very simple scheduler. It allows tasks (functions) to be added to a list and run on set intervals. The 'Scheduler' class works fine if I provide a static function as an argument to its 'ScheduleTask' member.
class TestController
{
private:
Scheduler _scheduler;
public:
TestController(void)
{
_scheduler.ScheduleTask(Task1, 3000);
_scheduler.ScheduleTask(Task2, 5000);
}
~TestController(void);
void Task1(void) { }
void Task2(void) { }
};
struct Task
{
long interval;
long last_run;
void (*TaskCallback) (void);
Task()
{
last_run = 0;
}
};
class Scheduler
{
private:
std::vector<Task> _tasks;
public:
Scheduler(void) { }
~Scheduler(void) { }
void ScheduleTask(void (*TaskCallback) (void), long interval)
{
Task t;
t.TaskCallback = TaskCallback;
t.interval = interval;
_tasks.push_back(t);
}
void loop()
{
for(unsigned int i = 0; i < _tasks.size(); i++)
{
long elapsed = clock();
if(elapsed - _tasks[i].last_run >= _tasks[i].interval)
{
_tasks[i].last_run = elapsed;
_tasks[i].TaskCallback();
}
}
}
};
How can I modify the callback to accept the member on the already instantiated 'TestController' object?
Use a combination of boost::function and boost::bind. Alternatively, use std::function and std::bind if your compiler supports them.
#include <boost/bind.hpp>
#include <boost/function.hpp>
#include <vector>
typedef boost::function<void()> Callback;
struct Task
{
long interval;
long last_run;
Callback TaskCallback;
Task()
{
last_run = 0;
}
};
class Scheduler
{
private:
std::vector<Task> _tasks;
public:
Scheduler(void) { }
~Scheduler(void) { }
void ScheduleTask(const Callback& TaskCallback, long interval)
{
Task t;
t.TaskCallback = TaskCallback;
t.interval = interval;
_tasks.push_back(t);
}
void loop()
{
for(unsigned int i = 0; i < _tasks.size(); i++)
{
long elapsed = clock();
if(elapsed - _tasks[i].last_run >= _tasks[i].interval)
{
_tasks[i].last_run = elapsed;
_tasks[i].TaskCallback();
}
}
}
};
class TestController
{
private:
Scheduler _scheduler;
public:
TestController(void)
{
_scheduler.ScheduleTask(boost::bind(&TestController::Task1,this), 3000);
_scheduler.ScheduleTask(boost::bind(&TestController::Task2,this), 5000);
}
~TestController(void);
void Task1(void) { }
void Task2(void) { }
};
Related
I want to calculate number of even numbers among all pairwise sums till 100000. And I want to do it using threadpools. Previously I did it in a static way, i.e., I allocated work to all the threads in the beginning itself. I was able to achieve linear speedup in that case. But the bottleneck is that the threads which started early, finished early (because there were less pairs to compute). So instead of that I want to allocate work to the threads dynamically, i.e., I will initially assign some work to the threads and as soon as they complete the work, they come back to take more work from the queue. Below is my threadpool code,
main.cpp :
#include <iostream>
#include <random>
#include<chrono>
#include<iomanip>
#include<future>
#include<vector>
#include "../include/ThreadPool.h"
std::random_device rd;
std::mt19937 mt(rd());
std::uniform_int_distribution<int> dist(-10, 10);
auto rnd = std::bind(dist, mt);
int thread_work;
long long pairwise(const int start) {
long long sum = 0;
long long counter = 0;
for(int i = start+1; i <= start+thread_work; i++)
{
for(int j = i-1; j >= 0; j--)
{
sum = i + j;
if(sum%2 == 0)
counter++;
}
}
//std::cout<<counter<<std::endl;
return counter;
}
int main(int argc, char *argv[])
{
// Create pool with x threads
int x;
std::cout<<"Enter num of threads : ";
std::cin>>x;
std::cout<<"Enter thread_work : ";
std::cin>>thread_work;
ThreadPool pool(x);
// Initialize pool
pool.init();
int N = 100000;
long long res = 0;
auto start = std::chrono::high_resolution_clock::now();
for(int i = 0; i < N; i = i + thread_work)
{
std::future<long long int> fut = pool.submit(pairwise,i);
res += fut.get();
}
std::cout<<"total is "<<res<<std::endl;
pool.shutdown();
auto end = std::chrono::high_resolution_clock::now();
double time_taken = std::chrono::duration_cast<std::chrono::nanoseconds>(end - start).count();
time_taken *= 1e-9;
std::cout << "Time taken by program is : " << std::fixed << time_taken << std::setprecision(9)<<" secs"<<std::endl;
return 0;
}
my SafeQueue.h :
#pragma once
#include <mutex>
#include <queue>
// Thread safe implementation of a Queue using an std::queue
template <typename T>
class SafeQueue {
private:
std::queue<T> m_queue;
std::mutex m_mutex;
public:
SafeQueue() {
}
SafeQueue(SafeQueue& other) {
//TODO:
}
~SafeQueue() {
}
bool empty() {
std::unique_lock<std::mutex> lock(m_mutex);
return m_queue.empty();
}
int size() {
std::unique_lock<std::mutex> lock(m_mutex);
return m_queue.size();
}
void enqueue(T& t) {
std::unique_lock<std::mutex> lock(m_mutex);
m_queue.push(t);
}
bool dequeue(T& t) {
std::unique_lock<std::mutex> lock(m_mutex);
if (m_queue.empty()) {
return false;
}
t = std::move(m_queue.front());
m_queue.pop();
return true;
}
};
and my ThreadPool.h :
#pragma once
#include <functional>
#include <future>
#include <mutex>
#include <queue>
#include <thread>
#include <utility>
#include <vector>
#include "SafeQueue.h"
class ThreadPool {
private:
class ThreadWorker {
private:
int m_id;
ThreadPool * m_pool;
public:
ThreadWorker(ThreadPool * pool, const int id)
: m_pool(pool), m_id(id) {
}
void operator()() {
std::function<void()> func;
bool dequeued;
while (!m_pool->m_shutdown) {
{
std::unique_lock<std::mutex> lock(m_pool->m_conditional_mutex);
if (m_pool->m_queue.empty()) {
m_pool->m_conditional_lock.wait(lock);
}
dequeued = m_pool->m_queue.dequeue(func);
}
if (dequeued) {
func();
}
}
}
};
bool m_shutdown;
SafeQueue<std::function<void()>> m_queue;
std::vector<std::thread> m_threads;
std::mutex m_conditional_mutex;
std::condition_variable m_conditional_lock;
public:
ThreadPool(const int n_threads)
: m_threads(std::vector<std::thread>(n_threads)), m_shutdown(false) {
}
ThreadPool(const ThreadPool &) = delete;
ThreadPool(ThreadPool &&) = delete;
ThreadPool & operator=(const ThreadPool &) = delete;
ThreadPool & operator=(ThreadPool &&) = delete;
// Inits thread pool
void init() {
for (int i = 0; i < m_threads.size(); ++i) {
m_threads[i] = std::thread(ThreadWorker(this, i));
}
}
// Waits until threads finish their current task and shutdowns the pool
void shutdown() {
m_shutdown = true;
m_conditional_lock.notify_all();
for (int i = 0; i < m_threads.size(); ++i) {
if(m_threads[i].joinable()) {
m_threads[i].join();
}
}
}
// Submit a function to be executed asynchronously by the pool
template<typename F, typename...Args>
auto submit(F&& f, Args&&... args) -> std::future<decltype(f(args...))> {
// Create a function with bounded parameters ready to execute
std::function<decltype(f(args...))()> func = std::bind(std::forward<F>(f), std::forward<Args>(args)...);
// Encapsulate it into a shared ptr in order to be able to copy construct / assign
auto task_ptr = std::make_shared<std::packaged_task<decltype(f(args...))()>>(func);
// Wrap packaged task into void function
std::function<void()> wrapper_func = [task_ptr]() {
(*task_ptr)();
};
// Enqueue generic wrapper function
m_queue.enqueue(wrapper_func);
// Wake up one thread if its waiting
m_conditional_lock.notify_one();
// Return future from promise
return task_ptr->get_future();
}
};
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.
I have a Timer class that calls function pointer on timeout. The problem that this Times should be able to be copied (instances of it can be swapped in array). After copying the m_callbackOwner became invalid.
So, how to deal with this problem? How to implement callbacks to allow copying?
#pragma once
#include "common/Function.h"
#include "helpers/Utils.h"
template<typename TimeoutCallbackOwner, typename TimeoutCallback>
class Timer
{
public:
Timer() : m_interval(0), m_value(0), m_callbackFunction(nullptr) {}
void setCallback(TimeoutCallbackOwner *cbOwner, TimeoutCallback cb)
{
assert(cbOwner && cb);
m_callbackOwner = cbOwner;
m_callbackFunction = cb;
}
void update(double dt)
{
if (m_interval < 0 || isEqual(m_interval, 0))
{
return;
}
m_value += dt;
if (m_value >= m_interval)
{
m_value = 0;
if (m_callbackOwner, m_callbackFunction)
CALL_MEMBER_FN(m_callbackOwner, m_callbackFunction);
}
}
void setInterval(double interval)
{
m_interval = interval;
m_value = 0;
}
double interval() const
{
return m_interval;
}
double value() const
{
return m_value;
}
bool isRunning() const
{
return m_value != 0;
}
private:
double m_interval;
double m_value;
TimeoutCallbackOwner * m_callbackOwner;
TimeoutCallback m_callbackFunction;
};
Let's say I have this function:
void changeMap(Player* player, int map) {
player->setMap(map);
}
And I want a timer class that enables me to run that function after a certain amount of time, Something like this.
Player* chr;
int mapid = 300;
int milliseconds = 6000;
Timer.Schedule(changeMap(chr, 300), milliseconds);
Thanks in advance.
If this is a game loop then one way is to keep of list of events that you want to happen some time in the future where you store a time and a pointer to the function you want to call. (Or a std::function, or whatever). Keep the list sorted by time so the soonest event is a the top of the list.
Then in your main game loop, every loop, check the top of the list to see if the time of that event has been reached yet and if it has pop the event and call the function.
You can achieve the desired effect by the liberal use of Functor delegate objects and templates:
CAlarm.h
#ifndef CALARM_H
#define CALARM_H
#include "ADTtime.h"
#include "CStopwatch.h"
template<class FunctionObject>
class Alarm : public StopWatch {
public:
Alarm(const FunctionObject& fn);
Alarm(double tickTime, const FunctionObject& fn);
virtual ~Alarm();
FunctionObject Tick();
protected:
FunctionObject _delegate;
double _tickTime;
private:
};
template<class FunctionObject>
Alarm<FunctionObject>::Alarm(const FunctionObject& fn)
: StopWatch(), _delegate(fn), _tickTime(1.0) { }
template<class FunctionObject>
Alarm<FunctionObject>::Alarm(double tickTime, const FunctionObject& fn)
: StopWatch(), _delegate(fn), _tickTime(tickTime) { }
template<class FunctionObject>
Alarm<FunctionObject>::~Alarm() {
if(_isRunning) Stop();
}
template<class FunctionObject>
FunctionObject Alarm<FunctionObject>::Tick() {
if(IsRunning() == false) return _delegate;
if(GetElapsedTimeInSeconds() >= _tickTime) {
Reset();
_delegate();
}
return _delegate;
}
#endif
CStopwatch.h
#ifndef CSTOPWATCH_H
#define CSTOPWATCH_H
#include "ADTtime.h"
class StopWatch : public ADTTime {
public:
StopWatch();
virtual ~StopWatch();
void Start();
void Restart();
void Stop();
void Reset();
virtual void CalculateElapsedTime();
virtual double GetElapsedTimeInSeconds();
virtual double GetElapsedTimeInMilliseconds();
protected:
private:
};
#endif
CStopwatch.cpp
#include "CStopwatch.h"
StopWatch::StopWatch() : ADTTime() {
/* DO NOTHING. ALL INITIALIZATION HAPPENS IN BASE CLASS */
}
StopWatch::~StopWatch() {
_startTime = -1;
_endTime = -1;
_deltaTime = -1.0;
_isRunning = false;
}
void StopWatch::Start() {
if(_isRunning == true) return;
_startTime = clock();
_isRunning = true;
}
void StopWatch::Stop() {
if(_isRunning == false) return;
_isRunning = false;
CalculateElapsedTime();
}
void StopWatch::Restart() {
Reset();
Start();
}
void StopWatch::Reset() {
Stop();
_startTime = 0;
_endTime = 0;
_deltaTime = 0.0;
}
void StopWatch::CalculateElapsedTime() {
_endTime = clock();
_deltaTime = difftime(_startTime, _endTime);
}
double StopWatch::GetElapsedTimeInSeconds() {
CalculateElapsedTime();
return -ADTTime::GetElapsedTimeInSeconds();
}
double StopWatch::GetElapsedTimeInMilliseconds() {
CalculateElapsedTime();
return -ADTTime::GetElapsedTimeInMilliseconds();
}
ADTTime.h
#ifndef ADTTIME_H
#define ADTTIME_H
#include <ctime>
class ADTTime {
public:
clock_t GetStartTime() const;
clock_t GetStartTime();
double GetStartTimeInSeconds() const;
double GetStartTimeInSeconds();
clock_t GetEndTime() const;
clock_t GetEndTime();
double GetEndTimeInSeconds() const;
double GetEndTimeInSeconds();
virtual double GetElapsedTimeInSeconds();
virtual double GetElapsedTimeInMilliseconds();
virtual void CalculateElapsedTime()=0;
bool IsRunning() const;
bool IsRunning();
virtual void Start()=0;
virtual void Restart()=0;
virtual void Stop()=0;
virtual void Reset()=0;
ADTTime();
virtual ~ADTTime();
protected:
bool _isRunning;
clock_t _startTime;
clock_t _endTime;
double _deltaTime;
private:
};
#endif
CADTTime.cpp
#include "ADTtime.h"
clock_t ADTTime::GetStartTime() const {
return _startTime;
}
clock_t ADTTime::GetStartTime() {
return static_cast<const ADTTime&>(*this).GetStartTime();
}
double ADTTime::GetStartTimeInSeconds() const {
return static_cast<double>((_startTime / CLOCKS_PER_SEC));
}
double ADTTime::GetStartTimeInSeconds() {
return static_cast<const ADTTime&>(*this).GetStartTimeInSeconds();
}
clock_t ADTTime::GetEndTime() const {
return _endTime;
}
clock_t ADTTime::GetEndTime() {
return static_cast<const ADTTime&>(*this).GetEndTime();
}
double ADTTime::GetEndTimeInSeconds() const {
return static_cast<double>((_endTime / CLOCKS_PER_SEC));
}
double ADTTime::GetEndTimeInSeconds() {
return static_cast<const ADTTime&>(*this).GetEndTimeInSeconds();
}
double ADTTime::GetElapsedTimeInSeconds() {
return _deltaTime / CLOCKS_PER_SEC;
}
double ADTTime::GetElapsedTimeInMilliseconds() {
return _deltaTime;
}
bool ADTTime::IsRunning() const {
return _isRunning;
}
bool ADTTime::IsRunning() {
return static_cast<const ADTTime&>(*this).IsRunning();
}
ADTTime::ADTTime() : _isRunning(false), _startTime(-1), _endTime(-1), _deltaTime(-1.0) { }
ADTTime::~ADTTime() {
_isRunning = false;
_startTime = -1;
_endTime = -1;
_deltaTime = -1.0;
}
Since you are running on Windows OS, I don't understand why are you reinventing the wheel?
CComPtr<IReferenceClock> pReferenceClock;
HRESULT hr = CoCreateInstance( CLSID_SystemClock, NULL, CLSCTX_INPROC_SERVER, IID_IReferenceClock, (void**)&pReferenceClock );
hr = pReferenceClock->AdviseTime( ... );
// or, hr = pReferenceClock->AdvisePeriodic( ... );
and once you are done,
hr = pReferenceClock->Unadvise( adviseCookie );
You can implement a simple (perhaps a bit rough around the edges) function that fire off a one-off event, like a timer, after a specified amount of milliseconds, using std::thread and std::chrono facilities
Something like that:
void doAfter( const std::function<void(void)>& f,
size_t intervalMs )
{
std::thread t{[f, intervalMs] () -> void
{
auto chronoInterval = std::chrono::milliseconds( intervalMs );
std::this_thread::sleep_for( chronoInterval );
f();
}
};
// You can either `t.detach()` the thread, or wait to `join` it in main
}
I have a big project where I faced a problem, which can be shortly formulated as following:
I had a class which is created temporally and used to process and modify some data (let's call it "worker"). Now I have two workers and two corresponding data formats. The data array can contain mixed data, how to make my programm automatically decide which worker class it should create and use for data processing? How to make this in the best way?
To illustrate this problem I wrote small example programm, which is analogical to my project.
#include <iostream>
#include <vector>
using namespace std;
const int NInputs = 10;
struct TOutput {
int i;
};
class TProcess {
public:
TProcess( const vector<TInput>& i ){ fInput = i; }
void Run();
void GetOutput( TOutput& o ) { o = fOutput; }
private:
vector<TInput> fInput;
TOutput fOutput;
};
#if 0
struct TInput {
int i;
};
class TWorker{
public:
void Init( int i ) { fResult = i; }
void Add( int i ) { fResult += i; }
int Result() { return fResult; }
private:
int fResult;
};
#else
struct TInput {
int i;
};
class TWorker {
public:
void Init( int i ) { fResult = i; }
void Add( int i ) { fResult ^= i; }
int Result() { return fResult; }
private:
int fResult;
};
#endif
void TProcess::Run() {
TWorker worker;
worker.Init(0);
for( int i = 0; i < fInput.size(); ++i )
worker.Add(fInput[i].i);
fOutput.i = worker.Result();
}
int main() {
vector<TInput> input(NInputs);
for ( int i = 0; i < NInputs; i++ ) {
input[i].i = i;
}
TProcess proc(input);
proc.Run();
TOutput output;
proc.GetOutput(output);
cout << output.i << endl;
}
The example is very simple, but that doesn't means that it's simply possible to transform it to one function --- it corresponds to big project. Therefore it is not possible to:
delete classes or functions, which already exists (but possible to modify them and create new)
make workers static or create only one copy of worker (each workers are temporary in many complicated functions and loops)
So how to modify it such that this will be something like this:
// TODO: TProcess declaration
struct TInput1 {
int i;
};
class TWorker1{
public:
void Init( TInput1 i ) { fResult = i; }
void Add( TInput1 i ) { fResult += i.i; }
int Result() { return fResult; }
private:
int fResult;
};
#else
struct TInput2 {
int i;
};
class TWorker2 {
public:
void Init( TInput2 i ) { fResult = i.i; }
void Add( TInput2 i ) { fResult ^= i.i; }
int Result() { return fResult; }
private:
int fResult;
};
void TProcess::Run() {
for( int i = 0; i < fInput.size(); ++i ) {
// TODO: choose and create a worker
worker.Add(fInput[i].i);
// TODO: get and save result
}
fOutput.i = worker.Result();
}
int main() {
vector<TInputBase> input(NInputs);
// TODO: fill input
TProcess proc(input);
proc.Run();
TOutput output;
proc.GetOutput(output);
cout << output.i << endl;
}
My initial idea was to use basic class and template functions, but there is no template virtual functions...
You've got the right idea with the vector<TInputBase> declaration in your second example -- you need to have a common base class for all inputs, and similarly for all workers:
class TInput {
}
class TInput1 : public TInput { ... }
class TInput2 : public TInput { ... }
class TWorker {
public:
void Init(TInput *input) = 0;
void Add(TInput *input) = 0;
int Result() = 0;
}
class TWorker1 : public TWorker { ... }
class TWorker2 : public TWorker { ... }
Note, however, that this means all workers can only take a TInput * as input and you will need to cast to the correct input class inside each worker class.
The simplest way to decide which worker class to use for a given input is to ask the input itself! You can have a virtual function in the input class that creates the right kind of worker:
class TInput {
virtual TWorker *createWorker() = 0;
}
class TInput1 : public TInput {
TWorker *createWorker() {
return new TWorker1();
}
}
class TInput2 : public TInput {
TWorker *createWorker() {
return new TWorker2();
}
}
If this is not possible for some reason, you can use typeid to determine the type of the input and create a corresponding worker instance.