|
solarpowerlog trunk
|
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