Fawkes API  Fawkes Development Version
multi.cpp
00001 
00002 /***************************************************************************
00003  *  multi.h - Fawkes multi logger
00004  *
00005  *  Created: Mon May 07 16:44:15 2007
00006  *  Copyright  2006-2007  Tim Niemueller [www.niemueller.de]
00007  *
00008  ****************************************************************************/
00009 
00010 /*  This program is free software; you can redistribute it and/or modify
00011  *  it under the terms of the GNU General Public License as published by
00012  *  the Free Software Foundation; either version 2 of the License, or
00013  *  (at your option) any later version. A runtime exception applies to
00014  *  this software (see LICENSE.GPL_WRE file mentioned below for details).
00015  *
00016  *  This program is distributed in the hope that it will be useful,
00017  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00018  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00019  *  GNU Library General Public License for more details.
00020  *
00021  *  Read the full text in the LICENSE.GPL_WRE file in the doc directory.
00022  */
00023 
00024 #include <logging/multi.h>
00025 #include <logging/logger.h>
00026 
00027 #include <core/utils/lock_list.h>
00028 #include <core/threading/thread.h>
00029 
00030 #include <sys/time.h>
00031 #include <time.h>
00032 
00033 namespace fawkes {
00034 
00035 /// @cond INTERNALS
00036 class MultiLoggerData
00037 {
00038  public:
00039   MultiLoggerData()
00040   {
00041     mutex = new Mutex();
00042   }
00043 
00044   ~MultiLoggerData()
00045   {
00046     delete mutex;
00047     mutex = NULL;
00048   }
00049 
00050   LockList<Logger *>            loggers;
00051   LockList<Logger *>::iterator  logit;
00052   Mutex                        *mutex;
00053   Thread::CancelState           old_state;
00054 };
00055 /// @endcond
00056 
00057 
00058 /** @class MultiLogger <logging/multi.h>
00059  * Log through multiple loggers.
00060  * It can be hand to have the opportunity to log to multiple channels, for
00061  * example log to a file and via network to a remote console. This can be
00062  * done with the MultiLogger. You can add an arbitrary number of loggers
00063  * to log the output to. Use the minimum number of necessary loggers though
00064  * because this can cause a high burden on log users if you have too many
00065  * loggers.
00066  *
00067  * Note that the multi logger takes over the ownership of the logger. That
00068  * means that the multi logger destroys all sub-loggers when it is deleted
00069  * itself. If you want to take over the loggers without destroying them you
00070  * have to properly remove them before destroying the multi logger.
00071  *
00072  * @author Tim Niemueller
00073  */
00074 
00075 /** Constructor.
00076  * This will create the logger without any sub-loggers. Message that are
00077  * logged are simply ignored.
00078  */
00079 MultiLogger::MultiLogger()
00080 {
00081   data = new MultiLoggerData();
00082 }
00083 
00084 
00085 /** Constructor.
00086  * This sets one sub-logger that messages are sent to.
00087  * @param logger sub-logger
00088  */
00089 MultiLogger::MultiLogger(Logger *logger)
00090 {
00091   data = new MultiLoggerData();
00092   data->loggers.push_back_locked(logger);
00093 }
00094 
00095 
00096 /** Destructor.
00097  * This will destroy all sub-data->loggers (they are deleted).
00098  */
00099 MultiLogger::~MultiLogger()
00100 {
00101   data->loggers.lock();
00102   for (data->logit = data->loggers.begin(); data->logit != data->loggers.end(); ++data->logit) {
00103     delete (*data->logit);
00104   }
00105   data->loggers.clear();
00106   data->loggers.unlock();
00107   delete data;
00108 }
00109 
00110 
00111 /** Add a logger.
00112  * @param logger new sub-logger to add
00113  */
00114 void
00115 MultiLogger::add_logger(Logger *logger)
00116 {
00117   data->mutex->lock();
00118   Thread::set_cancel_state(Thread::CANCEL_DISABLED, &(data->old_state));
00119   data->loggers.lock();
00120   data->loggers.push_back(logger);
00121   data->loggers.sort();
00122   data->loggers.unique();
00123   data->loggers.unlock();
00124   Thread::set_cancel_state(data->old_state);
00125   data->mutex->unlock();
00126 }
00127 
00128 
00129 /** Remove logger.
00130  * @param logger Sub-logger to remove
00131  */
00132 void
00133 MultiLogger::remove_logger(Logger *logger)
00134 {
00135   data->mutex->lock();
00136   Thread::set_cancel_state(Thread::CANCEL_DISABLED, &(data->old_state));
00137 
00138   data->loggers.remove_locked(logger);
00139   Thread::set_cancel_state(data->old_state);
00140   data->mutex->unlock();
00141 }
00142 
00143 
00144 void
00145 MultiLogger::set_loglevel(LogLevel level)
00146 {
00147   data->mutex->lock();
00148   Thread::set_cancel_state(Thread::CANCEL_DISABLED, &(data->old_state));
00149 
00150   for (data->logit = data->loggers.begin(); data->logit != data->loggers.end(); ++data->logit) {
00151     (*data->logit)->set_loglevel(level);
00152   }
00153   Thread::set_cancel_state(data->old_state);
00154   data->mutex->unlock();
00155 }
00156 
00157 
00158 void
00159 MultiLogger::log(LogLevel level, const char *component, const char *format, ...)
00160 {
00161   struct timeval now;
00162   gettimeofday(&now, NULL);
00163   data->mutex->lock();
00164   Thread::set_cancel_state(Thread::CANCEL_DISABLED, &(data->old_state));
00165 
00166   va_list va;
00167   va_start(va, format);
00168   for (data->logit = data->loggers.begin(); data->logit != data->loggers.end(); ++data->logit) {
00169     va_list vac;
00170     va_copy(vac, va);
00171     (*data->logit)->vtlog(level, &now, component, format, vac);
00172     va_end(vac);
00173   }
00174   va_end(va);
00175   Thread::set_cancel_state(data->old_state);
00176   data->mutex->unlock();
00177 }
00178 
00179 
00180 void
00181 MultiLogger::log_debug(const char *component, const char *format, ...)
00182 {
00183   struct timeval now;
00184   gettimeofday(&now, NULL);
00185   data->mutex->lock();
00186   Thread::set_cancel_state(Thread::CANCEL_DISABLED, &(data->old_state));
00187 
00188   va_list va;
00189   va_start(va, format);
00190   for (data->logit = data->loggers.begin(); data->logit != data->loggers.end(); ++data->logit) {
00191     va_list vac;
00192     va_copy(vac, va);
00193     (*data->logit)->vlog_debug(component, format, vac);
00194     va_end(vac);
00195   }
00196   va_end(va);
00197   Thread::set_cancel_state(data->old_state);
00198   data->mutex->unlock();
00199 }
00200 
00201 
00202 void
00203 MultiLogger::log_info(const char *component, const char *format, ...)
00204 {
00205   struct timeval now;
00206   gettimeofday(&now, NULL);
00207   data->mutex->lock();
00208   Thread::set_cancel_state(Thread::CANCEL_DISABLED, &(data->old_state));
00209 
00210   va_list va;
00211   va_start(va, format);
00212   for (data->logit = data->loggers.begin(); data->logit != data->loggers.end(); ++data->logit) {
00213     va_list vac;
00214     va_copy(vac, va);
00215     (*data->logit)->vlog_info(component, format, vac);
00216     va_end(vac);
00217   }
00218   va_end(va);
00219   Thread::set_cancel_state(data->old_state);
00220   data->mutex->unlock();
00221 }
00222 
00223 
00224 void
00225 MultiLogger::log_warn(const char *component, const char *format, ...)
00226 {
00227   struct timeval now;
00228   gettimeofday(&now, NULL);
00229   data->mutex->lock();
00230   Thread::set_cancel_state(Thread::CANCEL_DISABLED, &(data->old_state));
00231 
00232   va_list va;
00233   va_start(va, format);
00234   for (data->logit = data->loggers.begin(); data->logit != data->loggers.end(); ++data->logit) {
00235     va_list vac;
00236     va_copy(vac, va);
00237     (*data->logit)->vlog_warn(component, format, vac);
00238     va_end(vac);
00239   }
00240   va_end(va);
00241   Thread::set_cancel_state(data->old_state);
00242   data->mutex->unlock();
00243 }
00244 
00245 
00246 void
00247 MultiLogger::log_error(const char *component, const char *format, ...)
00248 {
00249   struct timeval now;
00250   gettimeofday(&now, NULL);
00251   data->mutex->lock();
00252   Thread::set_cancel_state(Thread::CANCEL_DISABLED, &(data->old_state));
00253 
00254   va_list va;
00255   va_start(va, format);
00256   for (data->logit = data->loggers.begin(); data->logit != data->loggers.end(); ++data->logit) {
00257     va_list vac;
00258     va_copy(vac, va);
00259     (*data->logit)->vlog_error(component, format, vac);
00260     va_end(vac);
00261   }
00262   va_end(va);
00263   Thread::set_cancel_state(data->old_state);
00264   data->mutex->unlock();
00265 }
00266 
00267 
00268 void
00269 MultiLogger::log(LogLevel level, const char *component, Exception &e)
00270 {
00271   struct timeval now;
00272   gettimeofday(&now, NULL);
00273   data->mutex->lock();
00274   Thread::set_cancel_state(Thread::CANCEL_DISABLED, &(data->old_state));
00275 
00276   for (data->logit = data->loggers.begin(); data->logit != data->loggers.end(); ++data->logit) {
00277     (*data->logit)->log(level, component, e);
00278   }
00279   Thread::set_cancel_state(data->old_state);
00280   data->mutex->unlock();
00281 }
00282 
00283 
00284 void
00285 MultiLogger::log_debug(const char *component, Exception &e)
00286 {
00287   struct timeval now;
00288   gettimeofday(&now, NULL);
00289   data->mutex->lock();
00290   Thread::set_cancel_state(Thread::CANCEL_DISABLED, &(data->old_state));
00291 
00292   for (data->logit = data->loggers.begin(); data->logit != data->loggers.end(); ++data->logit) {
00293     (*data->logit)->tlog_debug(&now, component, e);
00294   }
00295 
00296   Thread::set_cancel_state(data->old_state);
00297   data->mutex->unlock();
00298 }
00299 
00300 void
00301 MultiLogger::log_info(const char *component, Exception &e)
00302 {
00303   struct timeval now;
00304   gettimeofday(&now, NULL);
00305   data->mutex->lock();
00306   Thread::set_cancel_state(Thread::CANCEL_DISABLED, &(data->old_state));
00307 
00308   for (data->logit = data->loggers.begin(); data->logit != data->loggers.end(); ++data->logit) {
00309     (*data->logit)->tlog_info(&now, component, e);
00310   }
00311   Thread::set_cancel_state(data->old_state);
00312   data->mutex->unlock();
00313 }
00314 
00315 
00316 void
00317 MultiLogger::log_warn(const char *component, Exception &e)
00318 {
00319   struct timeval now;
00320   gettimeofday(&now, NULL);
00321   data->mutex->lock();
00322   Thread::set_cancel_state(Thread::CANCEL_DISABLED, &(data->old_state));
00323 
00324   for (data->logit = data->loggers.begin(); data->logit != data->loggers.end(); ++data->logit) {
00325     (*data->logit)->tlog_warn(&now, component, e);
00326   }
00327   Thread::set_cancel_state(data->old_state);
00328   data->mutex->unlock();
00329 }
00330 
00331 
00332 void
00333 MultiLogger::log_error(const char *component, Exception &e)
00334 {
00335   struct timeval now;
00336   gettimeofday(&now, NULL);
00337   data->mutex->lock();
00338   Thread::set_cancel_state(Thread::CANCEL_DISABLED, &(data->old_state));
00339 
00340   for (data->logit = data->loggers.begin(); data->logit != data->loggers.end(); ++data->logit) {
00341     (*data->logit)->tlog_error(&now, component, e);
00342   }
00343   Thread::set_cancel_state(data->old_state);
00344   data->mutex->unlock();
00345 }
00346 
00347 
00348 void
00349 MultiLogger::vlog(LogLevel level,
00350                   const char *component, const char *format, va_list va)
00351 {
00352   struct timeval now;
00353   gettimeofday(&now, NULL);
00354   data->mutex->lock();
00355   Thread::set_cancel_state(Thread::CANCEL_DISABLED, &(data->old_state));
00356 
00357   for (data->logit = data->loggers.begin(); data->logit != data->loggers.end(); ++data->logit) {
00358     va_list vac;
00359     va_copy(vac, va);
00360     (*data->logit)->vlog(level, component, format, vac);
00361     va_end(vac);
00362   }
00363   Thread::set_cancel_state(data->old_state);
00364   data->mutex->unlock();
00365 }
00366 
00367 
00368 void
00369 MultiLogger::vlog_debug(const char *component, const char *format, va_list va)
00370 {
00371   struct timeval now;
00372   gettimeofday(&now, NULL);
00373   data->mutex->lock();
00374   Thread::set_cancel_state(Thread::CANCEL_DISABLED, &(data->old_state));
00375 
00376   for (data->logit = data->loggers.begin(); data->logit != data->loggers.end(); ++data->logit) {
00377     va_list vac;
00378     va_copy(vac, va);
00379     (*data->logit)->vtlog_debug(&now, component, format, vac);
00380     va_end(vac);
00381   }
00382   Thread::set_cancel_state(data->old_state);
00383   data->mutex->unlock();
00384 }
00385 
00386 
00387 void
00388 MultiLogger::vlog_info(const char *component, const char *format, va_list va)
00389 {
00390   struct timeval now;
00391   gettimeofday(&now, NULL);
00392   data->mutex->lock();
00393   Thread::set_cancel_state(Thread::CANCEL_DISABLED, &(data->old_state));
00394 
00395   for (data->logit = data->loggers.begin(); data->logit != data->loggers.end(); ++data->logit) {
00396     va_list vac;
00397     va_copy(vac, va);
00398     (*data->logit)->vtlog_info(&now, component, format, vac);
00399     va_end(vac);
00400   }
00401   Thread::set_cancel_state(data->old_state);
00402   data->mutex->unlock();
00403 }
00404 
00405 
00406 void
00407 MultiLogger::vlog_warn(const char *component, const char *format, va_list va)
00408 {
00409   struct timeval now;
00410   gettimeofday(&now, NULL);
00411   data->mutex->lock();
00412   Thread::set_cancel_state(Thread::CANCEL_DISABLED, &(data->old_state));
00413 
00414   for (data->logit = data->loggers.begin(); data->logit != data->loggers.end(); ++data->logit) {
00415     va_list vac;
00416     va_copy(vac, va);
00417     (*data->logit)->vtlog_warn(&now, component, format, vac);
00418     va_end(vac);
00419   }
00420   Thread::set_cancel_state(data->old_state);
00421   data->mutex->unlock();
00422 }
00423 
00424 
00425 void
00426 MultiLogger::vlog_error(const char *component, const char *format, va_list va)
00427 {
00428   struct timeval now;
00429   gettimeofday(&now, NULL);
00430   data->mutex->lock();
00431   Thread::set_cancel_state(Thread::CANCEL_DISABLED, &(data->old_state));
00432 
00433   for (data->logit = data->loggers.begin(); data->logit != data->loggers.end(); ++data->logit) {
00434     va_list vac;
00435     va_copy(vac, va);
00436     (*data->logit)->vtlog_error(&now, component, format, vac);
00437     va_end(vac);
00438   }
00439   Thread::set_cancel_state(data->old_state);
00440   data->mutex->unlock();
00441 }
00442 
00443 void
00444 MultiLogger::tlog(LogLevel level, struct timeval *t,
00445                   const char *component, const char *format, ...)
00446 {
00447   data->mutex->lock();
00448   Thread::set_cancel_state(Thread::CANCEL_DISABLED, &(data->old_state));
00449   va_list va;
00450   va_start(va, format);
00451   for (data->logit = data->loggers.begin(); data->logit != data->loggers.end(); ++data->logit) {
00452     va_list vac;
00453     va_copy(vac, va);
00454     (*data->logit)->vtlog(level, t, component, format, vac);
00455     va_end(vac);
00456   }
00457   va_end(va);
00458   Thread::set_cancel_state(data->old_state);
00459   data->mutex->unlock();
00460 }
00461 
00462 
00463 void
00464 MultiLogger::tlog_debug(struct timeval *t, const char *component, const char *format, ...)
00465 {
00466   data->mutex->lock();
00467   Thread::set_cancel_state(Thread::CANCEL_DISABLED, &(data->old_state));
00468   va_list va;
00469   va_start(va, format);
00470   for (data->logit = data->loggers.begin(); data->logit != data->loggers.end(); ++data->logit) {
00471     va_list vac;
00472     va_copy(vac, va);
00473     (*data->logit)->vlog_debug(component, format, vac);
00474     va_end(vac);
00475   }
00476   va_end(va);
00477   Thread::set_cancel_state(data->old_state);
00478   data->mutex->unlock();
00479 }
00480 
00481 
00482 void
00483 MultiLogger::tlog_info(struct timeval *t, const char *component, const char *format, ...)
00484 {
00485   data->mutex->lock();
00486   Thread::set_cancel_state(Thread::CANCEL_DISABLED, &(data->old_state));
00487 
00488   va_list va;
00489   va_start(va, format);
00490   for (data->logit = data->loggers.begin(); data->logit != data->loggers.end(); ++data->logit) {
00491     va_list vac;
00492     va_copy(vac, va);
00493     (*data->logit)->vtlog_info(t, component, format, vac);
00494     va_end(vac);
00495   }
00496   va_end(va);
00497   Thread::set_cancel_state(data->old_state);
00498   data->mutex->unlock();
00499 }
00500 
00501 
00502 void
00503 MultiLogger::tlog_warn(struct timeval *t, const char *component, const char *format, ...)
00504 {
00505   data->mutex->lock();
00506   Thread::set_cancel_state(Thread::CANCEL_DISABLED, &(data->old_state));
00507 
00508   va_list va;
00509   va_start(va, format);
00510   for (data->logit = data->loggers.begin(); data->logit != data->loggers.end(); ++data->logit) {
00511     va_list vac;
00512     va_copy(vac, va);
00513     (*data->logit)->vtlog_warn(t, component, format, vac);
00514     va_end(vac);
00515   }
00516   va_end(va);
00517   Thread::set_cancel_state(data->old_state);
00518   data->mutex->unlock();
00519 }
00520 
00521 
00522 void
00523 MultiLogger::tlog_error(struct timeval *t, const char *component, const char *format, ...)
00524 {
00525   data->mutex->lock();
00526   Thread::set_cancel_state(Thread::CANCEL_DISABLED, &(data->old_state));
00527 
00528   va_list va;
00529   va_start(va, format);
00530   for (data->logit = data->loggers.begin(); data->logit != data->loggers.end(); ++data->logit) {
00531     va_list vac;
00532     va_copy(vac, va);
00533     (*data->logit)->vtlog_error(t, component, format, vac);
00534     va_end(vac);
00535   }
00536   va_end(va);
00537   Thread::set_cancel_state(data->old_state);
00538   data->mutex->unlock();
00539 }
00540 
00541 
00542 void
00543 MultiLogger::tlog(LogLevel level, struct timeval *t, const char *component, Exception &e)
00544 {
00545   data->mutex->lock();
00546   Thread::set_cancel_state(Thread::CANCEL_DISABLED, &(data->old_state));
00547 
00548   for (data->logit = data->loggers.begin(); data->logit != data->loggers.end(); ++data->logit) {
00549     (*data->logit)->tlog(level, t, component, e);
00550   }
00551   Thread::set_cancel_state(data->old_state);
00552   data->mutex->unlock();
00553 }
00554 
00555 
00556 void
00557 MultiLogger::tlog_debug(struct timeval *t, const char *component, Exception &e)
00558 {
00559   for (data->logit = data->loggers.begin(); data->logit != data->loggers.end(); ++data->logit) {
00560     (*data->logit)->tlog_error(t, component, e);
00561   }
00562 }
00563 
00564 void
00565 MultiLogger::tlog_info(struct timeval *t, const char *component, Exception &e)
00566 {
00567   data->mutex->lock();
00568   Thread::set_cancel_state(Thread::CANCEL_DISABLED, &(data->old_state));
00569 
00570   for (data->logit = data->loggers.begin(); data->logit != data->loggers.end(); ++data->logit) {
00571     (*data->logit)->tlog_error(t, component, e);
00572   }
00573   Thread::set_cancel_state(data->old_state);
00574   data->mutex->unlock();
00575 }
00576 
00577 
00578 void
00579 MultiLogger::tlog_warn(struct timeval *t, const char *component, Exception &e)
00580 {
00581   data->mutex->lock();
00582   Thread::set_cancel_state(Thread::CANCEL_DISABLED, &(data->old_state));
00583 
00584   for (data->logit = data->loggers.begin(); data->logit != data->loggers.end(); ++data->logit) {
00585     (*data->logit)->tlog_error(t, component, e);
00586   }
00587   Thread::set_cancel_state(data->old_state);
00588   data->mutex->unlock();
00589 }
00590 
00591 
00592 void
00593 MultiLogger::tlog_error(struct timeval *t, const char *component, Exception &e)
00594 {
00595   data->mutex->lock();
00596   Thread::set_cancel_state(Thread::CANCEL_DISABLED, &(data->old_state));
00597 
00598   for (data->logit = data->loggers.begin(); data->logit != data->loggers.end(); ++data->logit) {
00599     (*data->logit)->tlog_error(t, component, e);
00600   }
00601   Thread::set_cancel_state(data->old_state);
00602   data->mutex->unlock();
00603 }
00604 
00605 
00606 
00607 
00608 void
00609 MultiLogger::vtlog(LogLevel level, struct timeval *t,
00610                    const char *component, const char *format, va_list va)
00611 {
00612   data->mutex->lock();
00613   Thread::set_cancel_state(Thread::CANCEL_DISABLED, &(data->old_state));
00614 
00615   for (data->logit = data->loggers.begin(); data->logit != data->loggers.end(); ++data->logit) {
00616     va_list vac;
00617     va_copy(vac, va);
00618     (*data->logit)->vtlog(level, t, component, format, vac);
00619     va_end(vac);
00620   }
00621   Thread::set_cancel_state(data->old_state);
00622   data->mutex->unlock();
00623 }
00624 
00625 
00626 void
00627 MultiLogger::vtlog_debug(struct timeval *t, const char *component, const char *format, va_list va)
00628 {
00629   data->mutex->lock();
00630   Thread::set_cancel_state(Thread::CANCEL_DISABLED, &(data->old_state));
00631 
00632   for (data->logit = data->loggers.begin(); data->logit != data->loggers.end(); ++data->logit) {
00633     va_list vac;
00634     va_copy(vac, va);
00635     (*data->logit)->vtlog_debug(t, component, format, vac);
00636     va_end(vac);
00637   }
00638   Thread::set_cancel_state(data->old_state);
00639   data->mutex->unlock();
00640 }
00641 
00642 
00643 void
00644 MultiLogger::vtlog_info(struct timeval *t, const char *component, const char *format, va_list va)
00645 {
00646   data->mutex->lock();
00647   Thread::set_cancel_state(Thread::CANCEL_DISABLED, &(data->old_state));
00648 
00649   for (data->logit = data->loggers.begin(); data->logit != data->loggers.end(); ++data->logit) {
00650     va_list vac;
00651     va_copy(vac, va);
00652     (*data->logit)->vtlog_info(t, component, format, vac);
00653     va_end(vac);
00654   }
00655   Thread::set_cancel_state(data->old_state);
00656   data->mutex->unlock();
00657 }
00658 
00659 
00660 void
00661 MultiLogger::vtlog_warn(struct timeval *t, const char *component, const char *format, va_list va)
00662 {
00663   data->mutex->lock();
00664   Thread::set_cancel_state(Thread::CANCEL_DISABLED, &(data->old_state));
00665 
00666   for (data->logit = data->loggers.begin(); data->logit != data->loggers.end(); ++data->logit) {
00667     va_list vac;
00668     va_copy(vac, va);
00669     (*data->logit)->vtlog_warn(t, component, format, vac);
00670     va_end(vac);
00671   }
00672   Thread::set_cancel_state(data->old_state);
00673   data->mutex->unlock();
00674 }
00675 
00676 
00677 void
00678 MultiLogger::vtlog_error(struct timeval *t, const char *component, const char *format, va_list va)
00679 {
00680   data->mutex->lock();
00681   Thread::set_cancel_state(Thread::CANCEL_DISABLED, &(data->old_state));
00682 
00683   for (data->logit = data->loggers.begin(); data->logit != data->loggers.end(); ++data->logit) {
00684     va_list vac;
00685     va_copy(vac, va);
00686     (*data->logit)->vtlog_error(t, component, format, vac);
00687     va_end(vac);
00688   }
00689   Thread::set_cancel_state(data->old_state);
00690   data->mutex->unlock();
00691 }
00692 
00693 
00694 } // end namespace fawkes