blob: 9fd718e3060707a342546898e8d83ec3969a951f [file] [log] [blame]
Chris Lattnera2e93632003-12-31 05:40:02 +00001//===-- SlowOperationInformer.cpp - Keep the user informed ----------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file was developed by the LLVM research group and is distributed under
6// the University of Illinois Open Source License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file implements the SlowOperationInformer class for the LLVM debugger.
11//
12//===----------------------------------------------------------------------===//
13
14#include "Support/SlowOperationInformer.h"
15#include "Config/config.h" // Get the signal handler return type
16#include <iostream>
17#include <sstream>
18#include <signal.h>
19#include <unistd.h>
Chris Lattner0a5f0332003-12-31 07:31:10 +000020#include <cassert>
Chris Lattnera2e93632003-12-31 05:40:02 +000021using namespace llvm;
22
23/// OperationCancelled - This flag is set by the SIGINT signal handler if the
24/// user presses CTRL-C.
25static volatile bool OperationCancelled;
26
27/// ShouldShowStatus - This flag gets set if the operation takes a long time.
28///
29static volatile bool ShouldShowStatus;
30
31/// NestedSOI - Sanity check. SlowOperationInformers cannot be nested or run in
32/// parallel. This ensures that they never do.
33static bool NestedSOI = false;
34
35static RETSIGTYPE SigIntHandler(int Sig) {
36 OperationCancelled = true;
37 signal(SIGINT, SigIntHandler);
38}
39
40static RETSIGTYPE SigAlarmHandler(int Sig) {
41 ShouldShowStatus = true;
42}
43
44static sighandler_t OldSigIntHandler;
45
46
47SlowOperationInformer::SlowOperationInformer(const std::string &Name)
48 : OperationName(Name), LastPrintAmount(0) {
49 assert(!NestedSOI && "SlowerOperationInformer objects cannot be nested!");
50 NestedSOI = true;
51
52 OperationCancelled = 0;
53 ShouldShowStatus = 0;
54
55 signal(SIGALRM, SigAlarmHandler);
56 OldSigIntHandler = signal(SIGINT, SigIntHandler);
57 alarm(1);
58}
59
60SlowOperationInformer::~SlowOperationInformer() {
61 NestedSOI = false;
Chris Lattner9e260272003-12-31 10:20:38 +000062 if (LastPrintAmount) {
63 // If we have printed something, make _sure_ we print the 100% amount, and
64 // also print a newline.
65 std::cout << std::string(LastPrintAmount, '\b') << "Progress "
66 << OperationName << ": 100% \n";
67 }
Chris Lattnera2e93632003-12-31 05:40:02 +000068
69 alarm(0);
70 signal(SIGALRM, SIG_DFL);
71 signal(SIGINT, OldSigIntHandler);
72}
73
74/// progress - Clients should periodically call this method when they are in
75/// an exception-safe state. The Amount variable should indicate how far
76/// along the operation is, given in 1/10ths of a percent (in other words,
77/// Amount should range from 0 to 1000).
78void SlowOperationInformer::progress(unsigned Amount) {
79 if (OperationCancelled) {
80 std::cout << "\n";
81 LastPrintAmount = 0;
82 throw "While " + OperationName + ", operation cancelled.";
83 }
84
85 // If we haven't spent enough time in this operation to warrant displaying the
86 // progress bar, don't do so yet.
87 if (!ShouldShowStatus)
88 return;
89
90 // Delete whatever we printed last time.
91 std::string ToPrint = std::string(LastPrintAmount, '\b');
92
93 std::ostringstream OS;
Chris Lattner9e260272003-12-31 10:20:38 +000094 OS << "Progress " << OperationName << ": " << Amount/10;
95 if (unsigned Rem = Amount % 10)
96 OS << "." << Rem << "%";
97 else
98 OS << "% ";
Chris Lattnera2e93632003-12-31 05:40:02 +000099
100 LastPrintAmount = OS.str().size();
101 std::cout << ToPrint+OS.str() << std::flush;
102}