LLVM API Documentation
00001 //===-- SlowOperationInformer.cpp - Keep the user informed ----------------===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file was developed by the LLVM research group and is distributed under 00006 // the University of Illinois Open Source License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // This file implements the SlowOperationInformer class for the LLVM debugger. 00011 // 00012 //===----------------------------------------------------------------------===// 00013 00014 #include "llvm/Support/SlowOperationInformer.h" 00015 #include "llvm/Config/config.h" // Get the signal handler return type 00016 #include <iostream> 00017 #include <sstream> 00018 #include <signal.h> 00019 #include <unistd.h> 00020 #include <cassert> 00021 using namespace llvm; 00022 00023 /// OperationCancelled - This flag is set by the SIGINT signal handler if the 00024 /// user presses CTRL-C. 00025 static volatile bool OperationCancelled; 00026 00027 /// ShouldShowStatus - This flag gets set if the operation takes a long time. 00028 /// 00029 static volatile bool ShouldShowStatus; 00030 00031 /// NestedSOI - Sanity check. SlowOperationInformers cannot be nested or run in 00032 /// parallel. This ensures that they never do. 00033 static bool NestedSOI = false; 00034 00035 static RETSIGTYPE SigIntHandler(int Sig) { 00036 OperationCancelled = true; 00037 signal(SIGINT, SigIntHandler); 00038 } 00039 00040 static RETSIGTYPE SigAlarmHandler(int Sig) { 00041 ShouldShowStatus = true; 00042 } 00043 00044 static void (*OldSigIntHandler) (int); 00045 00046 00047 SlowOperationInformer::SlowOperationInformer(const std::string &Name) 00048 : OperationName(Name), LastPrintAmount(0) { 00049 assert(!NestedSOI && "SlowerOperationInformer objects cannot be nested!"); 00050 NestedSOI = true; 00051 00052 OperationCancelled = 0; 00053 ShouldShowStatus = 0; 00054 00055 signal(SIGALRM, SigAlarmHandler); 00056 OldSigIntHandler = signal(SIGINT, SigIntHandler); 00057 alarm(1); 00058 } 00059 00060 SlowOperationInformer::~SlowOperationInformer() { 00061 NestedSOI = false; 00062 if (LastPrintAmount) { 00063 // If we have printed something, make _sure_ we print the 100% amount, and 00064 // also print a newline. 00065 std::cout << std::string(LastPrintAmount, '\b') << "Progress " 00066 << OperationName << ": 100% \n"; 00067 } 00068 00069 alarm(0); 00070 signal(SIGALRM, SIG_DFL); 00071 signal(SIGINT, OldSigIntHandler); 00072 } 00073 00074 /// progress - Clients should periodically call this method when they are in 00075 /// an exception-safe state. The Amount variable should indicate how far 00076 /// along the operation is, given in 1/10ths of a percent (in other words, 00077 /// Amount should range from 0 to 1000). 00078 void SlowOperationInformer::progress(unsigned Amount) { 00079 if (OperationCancelled) { 00080 std::cout << "\n"; 00081 LastPrintAmount = 0; 00082 throw "While " + OperationName + ", operation cancelled."; 00083 } 00084 00085 // If we haven't spent enough time in this operation to warrant displaying the 00086 // progress bar, don't do so yet. 00087 if (!ShouldShowStatus) 00088 return; 00089 00090 // Delete whatever we printed last time. 00091 std::string ToPrint = std::string(LastPrintAmount, '\b'); 00092 00093 std::ostringstream OS; 00094 OS << "Progress " << OperationName << ": " << Amount/10; 00095 if (unsigned Rem = Amount % 10) 00096 OS << "." << Rem << "%"; 00097 else 00098 OS << "% "; 00099 00100 LastPrintAmount = OS.str().size(); 00101 std::cout << ToPrint+OS.str() << std::flush; 00102 }