#include #include #include #include #include #include #include #ifdef USE_EXCEPTIONS bool interrupt_state = false; # define QUIT \ do \ { \ if (interrupt_state) \ { \ interrupt_state = false; \ std::cerr << "do_something: throwing interrupt_exception" \ << std::endl; \ throw interrupt_exception (); \ } \ } \ while (0) # define JUMP_TO_TOP_LEVEL do { interrupt_state = true; } while (0) # define INIT_JMP_BUF do { } while (0) #else # include sigset_t signal_mask; jmp_buf top_level; # define QUIT do { } while (0) # define JUMP_TO_TOP_LEVEL longjmp (top_level, 1) # define INIT_JMP_BUF \ do \ { \ save_signal_mask (); \ if (setjmp (top_level) != 0) \ { \ std::cout << "\n"; \ restore_signal_mask (); \ } \ } \ while (0) void save_signal_mask (void) { std::cerr << "saving signal mask" << std::endl; sigprocmask (0, 0, &signal_mask); } void restore_signal_mask (void) { std::cerr << "restoring signal mask" << std::endl; sigprocmask (SIG_SETMASK, &signal_mask, 0); } #endif class interrupt_exception { // Empty. }; #define RETSIGTYPE void typedef RETSIGTYPE sig_handler (int); sig_handler * set_signal_handler (int sig, sig_handler *handler) { struct sigaction act, oact; act.sa_handler = handler; act.sa_flags = 0; sigemptyset (&act.sa_mask); sigemptyset (&oact.sa_mask); sigaction (sig, &act, &oact); return oact.sa_handler; } void sigint_handler (int) { std::cerr << "sigint_handler" << std::endl; JUMP_TO_TOP_LEVEL; } class big_storage_hog { public: big_storage_hog (int n = 1024*1024) : p (0) { std::cerr << "big_storage_hog: constructor" << std::endl; init (n); } ~big_storage_hog (void) { std::cerr << "big_storage_hog: destructor" << std::endl; delete [] p; } void init (int n) { p = new double [n]; for (int i = 0; i < n; i++) p[i] = sin (i) * cos (i); } private: double *p; }; void do_something (void) { std::cerr << "do_something: creating big_storage_hog object" << std::endl; big_storage_hog x; #if DO_SLEEP std::cerr << "do_something: sleeping for three seconds" << std::endl; sleep (3); #else std::cerr << "do_something: working in C++ for three seconds" << std::endl; time_t t = time(NULL); double sum = 0.0; while (time(NULL) - t < 3) for (int i=0; i < 1000000; i++) sum += i; std::cerr << "do_something: result is " << sum << std::endl; #endif std::cerr << "do_something: wake up" << std::endl << std::flush; QUIT; std::cerr << "do_something: returning" << std::endl; } int main (void) { int k = 0; INIT_JMP_BUF; std::cerr << "main: setting SIGINT handler" << std::endl; set_signal_handler (SIGINT, sigint_handler); std::cerr << "main: entering main loop" << std::endl; while (1) { try { std::cerr << "main: calling do_something" << std::endl << std::flush; do_something (); } catch (interrupt_exception) { std::cerr << "interrupt_exception caught" << std::endl; } std::cerr << "k = " << k << std::endl; if (k++ > 2) break; } }