LLVM API Documentation

Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

SlowOperationInformer.cpp

Go to the documentation of this file.
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 }