1

I have a function that performs a potentially very slow calculation (see below for a basic example). The function does not write to existing resources, there are no side effects, and only uses automatic allocation for all its variables (so new and delete are never called, outside of any calls within the standard library).

Is it possible to time-out the function after it's been running for a certain amount of time and free the heap memory it has requested, without modifying the function itself?

//Returns all primes up to n (fairly bad implementation; the idea is that it runs too long)
std::vector<int> primes(int n) {
    std::vector<int> list={2};
    for (int i = 3; i <= n; i++) {
        bool flag= 0;
        for (const auto& j : list) {
            if (i % j == 0) {
                flag= 1;
                break;
            }
        }
        if (!flag)
            list.push_back(i);
    }
    return list;
}

And main looks like this:

int main(){
std::vector<std::vector<int>> list_of_lists(6);
#pragma omp parallel for num_threads(6)
    for (int n = 1; n < 7; n++) {
       //I want the assignment below to make list_of_lists[n-1] empty if it takes more than 5 secs
        list_of_lists[n-1] = primes(n*100000);
    }
//use the list_of_lists
}

The function primes itself must not be modified.

There is a way to use std::async to check for the time elapsed from outside the function, but unfortunately there is no way to kill a std::future before it finishes. So I am wondering what's the best way to do this.

curiousguy
  • 8,038
  • 2
  • 40
  • 58
user12005284
  • 17
  • 1
  • 5
  • 1
    Not easily, why can't you modify the `primes` function? Also what OS does this have to run on, or is it an academic exercise? – gct Jan 18 '20 at 19:02
  • 1
    C++ does not offer any such capability, so `std::async` is not going to help you. Also try to stick to either OpenMP or C++11 threading constructs. It is probably not a good idea to mix the two. You probably need to use some OS-specific API if you *really* need to do this. – walnut Jan 18 '20 at 19:04
  • @gct In reality the ```primes``` function is another function calling other functions calling.... There are many unpredictable points where any of these functions could slow down, so making checks everywhere and passing timeout variables would be quite the undertaking. OS are Windows and Linux. – user12005284 Jan 18 '20 at 19:05
  • 1
    Yeah there's no easy way to pre-empty a generic function in C++. Think of it this way: with inlining those functions might not even exist at _all_ at runtime, so what would you pre-empt? Doing it cross platform will be even harder. – gct Jan 18 '20 at 19:07
  • My best answer would be to look at Boost.Process and run the computation in a child process that you can then kill if it takes too long. – gct Jan 18 '20 at 19:08
  • @gct Is there a standard library alternative to boost::process ? And are there any performance penalties I should be aware of? – user12005284 Jan 18 '20 at 19:10
  • 1
    There's no standardized process management in c++ (yet) unfortunately. Spawning a process might be a _little_ more expensive, but I think it'll be close to spawning a thread in general, at least for Linux, I'm not very familiar with Windows. – gct Jan 18 '20 at 19:11
  • See also the answer on [this question](https://stackoverflow.com/questions/13893060/i-want-to-kill-a-stdthread-using-its-thread-object) with regards to general considerations about memory resources when you kill a thread. – walnut Jan 18 '20 at 19:11
  • @gct Also the program will run on the OS it's compiled in (i.e. I can have a preprocessor directive that checks the OS being used). – user12005284 Jan 18 '20 at 19:12
  • Even with a new process, terminating it is very bad practise unless you are sure that there will be no remnants (like some temp file permanently filling your temp directory). Besides, in windows, processes are usually big and duplicating one just for a single function is considered bad practise. – Michael Chourdakis Jan 18 '20 at 19:15
  • @MichaelChourdakis There are no files being written, only heap memory being allocated. I can't think of any other possible remnants. – user12005284 Jan 18 '20 at 19:16
  • @user12005284 it's still a bad habit of doing things like that. – Michael Chourdakis Jan 18 '20 at 19:17

2 Answers2

1

Without the function noticing, any sort of "termination" is risky. The best you can do is have a loop which periodically checks for a "terminate" flag visible outside the function and exit, or to measure the time elapsed within the function.

for(;;)
{
    if (bExit)
       break;

    // calculations here
}

The bad way is to run the function within a thread to be terminated after some time has elapsed.

Michael Chourdakis
  • 10,345
  • 3
  • 42
  • 78
0

There is strictly no way to know when it's safe, and how it would be possible to fix the modifiable state of the program when a function is running.

A function can be allocate ressources, even internal program ressources. For that purpose it needs to modify global data structures and these modifications are probably not atomic nor would be correctly reversed if they were.

You need some cooperation.

curiousguy
  • 8,038
  • 2
  • 40
  • 58