user3417963
user3417963

Reputation: 11

Call function to do anything at x minutes

i have spend a lot of time for it but i cant find the right way to do it. I want a function thats called every x minutes to do over stuff, but without stopping my whole program. It's just a function in a large program. I have tried a lot of functions like difftime or others, but everything stops my program and difftime does not work for me, like this one

void ProcStatistics(int thisarg)

time_t end;
time(&start);
while (1) {
time(&end);
double dif = difftime (end,start);
if (dif < 600) 
{
std::cout << "Start" << std::endl;

//do other stuff

std::cout << "End" << std::endl;
time(&end);
return detour_ProcStatistics->GetOriginalFunction()(thisarg);
}

I cant use sleep, maybe a loop or something else, with a break or continue. The problem is that program time constantly updated, because it runs all the time.

Upvotes: 1

Views: 236

Answers (3)

Jfevold
Jfevold

Reputation: 422

The code below would work better than anything using sleep_for if maintaining timing is critical. If you're not sweating the microseconds, (picoseconds?) then Trevor's answer is a lot simpler.

Uses C++11 features. Must be linked with -lpthread if using g++ (at least for mine) Runs as written to give a simple and easy to understand demonstration

#include <chrono>
#include <thread>
#include <iostream>

//This is where you set the rate to call repeated_function at
constexpr int ancilary_function_rate_minutes = 3;

//This is the function which will be called repeatedly
void repeated_function(void)
{
  //TODO: Put useful code here
  //TODO: Be aware of race conditions, use std::mutex variables to guard conflicts


  //This code should be discarded for actual use, but makes a reasonable demonstration

  static int i = 0;
  std::cout << __PRETTY_FUNCTION__ << " " << i << std::endl;
  i++;
  return;
}

void ancilary_thread_main(void)
{
  std::chrono::system_clock::time_point tp =
  std::chrono::system_clock::now(); 

  while(1)
  {
    //use the below line for minutes for intended application
    //tp += std::chrono::minutes(ancilary_function_rate_minutes);

    //use the below line for seconds to see it run in realtime
    tp += std::chrono::seconds(3);

    //Note the above two durations are additive, you could use both


    repeated_function(); //This is where the function gets called repeatedly


    //By using sleep_until instead of sleep_for, and by only calling now()
    //  once, we do not lose the time it takes to run repeated_function and
    //  allow our rate to drift
    std::this_thread::sleep_until(tp);

    //Note that this will sleep AT LEAST until the given time, there is no
    //  guarantee that it will run then, but more likely will run the first
    //  time after that when a processor (core) becomes available.
  }
}

int main()
{
  //First launch the initial thread
  std::thread my_thread (ancilary_thread_main);


  //The rest of your code here


  //This code should be discarded for actual use, but makes a reasonable demonstration
  int i = 0;
  while(1) //Generally only acceptable in embedded applications
  {
    std::cout << "Main Thread " << i << std::endl;
    i++;
    //Because this look uses sleep_for, it will lose time over many iterations
    std::this_thread::sleep_for(std::chrono::milliseconds(500));
  }

  my_thread.join(); //This is unreachable, but in application, main loop will eventually exit.
  return 0;
}

Upvotes: 0

user3417963
user3417963

Reputation: 11

I think you are right, i have read about threads, but I dont really know how I can use it for this program. Maybe you can make a solution for me. Small snippet from main.ccp:

int AffAddPoint(int a1, int a2, int a3)
{
#ifdef TEST
std::cout << "(int)Points: " << (int)a2 << std::endl;
std::cout << "(LONGLONG)Points: " << (LONGLONG)a2 << std::endl;
#endif

detour_affinity->GetOriginalFunction()(a1, a2, a3);
}

// Function what i need ->
void ProcStatistics(int thisarg) 
{
{
 std::cout << "Start" << std::endl;
        char const* godbless = " 410 5";
        ((void(*)(int, char const*))0x082249E4)(0, godbless);
        godbless = " 627 4";
        std::cout << "End" << std::endl;
        }
return detour_ProcStatistics->GetOriginalFunction()(thisarg);
}
// <- Function End

detour_ProcStatistics = simpleHook<tProcStatistics>((unsigned int)0x081E3934, ProcStatistics);

void ConnectDB()
{
mysql_init(&m_dbuserxx);

small snippet from main.h

typedef void (*tProcStatistics)(int);

MologieDetours::Detour<tProcStatistics>* detour_ProcStatistics= NULL;

Upvotes: 0

Trevor Hickey
Trevor Hickey

Reputation: 37806

Please note, this is C+11 and above.

#include <chrono>
#include <thread>

//spawn a new thread as to not stop the whole program.
std::thread t([] {

    //call a function every n minutes
    while (1){
       std::this_thread::sleep_for(std::chrono::minutes(/*n minutes*/));
       function();
    }
});

//thread can now run in background, 
//and you don't have to worry about joining it.  
//i.e. a terminate call without an active exception
t.detach();

Upvotes: 1

Related Questions