Module: sems Branch: master Commit: dc8f4ef0b0bb88effb20f7394782cc7ff9cf0f23 URL: http://git.sip-router.org/cgi-bin/gitweb.cgi/sems/?a=commit;h=dc8f4ef0b0bb88effb20f7394782cc7ff9cf0f23
Author: Raphael Coeffic <[email protected]> Committer: Raphael Coeffic <[email protected]> Date: Mon Oct 1 10:52:13 2012 +0200 added generic periodic thread support this class should used each time some task needs to be implemented that executes at regular time interval. --- AmPeriodicThread.cpp | 97 ++++++++++++++++++++++++++++++++++++++++++++++++++ AmPeriodicThread.h | 62 ++++++++++++++++++++++++++++++++ 2 files changed, 159 insertions(+), 0 deletions(-) diff --git a/AmPeriodicThread.cpp b/AmPeriodicThread.cpp new file mode 100644 index 0000000..7289c06 --- /dev/null +++ b/AmPeriodicThread.cpp @@ -0,0 +1,97 @@ +/* + * Copyright (C) 2012 Frafos GmbH + * + * This file is part of SEMS, a free SIP media server. + * + * SEMS is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. This program is released under + * the GPL with the additional exemption that compiling, linking, + * and/or using OpenSSL is allowed. + * + * For a license to use the SEMS software under conditions + * other than those described here, or to purchase support for this + * software, please contact iptel.org by e-mail at the following addresses: + * [email protected] + * + * SEMS is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +/** @file AmPeriodicThread.cpp */ + +#include "AmPeriodicThread.h" +#include <assert.h> + +#include "log.h" + +void AmPeriodicThread::infinite_loop(struct timeval* tick, unsigned int max_ticks_behind, void* usr_data) +{ + struct timeval now,next_tick,diff; + unsigned int ticks_passed; + unsigned long ms_diff, ms_tick; + + assert(tick); + ms_tick = tick->tv_sec * 1000 + tick->tv_usec / 1000; + + gettimeofday(&next_tick,NULL); + + while (true) { + + gettimeofday(&now,NULL); + timeradd(tick,&next_tick,&next_tick); + + if(timercmp(&now,&next_tick,<)){ + + struct timespec sdiff,rem; + timersub(&next_tick,&now,&diff); + + // detect backward clockdrift + ms_diff = diff.tv_sec * 1000 + diff.tv_usec / 1000; + if(ms_diff / ms_tick > 1) { + // at least 2 ticks ahead... + next_tick = now; + sdiff.tv_sec = tick->tv_sec; + sdiff.tv_nsec = tick->tv_usec * 1000; + + WARN("clock drift backwards detected (%ul ticks ahead), resetting sw clock\n", + ms_diff / ms_tick - 1); + } + else { + // everything ok + sdiff.tv_sec = diff.tv_sec; + sdiff.tv_nsec = diff.tv_usec * 1000; + } + + if(sdiff.tv_nsec > 2000000) // 2 ms + nanosleep(&sdiff,&rem); + + ticks_passed = 1; + } + else { + // compute missed ticks + unsigned long ms_diff; + timersub(&now,&next_tick,&diff); + ms_diff = diff.tv_sec * 1000 + diff.tv_usec / 1000; + ticks_passed = ms_diff / ms_tick + 1; + + // missed too many ticks: resync + if(ticks_passed > max_ticks_behind) { + // resync to clock if clock is farther than max_behind_tick in the future + WARN("clock drift detected (missed %d ticks), resetting sw clock\n", + ticks_passed); + next_tick = now; + } + } + + // execute looping step code + if(!looping_step(usr_data)) + break; + } +} diff --git a/AmPeriodicThread.h b/AmPeriodicThread.h new file mode 100644 index 0000000..5a113a8 --- /dev/null +++ b/AmPeriodicThread.h @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2012 Frafos GmbH + * + * This file is part of SEMS, a free SIP media server. + * + * SEMS is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. This program is released under + * the GPL with the additional exemption that compiling, linking, + * and/or using OpenSSL is allowed. + * + * For a license to use the SEMS software under conditions + * other than those described here, or to purchase support for this + * software, please contact iptel.org by e-mail at the following addresses: + * [email protected] + * + * SEMS is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +/** @file AmPeriodicThread.h */ +#ifndef _AmPeriodicThread_h_ +#define _AmPeriodicThread_h_ + +#include "AmThread.h" + +class AmPeriodicThread: public AmThread +{ +protected: + AmPeriodicThread() {} + virtual ~AmPeriodicThread() {} + + /* + * Start the infinite loop. The loop will + * do its best to execute looping_step() at regular + * intervals defined by 'tick'. The time spent in looping_step() + * is subtracted from the 'tick' to calculate the next execution + * time. + * + * @param tick execution time interval. + * @param max_ticks_behind maximum forward clock drift in ticks. + * @param usr_data pointer that will be passed to looping_step(). + */ + void infinite_loop(struct timeval* tick, + unsigned int max_ticks_behind, + void* usr_data); + + /* + * This method is executed periodically by + * infinite loop. + * @return true to continue the loop, false to stop it. + */ + virtual bool looping_step(void* usr_data)=0; +}; + +#endif _______________________________________________ Semsdev mailing list [email protected] http://lists.iptel.org/mailman/listinfo/semsdev
