1 /*********************************************************************/ 2 // dar - disk archive - a backup/restoration program 3 // Copyright (C) 2002-2052 Denis Corbin 4 // 5 // This program is free software; you can redistribute it and/or 6 // modify it under the terms of the GNU General Public License 7 // as published by the Free Software Foundation; either version 2 8 // of the License, or (at your option) any later version. 9 // 10 // This program is distributed in the hope that it will be useful, 11 // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 // GNU General Public License for more details. 14 // 15 // You should have received a copy of the GNU General Public License 16 // along with this program; if not, write to the Free Software 17 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 18 // 19 // to contact the author : http://dar.linux.free.fr/email.html 20 /*********************************************************************/ 21 22 /// \file thread_cancellation.hpp 23 /// \brief to be able to cancel libdar operation while running in a given thread. 24 /// \ingroup API 25 /// 26 /// the class thread_cancellation implemented in this module 27 /// permits to define checkpoints where is looked whether the current 28 /// thread has been marked as to be canceled by the user 29 /// The advantage of this class is that it then throws a Euser_abort 30 /// exception which properly terminates the libdar operation in the thread 31 /// freeing allocated memory and release mutex properly. Note that the thread 32 /// is not canceled but libdar call in this thread returns as soon as a checkpoint 33 /// is met during the execution. 34 35 #ifndef THREAD_CANCELLATION_HPP 36 #define THREAD_CANCELLATION_HPP 37 38 #include "../my_config.h" 39 40 extern "C" 41 { 42 #if MUTEX_WORKS 43 #if HAVE_PTHREAD_H 44 #include <pthread.h> 45 #endif 46 #endif 47 } 48 #include <list> 49 #include <map> 50 #include "integers.hpp" 51 52 namespace libdar 53 { 54 55 /// class to be used as parent to provide checkpoints to inherited classes 56 57 /// the class provides a checkpoints to inherited classes and a mechanism 58 /// that let any libdar external code to ask the termination of a libdar 59 /// call executing in a given thread. This does not imply the termination 60 /// of the thread itself but it implies the return of the thread execution 61 /// to the code that called libdar 62 /// \ingroup Private 63 64 class thread_cancellation 65 { 66 public: 67 68 /// the constructor 69 thread_cancellation(); 70 71 /// the destructor 72 virtual ~thread_cancellation() throw(Ebug); 73 74 /// Checkpoint test : whether the current libdar call must abort or not 75 76 /// \exception Euser_abort is thrown if the thread the checkpoint is running 77 /// from is marked as to be canceled. 78 void check_self_cancellation() const; 79 80 /// by default delayed (non immediate) cancellation generate a specific exception, 81 /// it is possible for delayed cancellation only, do block such exceptions for a certain time 82 83 ///\param[in] mode can be set to true to block delayed cancellations 84 ///\note when unblocking delayed cancellations, if a delayed cancellation has been 85 ///requested during the ignore time, it will be thrown by this call 86 void block_delayed_cancellation(bool mode); 87 88 89 #if MUTEX_WORKS 90 /// marks the thread given in argument as to be canceled 91 92 //! \param[in] tid the thread ID of the thread where any libdar call must abort 93 //! \param[in] x_immediate whether the cancellation must be as fast as possible or can take a 94 //! \param[in] x_flag is a value to transmit to the Ethread_cancel exception used to cancel libdar's call stack 95 //! little time to make a usable archive 96 static void cancel(pthread_t tid, bool x_immediate, U_64 x_flag); 97 98 /// gives the cancellation status of the given thread ID 99 100 //! \param[in] tid the thread to check 101 //! \return true if the given thread is under cancellation 102 static bool cancel_status(pthread_t tid); 103 104 /// abort the pending thread cancellation 105 106 /// \return true if the pending thread was still running and 107 /// false if it has already aborted. 108 static bool clear_pending_request(pthread_t tid); 109 110 /// define association between threads: if a cancellation is requested for src, it will also be requested for dst 111 /// 112 /// \param[in] src orginal target for cancellation 113 /// \param[in] dst additional target for cancellation 114 /// \note that the propagation of cancellation request with association is transitive 115 /// in other word if t1 is associtated with t2 which is associated with t3, 116 /// requesting cancellation of t1 will also lead to signal cancellation request for t2 and t3 117 /// \note that association is not symmetrical, unless associating A to B *and* B to A 118 static void associate_tid_to_tid(pthread_t src, pthread_t dst); 119 120 /// remove all association from a given tid to any other thread 121 /// 122 /// \param[in] src is the thread id that has to be removed from the 123 /// association table (see associate_tid_to_tid() above). 124 static void remove_association_for_tid(pthread_t src); 125 126 /// remove all association for any thread to a given targetted thread 127 /// 128 /// \param[in] dst all association target at dst will be removed 129 static void remove_association_targeted_at(pthread_t dst); 130 131 /// clean class info from all related information about that thread, like associations and pending cancellations 132 static void dead_thread(pthread_t tid); 133 #endif 134 135 /// method for debugging/control purposes count()136 static U_I count() 137 { 138 #if MUTEX_WORKS 139 return info.size(); 140 #else 141 return 0; 142 #endif 143 }; 144 145 #if MUTEX_WORKS 146 private: 147 148 // class types 149 150 struct fields 151 { 152 pthread_t tid; ///< thread id of the current thread 153 bool block_delayed; ///< whether we buffer any delayed cancellation requests for "this" thread 154 bool immediate; ///< whether we take a few more second to make a real usable archive 155 bool cancellation; ///< true if a thread has to be canceled 156 U_64 flag; ///< user defined informational field, given to the Ethread_cancel constructor 157 }; 158 159 // object information 160 161 fields status; 162 163 // class's static variables and types 164 165 static pthread_mutex_t access; //< mutex for the access to "info" 166 static std::list<thread_cancellation *> info; //< list of all object 167 static std::list<fields> preborn; //< canceled thread that still not have a thread_cancellation object to deal with cancellation 168 static std::multimap<pthread_t, pthread_t> thread_asso; //< which other thread to propagate cancellation request to, given a initial tid 169 170 // helper class routing 171 static void set_cancellation_in_info_for(pthread_t tid, 172 bool cancel_status, 173 bool x_immediate, 174 U_64 x_flag, 175 bool & found, 176 bool & previous_val, 177 bool & bug); 178 static void add_to_preborn(pthread_t tid, bool x_immediate, U_64 x_flag); 179 static void remove_from_preborn(pthread_t tid, bool & found, bool & prev); 180 static void find_asso_tid_with(pthread_t tid, 181 std::multimap<pthread_t, pthread_t>::iterator & begin, 182 std::multimap<pthread_t, pthread_t>::iterator & end); 183 184 #endif 185 }; 186 187 } // end of namespace 188 189 #endif 190