solarpowerlog trunk
/home/tobi/workspace/solarpowerlog/src/interfaces/CTimedWork.cpp
Go to the documentation of this file.
00001 /* ----------------------------------------------------------------------------
00002  solarpowerlog
00003  Copyright (C) 2009  Tobias Frost
00004 
00005  This file is part of solarpowerlog.
00006 
00007  Solarpowerlog is free software; However, it is dual-licenced
00008  as described in the file "COPYING".
00009 
00010  For this file (CTimedWork.cpp), the license terms are:
00011 
00012  You can redistribute it and/or modify it under the terms of the GNU
00013  General Public License as published by the Free Software Foundation; either
00014  version 3 of the License, or (at your option) any later version.
00015 
00016  This program is distributed in the hope that it will be useful, but
00017  WITHOUT ANY WARRANTY; without even the implied warranty of
00018  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00019  Lesser General Public License for more details.
00020 
00021  You should have received a copy of the GNU Library General Public
00022  License along with this proramm; if not, see
00023  <http://www.gnu.org/licenses/>.
00024  ----------------------------------------------------------------------------
00025  */
00026 
00033 #ifdef HAVE_CONFIG_H
00034 #include "config.h"
00035 #endif
00036 
00037 #include <iostream>
00038 #include <list>
00039 #include <time.h>
00040 
00041 #include "CTimedWork.h"
00042 
00043 #include "interfaces/CMutexHelper.h"
00044 
00045 #include <boost/thread.hpp>
00046 #include "boost/date_time/posix_time/posix_time.hpp"
00047 #include "interfaces/CMutexHelper.h"
00048 
00049 CTimedWork::CTimedWork( CWorkScheduler *sch ) : sch(sch), terminate(false)
00050 {
00051 }
00052 
00053 CTimedWork::~CTimedWork()
00054 {
00055      if (!terminate)
00056           RequestTermination();
00057      thread.join();
00058 }
00059 
00060 // Called on execution of the thread.
00061 void CTimedWork::run()
00062 {
00063      thread = boost::thread(boost::bind(&CTimedWork::_main, this));
00064 }
00065 
00066 void CTimedWork::ScheduleWork( ICommand *Command, struct timespec ts )
00067 {
00068      boost::posix_time::ptime n =
00069           boost::posix_time::microsec_clock::local_time();
00070      boost::posix_time::seconds s(ts.tv_sec);
00071      boost::posix_time::millisec ms(ts.tv_nsec / (1000*1000));
00072      n = n + s + ms;
00073      {
00074           CMutexAutoLock lock(&mut);
00075           TimedCommands.insert(
00076                pair<boost::posix_time::ptime, ICommand*> (n, Command));
00077      }
00078 
00079      thread.interrupt();
00080 }
00081 
00082 void CTimedWork::_main()
00083 {
00084      boost::posix_time::ptime n, w;
00085      boost::posix_time::time_duration s;
00086 
00087      while (!terminate) {
00088           // get now
00089           n = boost::posix_time::microsec_clock::local_time();
00090 
00091 #if 0
00092           cerr << "Now: " << n << endl;
00093 #endif
00094 
00095           mut.lock();
00096 
00097 #if 0
00098           cerr << "TIMED WORKS EXPIRATION" << endl;
00099           multimap<boost::posix_time::ptime, ICommand*>::iterator it;
00100           for (it = TimedCommands.begin(); it != TimedCommands.end(); it++) {
00101                cerr << (*it).first << endl;
00102           }
00103           cerr << "TIMED WORKS LIST END" << endl;
00104 #endif
00105 
00106           if (!TimedCommands.empty()) {
00107                w = (TimedCommands.begin())->first;
00108 #if 0
00109                cerr << "Waiting: " << to_simple_string(w) << endl;
00110 #endif
00111                if (w > n) {
00112                     s = w - n;
00113 #if 0
00114                     cerr << "Difference: " << to_simple_string(s)
00115                          << endl;
00116 #endif
00117                } else {
00118                     ICommand *cmd = (TimedCommands.begin())->second;
00119                     TimedCommands.erase(TimedCommands.begin());
00120                     mut.unlock();
00121                     sch->ScheduleWork(cmd);
00122                     continue;
00123                }
00124           } else {
00125                s = boost::posix_time::hours(1);
00126           }
00127 
00128           mut.unlock();
00129 
00130           try {
00131 #if 0
00132                cerr << "sleeping for "
00133                     << boost::posix_time::to_simple_string(s)
00134                     << endl;
00135 #endif
00136                boost::this_thread::sleep(s);
00137           } catch (boost::thread_interrupted e) {
00138 #if 0
00139                cerr << " Sleep interrupted " << endl;
00140 #endif
00141           }
00142      }
00143 }
00144 
00145 void CTimedWork::RequestTermination( void )
00146 {
00147      terminate = true;
00148      thread.interrupt();
00149 }
00150