From: g0dil Date: Tue, 27 May 2008 12:59:00 +0000 (+0000) Subject: Console: Implement short-option and non-option parsing X-Git-Url: http://g0dil.de/git?a=commitdiff_plain;h=10985d71f77b627bc4da543d7114feb7c4529329;p=senf.git Console: Implement short-option and non-option parsing Fix lot's of inline implementation ordering errors (make sure, all inline functions are implemented before first use) git-svn-id: https://svn.berlios.de/svnroot/repos/senf/trunk@854 270642c3-0616-0410-b53a-bc976706d245 --- diff --git a/PPI/Connectors.cci b/PPI/Connectors.cci index c61555c..8db9cd9 100644 --- a/PPI/Connectors.cci +++ b/PPI/Connectors.cci @@ -71,12 +71,52 @@ prefix_ void senf::ppi::connector::Connector::setModule(module::Module & module) /////////////////////////////////////////////////////////////////////////// // senf::ppi::connector::PassiveConnector +prefix_ senf::ppi::connector::ActiveConnector & senf::ppi::connector::PassiveConnector::peer() + const +{ + return dynamic_cast(Connector::peer()); +} + prefix_ bool senf::ppi::connector::PassiveConnector::throttled() const { return nativeThrottled_ || remoteThrottled_; } +//////////////////////////////////////// +// private members + +prefix_ void senf::ppi::connector::PassiveConnector::emitThrottle() +{ + peer().notifyThrottle(); +} + +prefix_ void senf::ppi::connector::PassiveConnector::emitUnthrottle() +{ + peer().notifyUnthrottle(); + v_unthrottleEvent(); +} + +prefix_ void senf::ppi::connector::PassiveConnector::notifyThrottle() +{ + if (!throttled()) { + remoteThrottled_ = true; + emitThrottle(); + } + else + remoteThrottled_ = true; +} + +prefix_ void senf::ppi::connector::PassiveConnector::v_unthrottleEvent() +{} + +prefix_ void senf::ppi::connector::PassiveConnector::registerRoute(ForwardingRoute & route) +{ + routes_.push_back(&route); +} + +// public members + prefix_ bool senf::ppi::connector::PassiveConnector::nativeThrottled() const { @@ -101,12 +141,6 @@ prefix_ void senf::ppi::connector::PassiveConnector::unthrottle() } -prefix_ senf::ppi::connector::ActiveConnector & senf::ppi::connector::PassiveConnector::peer() - const -{ - return dynamic_cast(Connector::peer()); -} - //////////////////////////////////////// // protected members @@ -121,38 +155,6 @@ prefix_ void senf::ppi::connector::PassiveConnector::emit() callback_(); } -//////////////////////////////////////// -// private members - -prefix_ void senf::ppi::connector::PassiveConnector::notifyThrottle() -{ - if (!throttled()) { - remoteThrottled_ = true; - emitThrottle(); - } - else - remoteThrottled_ = true; -} - -prefix_ void senf::ppi::connector::PassiveConnector::emitThrottle() -{ - peer().notifyThrottle(); -} - -prefix_ void senf::ppi::connector::PassiveConnector::emitUnthrottle() -{ - peer().notifyUnthrottle(); - v_unthrottleEvent(); -} - -prefix_ void senf::ppi::connector::PassiveConnector::v_unthrottleEvent() -{} - -prefix_ void senf::ppi::connector::PassiveConnector::registerRoute(ForwardingRoute & route) -{ - routes_.push_back(&route); -} - /////////////////////////////////////////////////////////////////////////// // senf::ppi::connector::ActiveConnector @@ -251,6 +253,12 @@ prefix_ void senf::ppi::connector::InputConnector::enqueue(Packet p) /////////////////////////////////////////////////////////////////////////// // senf::ppi::connector::OutputConnector +prefix_ senf::ppi::connector::InputConnector & senf::ppi::connector::OutputConnector::peer() + const +{ + return dynamic_cast(Connector::peer()); +} + prefix_ void senf::ppi::connector::OutputConnector::operator()(Packet p) { peer().enqueue(p); @@ -261,12 +269,6 @@ prefix_ void senf::ppi::connector::OutputConnector::write(Packet p) operator()(p); } -prefix_ senf::ppi::connector::InputConnector & senf::ppi::connector::OutputConnector::peer() - const -{ - return dynamic_cast(Connector::peer()); -} - //////////////////////////////////////// // protected members diff --git a/PPI/DebugModules.cc b/PPI/DebugModules.cc new file mode 100644 index 0000000..409c5ce --- /dev/null +++ b/PPI/DebugModules.cc @@ -0,0 +1,68 @@ +// $Id$ +// +// Copyright (C) 2008 +// Fraunhofer Institute for Open Communication Systems (FOKUS) +// Competence Center NETwork research (NET), St. Augustin, GERMANY +// Stefan Bund +// +// This program 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 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 + \brief DebugModules non-inline non-template implementation */ + +#include "DebugModules.hh" +//#include "DebugModules.ih" + +// Custom includes + +//#include "DebugModules.mpp" +#define prefix_ +///////////////////////////////cc.p//////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////// +// senf::ppi::module::debug::PassiveSource + +prefix_ void senf::ppi::module::debug::PassiveSource::request() +{ + SENF_ASSERT( ! packets_.empty() ); + output(packets_.front()); + packets_.pop_front(); + if (packets_.empty()) + output.throttle(); +} + +/////////////////////////////////////////////////////////////////////////// +// senf::ppi::module::debug::PassiveSink + +prefix_ void senf::ppi::module::debug::PassiveSink::request() +{ + packets_.push_back(input()); +} + +///////////////////////////////cc.e//////////////////////////////////////// +#undef prefix_ +//#include "DebugModules.mpp" + + +// Local Variables: +// mode: c++ +// fill-column: 100 +// comment-column: 40 +// c-file-style: "senf" +// indent-tabs-mode: nil +// ispell-local-dictionary: "american" +// compile-command: "scons -u test" +// End: diff --git a/PPI/DebugModules.cci b/PPI/DebugModules.cci index 975d9bb..09fbda1 100644 --- a/PPI/DebugModules.cci +++ b/PPI/DebugModules.cci @@ -88,15 +88,6 @@ senf::ppi::module::debug::PassiveSource::size() //////////////////////////////////////// // private members -prefix_ void senf::ppi::module::debug::PassiveSource::request() -{ - SENF_ASSERT( ! packets_.empty() ); - output(packets_.front()); - packets_.pop_front(); - if (packets_.empty()) - output.throttle(); -} - prefix_ void senf::ppi::module::debug::PassiveSource::init() { if (empty()) @@ -185,14 +176,6 @@ prefix_ void senf::ppi::module::debug::PassiveSink::clear() packets_.erase(packets_.begin(), packets_.end()); } -//////////////////////////////////////// -// private members - -prefix_ void senf::ppi::module::debug::PassiveSink::request() -{ - packets_.push_back(input()); -} - /////////////////////////////////////////////////////////////////////////// // senf::ppi::module::debug::ActiveFeederSource diff --git a/PPI/Module.cci b/PPI/Module.cci index 26045ba..35df877 100644 --- a/PPI/Module.cci +++ b/PPI/Module.cci @@ -35,6 +35,40 @@ /////////////////////////////////////////////////////////////////////////// // senf::ppi::module::Module +//////////////////////////////////////// +// private members + +prefix_ void senf::ppi::module::Module::init() +{} + +prefix_ senf::ppi::EventManager & senf::ppi::module::Module::eventManager() + const +{ + return EventManager::instance(); +} + +prefix_ senf::ppi::ModuleManager & senf::ppi::module::Module::moduleManager() + const +{ + return ModuleManager::instance(); +} + +prefix_ void senf::ppi::module::Module::registerConnector(connector::Connector & connector) +{ + connectorRegistry_.push_back(&connector); + connector.setModule(*this); +} + +prefix_ senf::ppi::RouteBase & +senf::ppi::module::Module::addRoute(std::auto_ptr route) +{ + routes_.push_back(route.release()); + return routes_.back(); +} + +//////////////////////////////////////// +// public members + prefix_ senf::ppi::module::Module::~Module() { moduleManager().unregisterModule(*this); @@ -71,37 +105,6 @@ prefix_ void senf::ppi::module::Module::destroy() eventManager().destroyModule(*this); } -//////////////////////////////////////// -// private members - -prefix_ void senf::ppi::module::Module::init() -{} - -prefix_ senf::ppi::EventManager & senf::ppi::module::Module::eventManager() - const -{ - return EventManager::instance(); -} - -prefix_ senf::ppi::ModuleManager & senf::ppi::module::Module::moduleManager() - const -{ - return ModuleManager::instance(); -} - -prefix_ void senf::ppi::module::Module::registerConnector(connector::Connector & connector) -{ - connectorRegistry_.push_back(&connector); - connector.setModule(*this); -} - -prefix_ senf::ppi::RouteBase & -senf::ppi::module::Module::addRoute(std::auto_ptr route) -{ - routes_.push_back(route.release()); - return routes_.back(); -} - ///////////////////////////////cci.e/////////////////////////////////////// #undef prefix_ diff --git a/Packets/Packet.cci b/Packets/Packet.cci index 813ab10..f02dabd 100644 --- a/Packets/Packet.cci +++ b/Packets/Packet.cci @@ -32,11 +32,26 @@ /////////////////////////////////////////////////////////////////////////// // senf::Packet +// protected members + +prefix_ senf::Packet::Packet(PacketInterpreterBase::ptr packet) + : packet_(packet) +{} + +prefix_ senf::PacketInterpreterBase::ptr senf::Packet::ptr() + const +{ + SENF_ASSERT(packet_); + return packet_; +} + // public structors prefix_ senf::Packet::Packet() {} +// public members + prefix_ senf::Packet senf::Packet::clone() const { @@ -45,6 +60,13 @@ prefix_ senf::Packet senf::Packet::clone() // Interpreter chain access +prefix_ senf::Packet senf::Packet::next(NoThrow_t) + const +{ + PacketInterpreterBase::ptr p (ptr()->next()); + return !p && ptr()->nextPacketRange() ? checkNext() : Packet(p); +} + prefix_ senf::Packet senf::Packet::next() const { @@ -53,11 +75,10 @@ prefix_ senf::Packet senf::Packet::next() return p; } -prefix_ senf::Packet senf::Packet::next(NoThrow_t) +prefix_ senf::Packet senf::Packet::prev(NoThrow_t) const { - PacketInterpreterBase::ptr p (ptr()->next()); - return !p && ptr()->nextPacketRange() ? checkNext() : Packet(p); + return Packet(ptr()->prev()); } prefix_ senf::Packet senf::Packet::prev() @@ -68,12 +89,6 @@ prefix_ senf::Packet senf::Packet::prev() return p; } -prefix_ senf::Packet senf::Packet::prev(NoThrow_t) - const -{ - return Packet(ptr()->prev()); -} - prefix_ senf::Packet senf::Packet::first() const { @@ -154,19 +169,6 @@ prefix_ bool senf::Packet::boolean_test() return packet_ && packet_->valid(); } -// protected members - -prefix_ senf::Packet::Packet(PacketInterpreterBase::ptr packet) - : packet_(packet) -{} - -prefix_ senf::PacketInterpreterBase::ptr senf::Packet::ptr() - const -{ - SENF_ASSERT(packet_); - return packet_; -} - ///////////////////////////////cci.e/////////////////////////////////////// #undef prefix_ diff --git a/Packets/PacketData.cci b/Packets/PacketData.cci index 28ae24c..9ea4cef 100644 --- a/Packets/PacketData.cci +++ b/Packets/PacketData.cci @@ -27,7 +27,7 @@ #include "../Utils/senfassert.hh" #include #include "PacketImpl.hh" -#include "PacketParser.hh" +// #include "PacketParser.hh" #define prefix_ inline ///////////////////////////////cci.p/////////////////////////////////////// @@ -35,6 +35,13 @@ /////////////////////////////////////////////////////////////////////////// // senf::PacketData +prefix_ senf::detail::PacketImpl & senf::PacketData::impl() + const +{ + SENF_ASSERT( impl_ ); + return *impl_; +} + prefix_ senf::PacketData::iterator senf::PacketData::begin() const { @@ -112,111 +119,6 @@ prefix_ senf::PacketData::PacketData(size_type b, size_type e) : impl_(), begin_(b), end_(e) {} -prefix_ senf::detail::PacketImpl & senf::PacketData::impl() - const -{ - SENF_ASSERT( impl_ ); - return *impl_; -} - -/////////////////////////////////////////////////////////////////////////// -// senf::safe_data_iterator - -prefix_ senf::safe_data_iterator::safe_data_iterator() - : data_(0), i_(0) -{} - -prefix_ senf::safe_data_iterator::safe_data_iterator(PacketData & data) - : data_(&data), i_(0) -{} - -prefix_ senf::safe_data_iterator::safe_data_iterator(PacketData & data, PacketData::iterator i) - : data_(&data), i_(std::distance(data.begin(),i)) -{} - -prefix_ senf::safe_data_iterator::safe_data_iterator(PacketParserBase const & parser) - : data_(&parser.data()), i_(std::distance(data_->begin(),parser.i())) -{} - -prefix_ senf::safe_data_iterator & senf::safe_data_iterator::operator=(PacketData::iterator i) -{ - SENF_ASSERT(data_); - i_ = std::distance(data_->begin(),i); - return *this; -} - -prefix_ senf::safe_data_iterator & -senf::safe_data_iterator::operator=(PacketParserBase const & parser) -{ - data_ = &parser.data(); - i_ = std::distance(data_->begin(),parser.i()); - return *this; -} - -prefix_ senf::safe_data_iterator::operator senf::PacketData::iterator() - const -{ - return i(); -} - -prefix_ bool senf::safe_data_iterator::boolean_test() - const -{ - return data_; -} - -prefix_ senf::PacketData & senf::safe_data_iterator::data() - const -{ - SENF_ASSERT(data_); - return *data_; -} - -prefix_ senf::safe_data_iterator::value_type & senf::safe_data_iterator::dereference() - const -{ - return *i(); -} - -prefix_ bool senf::safe_data_iterator::equal(safe_data_iterator const & other) - const -{ - SENF_ASSERT(data_ == other.data_); - return i_ == other.i_; -} - -prefix_ senf::safe_data_iterator::difference_type -senf::safe_data_iterator::distance_to(safe_data_iterator const & other) - const -{ - SENF_ASSERT(data_ == other.data_); - return other.i_ - i_; -} - -prefix_ void senf::safe_data_iterator::increment() -{ - ++i_; -} - -prefix_ void senf::safe_data_iterator::decrement() -{ - SENF_ASSERT(i_>0); - --i_; -} - -prefix_ void senf::safe_data_iterator::advance(difference_type n) -{ - SENF_ASSERT( -n < difference_type(i_) ); - i_ += n; -} - -prefix_ senf::PacketData::iterator senf::safe_data_iterator::i() - const -{ - SENF_ASSERT(data_); - return boost::next(data_->begin(),i_); -} - ///////////////////////////////cci.e/////////////////////////////////////// #undef prefix_ diff --git a/Packets/PacketData.hh b/Packets/PacketData.hh index 96db5b1..d63e01a 100644 --- a/Packets/PacketData.hh +++ b/Packets/PacketData.hh @@ -29,7 +29,6 @@ // Custom includes #include #include -#include #include "../Utils/safe_bool.hh" #include "../Utils/Exception.hh" #include "PacketTypes.hh" @@ -163,67 +162,6 @@ namespace senf { struct TruncatedPacketException : public senf::Exception { TruncatedPacketException() : senf::Exception("truncated packet"){} }; - /** \brief Re-validating data iterator - - This class is a wrapper around a PacketData::iterator instance. It will revalidate the - iterator on every access. This keeps the iterator valid even when the data container is - resized and thereby possibly relocated. The iterator will always point to the byte at the - same offset from the packets beginning. If data is inserted before this iterators position, - the data pointed to will of course change. - - For this to work, the safe_data_iterator must be initialized with the container to which the - iterator belongs. After this initialization it can be used like any other iterator. - */ - class safe_data_iterator - : public boost::iterator_facade< safe_data_iterator, - PacketData::value_type, - boost::random_access_traversal_tag >, - public comparable_safe_bool - { - public: - typedef PacketData::size_type size_type; - - safe_data_iterator(); ///< Make uninitialized iterator - explicit safe_data_iterator(PacketData & data); - ///< Construct iterator only setting the data container - safe_data_iterator(PacketData & data, PacketData::iterator i); - ///< Initialize iterator to given position - explicit safe_data_iterator(PacketParserBase const & parser); - ///< Initialize iterator from parser - /**< The iterator will point to the parsers start - position. */ - - safe_data_iterator & operator=(PacketData::iterator i); ///< Assign iterator - /**< The iteator \a i must be from the container wo which \c - this iterator has been initialized. */ - safe_data_iterator & operator=(PacketParserBase const & parser); - ///< Assign iterator from parser - /**< The iterator will point to the parser start - position. */ - - operator PacketData::iterator() const; ///< Convert to iterator - - bool boolean_test() const; ///< Check, if iterator is initialized - - PacketData & data() const; ///< Access data container - - private: - friend class boost::iterator_core_access; - - // iterator_facade interface - - value_type & dereference() const; - bool equal(safe_data_iterator const & other) const; - difference_type distance_to(safe_data_iterator const & other) const; - void increment(); - void decrement(); - void advance(difference_type n); - - PacketData::iterator i() const; - - PacketData * data_; - size_type i_; - }; } ///////////////////////////////hh.e//////////////////////////////////////// diff --git a/Packets/PacketImpl.cc b/Packets/PacketImpl.cc index 92e0e22..2bd41be 100644 --- a/Packets/PacketImpl.cc +++ b/Packets/PacketImpl.cc @@ -36,6 +36,21 @@ /////////////////////////////////////////////////////////////////////////// // senf::detail::PacketImpl +// This function has a problem being inlined. Somehow, often when calling this, the size of the +// resulting inlined code would be huge. Need to further debug this. + +prefix_ void senf::detail::PacketImpl::release(refcount_t n) +{ + SENF_ASSERT(refcount_ >= n); + // uah ... we need to be extremely careful here. If refcount_ is n, we want to commit suicide, + // however the destructor will remove all PacketInterpreters from the list and will thereby + // decrement refcount -> only decrenebt refcount_ when *not* caling delete + if (refcount_ == n) + delete this; + else + refcount_ -= n; +} + // interpreter chain prefix_ void senf::detail::PacketImpl::appendInterpreter(PacketInterpreterBase * p) diff --git a/Packets/PacketImpl.cci b/Packets/PacketImpl.cci index a6106ae..40489bf 100644 --- a/Packets/PacketImpl.cci +++ b/Packets/PacketImpl.cci @@ -25,7 +25,7 @@ // Custom includes #include "../Utils/senfassert.hh" -#include "PacketInterpreter.hh" +// #include "PacketInterpreter.hh" #define prefix_ inline ///////////////////////////////cci.p/////////////////////////////////////// @@ -78,18 +78,6 @@ prefix_ void senf::detail::PacketImpl::add_ref(refcount_t n) refcount_ += n; } -prefix_ void senf::detail::PacketImpl::release(refcount_t n) -{ - SENF_ASSERT(refcount_ >= n); - // uah ... we need to be extremely careful here. If refcount_ is n, we want to commit suicide, - // however the destructor will remove all PacketInterpreters from the list and will thereby - // decrement refcount -> only decrenebt refcount_ when *not* caling delete - if (refcount_ == n) - delete this; - else - refcount_ -= n; -} - prefix_ senf::detail::PacketImpl::refcount_t senf::detail::PacketImpl::refcount() const { diff --git a/Packets/PacketParser.cci b/Packets/PacketParser.cci index 4978b4b..510c2a6 100644 --- a/Packets/PacketParser.cci +++ b/Packets/PacketParser.cci @@ -33,51 +33,37 @@ /////////////////////////////////////////////////////////////////////////// // senf::PacketParserBase +// public members + prefix_ senf::PacketParserBase::data_iterator senf::PacketParserBase::i() const { return i_; } -prefix_ senf::PacketParserBase::data_iterator senf::PacketParserBase::i(size_type offset) - const -{ - validate(offset); - return boost::next(i_, offset); -} +// private members -prefix_ senf::PacketParserBase::state_type senf::PacketParserBase::state() +prefix_ senf::PacketParserBase::data_iterator senf::PacketParserBase::end() const { - return data_; + return data_->end(); } -prefix_ senf::PacketData & senf::PacketParserBase::data() +// protected members + +prefix_ bool senf::PacketParserBase::check(size_type size) const { - return * data_; + return size <= size_type(std::distance(i(),end())); } -prefix_ void senf::PacketParserBase::init() - const -{} - -prefix_ void senf::PacketParserBase::defaultInit() - const -{} - -prefix_ senf::Packet senf::PacketParserBase::packet() - const +prefix_ void senf::PacketParserBase::validate(size_type size) + const { - // OUCH ... I hate this but for some awkward packet types, access to the packet - // from the parser is really needed (e.g. UDP when building the pseudo-header - // for calculating the checksum). - return Packet(PacketInterpreterBase::ptr(static_cast(&data()))); + if (! check(size)) + throw TruncatedPacketException(); } -//////////////////////////////////////// -// protected members - prefix_ senf::PacketParserBase::PacketParserBase(data_iterator i, state_type s) : i_ (i), data_ (s) {} @@ -89,26 +75,42 @@ prefix_ senf::PacketParserBase::PacketParserBase(data_iterator i, state_type s, validate(size); } -prefix_ bool senf::PacketParserBase::check(size_type size) +// public members + +prefix_ senf::PacketParserBase::data_iterator senf::PacketParserBase::i(size_type offset) const { - return size <= size_type(std::distance(i(),end())); + validate(offset); + return boost::next(i_, offset); } -prefix_ void senf::PacketParserBase::validate(size_type size) +prefix_ senf::PacketParserBase::state_type senf::PacketParserBase::state() const { - if (! check(size)) - throw TruncatedPacketException(); + return data_; } -//////////////////////////////////////// -// private members +prefix_ senf::PacketData & senf::PacketParserBase::data() + const +{ + return * data_; +} -prefix_ senf::PacketParserBase::data_iterator senf::PacketParserBase::end() +prefix_ void senf::PacketParserBase::init() + const +{} + +prefix_ void senf::PacketParserBase::defaultInit() + const +{} + +prefix_ senf::Packet senf::PacketParserBase::packet() const { - return data_->end(); + // OUCH ... I hate this but for some awkward packet types, access to the packet + // from the parser is really needed (e.g. UDP when building the pseudo-header + // for calculating the checksum). + return Packet(PacketInterpreterBase::ptr(static_cast(&data()))); } ///////////////////////////////cci.e/////////////////////////////////////// diff --git a/Packets/PacketParser.ct b/Packets/PacketParser.ct index ceb0d5c..f025d54 100644 --- a/Packets/PacketParser.ct +++ b/Packets/PacketParser.ct @@ -54,6 +54,14 @@ prefix_ Parser senf::operator<<(Parser target, Parser source) {} #endif +// Why is this function reported as not inlineable ? + +template +prefix_ senf::PacketParserBase::size_type senf::detail::packetParserSize(Parser p, ...) +{ + return p.bytes(); +} + ///////////////////////////////ct.e//////////////////////////////////////// #undef prefix_ diff --git a/Packets/PacketParser.cti b/Packets/PacketParser.cti index 7872f83..9cb4968 100644 --- a/Packets/PacketParser.cti +++ b/Packets/PacketParser.cti @@ -99,58 +99,6 @@ senf::detail::packetParserSize(Parser p, int, senf::mpl::take_uint -prefix_ senf::PacketParserBase::size_type senf::detail::packetParserSize(Parser p, ...) -{ - return p.bytes(); -} - -/////////////////////////////////////////////////////////////////////////// -// senf::SafePacketParserWrapper - -template -prefix_ senf::SafePacketParserWrapper::SafePacketParserWrapper() - : parser_(), i_() -{} - -template -prefix_ senf::SafePacketParserWrapper::SafePacketParserWrapper(Parser parser) - : parser_(parser), i_(parser) -{} - -template -prefix_ senf::SafePacketParserWrapper & senf::SafePacketParserWrapper::operator=(Parser parser) -{ - parser_ = parser; - i_ = parser; - return *this; -} - -template -prefix_ Parser senf::SafePacketParserWrapper::operator*() - const -{ - SENF_ASSERT( i_ ); - parser_->i_ = PacketParserBase::data_iterator(i_); - return *parser_; -} - -template -prefix_ Parser const * senf::SafePacketParserWrapper::operator->() - const -{ - SENF_ASSERT( i_ ); - parser_->i_ = PacketParserBase::data_iterator(i_); - return & (*parser_); -} - -template -prefix_ bool senf::SafePacketParserWrapper::boolean_test() - const -{ - return i_; -} - ///////////////////////////////cti.e/////////////////////////////////////// #undef prefix_ diff --git a/Packets/PacketParser.hh b/Packets/PacketParser.hh index 3e56843..c85ff2f 100644 --- a/Packets/PacketParser.hh +++ b/Packets/PacketParser.hh @@ -465,63 +465,6 @@ namespace senf { SENF_PARSER_FINALIZE(VoidPacketParser); }; - /** \brief Iterator re-validating Parser wrapper - - An ordinary parser will be invalidated whenever the raw data container's size is - changed. This can complicate some algorithms considerably. - - This wrapper will update the parsers iterator (the value returned by the i() member) on - every access. This ensures that the iterator will stay valid. - - \attention Beware however, if you insert or remove data before the safe wrapper, the - location will \e not be updated accordingly and therefore the parser will be - invalid. - - Additionally a SafePacketParserWrapper has an uninitialized state. The only allowed operations in - this state are the boolean test for validity and assigning another parser. - - \ingroup packetparser - */ - template - class SafePacketParserWrapper - : public safe_bool< SafePacketParserWrapper > - { - public: - /////////////////////////////////////////////////////////////////////////// - // Types - - /////////////////////////////////////////////////////////////////////////// - ///\name Structors and default members - ///@{ - - // default copy constructor - // default copy assignment - // default destructor - SafePacketParserWrapper(); ///< Create an empty uninitialized SafePacketParserWrapper - - // conversion constructors - SafePacketParserWrapper(Parser parser); ///< Initialize SafePacketParserWrapper from \a parser - - SafePacketParserWrapper & operator=(Parser parser); ///< Assign \a parser to \c this - - ///@} - /////////////////////////////////////////////////////////////////////////// - - Parser operator*() const; ///< Access the stored parser - /**< On every access, the stored parsers iterator will be - updated / re-validated. */ - Parser const * operator->() const; ///< Access the stored parser - /**< On every access, the stored parsers iterator will be - updated / re-validated. */ - bool boolean_test() const; ///< Check validity - - protected: - - private: - mutable boost::optional parser_; - senf::safe_data_iterator i_; - }; - } ///////////////////////////////hh.e//////////////////////////////////////// diff --git a/Packets/PacketParser.test.cc b/Packets/PacketParser.test.cc index b583381..3e53f00 100644 --- a/Packets/PacketParser.test.cc +++ b/Packets/PacketParser.test.cc @@ -91,27 +91,6 @@ BOOST_AUTO_UNIT_TEST(packetParserBase) BOOST_CHECK_EQUAL( senf::init_bytes::value, 6u ); } -BOOST_AUTO_UNIT_TEST(safePacketParser) -{ - senf::PacketInterpreter::ptr pi (senf::PacketInterpreter::create(6u)); - senf::SafePacketParserWrapper p; - - BOOST_CHECK( !p ); - - p = senf::UInt16Parser(pi->data().begin(),&pi->data()); - - BOOST_CHECK( p ); - (*p) = 0x1234u; - - BOOST_CHECK_EQUAL( (*p), 0x1234u ); - BOOST_CHECK_EQUAL( p->data()[0], 0x12u ); - - p->data().resize(1024u); - BOOST_CHECK_EQUAL( (*p), 0x1234u ); - (*p) = 0x2345u; - BOOST_CHECK_EQUAL( p->data()[0], 0x23u ); -} - ///////////////////////////////cc.e//////////////////////////////////////// #undef prefix_ diff --git a/Packets/SConscript b/Packets/SConscript index 4500875..10c6a89 100644 --- a/Packets/SConscript +++ b/Packets/SConscript @@ -5,8 +5,8 @@ import SENFSCons, glob ########################################################################### -SENFSCons.AllIncludesHH(env, [ f for f in glob.glob("*.hh") - if 'defined(HH_Packets__decls_)' in file(f).read() ]) +#SENFSCons.AllIncludesHH(env, [ f for f in glob.glob("*.hh") +# if 'defined(HH_Packets__decls_)' in file(f).read() ]) SENFSCons.StandardTargets(env) SENFSCons.Lib(env, diff --git a/Packets/SafeIterator.cci b/Packets/SafeIterator.cci new file mode 100644 index 0000000..dbd1264 --- /dev/null +++ b/Packets/SafeIterator.cci @@ -0,0 +1,143 @@ +// $Id$ +// +// Copyright (C) 2008 +// Fraunhofer Institute for Open Communication Systems (FOKUS) +// Competence Center NETwork research (NET), St. Augustin, GERMANY +// Stefan Bund +// +// This program 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 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 + \brief SafeIterator inline non-template implementation */ + +//#include "SafeIterator.ih" + +// Custom includes + +#define prefix_ inline +///////////////////////////////cci.p/////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////// +// senf::safe_data_iterator + +prefix_ senf::safe_data_iterator::safe_data_iterator() + : data_(0), i_(0) +{} + +prefix_ senf::safe_data_iterator::safe_data_iterator(PacketData & data) + : data_(&data), i_(0) +{} + +prefix_ senf::safe_data_iterator::safe_data_iterator(PacketData & data, PacketData::iterator i) + : data_(&data), i_(std::distance(data.begin(),i)) +{} + +prefix_ senf::safe_data_iterator::safe_data_iterator(PacketParserBase const & parser) + : data_(&parser.data()), i_(std::distance(data_->begin(),parser.i())) +{} + +prefix_ senf::PacketData::iterator senf::safe_data_iterator::i() + const +{ + SENF_ASSERT(data_); + return boost::next(data_->begin(),i_); +} + +prefix_ senf::safe_data_iterator & senf::safe_data_iterator::operator=(PacketData::iterator i) +{ + SENF_ASSERT(data_); + i_ = std::distance(data_->begin(),i); + return *this; +} + +prefix_ senf::safe_data_iterator & +senf::safe_data_iterator::operator=(PacketParserBase const & parser) +{ + data_ = &parser.data(); + i_ = std::distance(data_->begin(),parser.i()); + return *this; +} + +prefix_ senf::safe_data_iterator::operator senf::PacketData::iterator() + const +{ + return i(); +} + +prefix_ bool senf::safe_data_iterator::boolean_test() + const +{ + return data_; +} + +prefix_ senf::PacketData & senf::safe_data_iterator::data() + const +{ + SENF_ASSERT(data_); + return *data_; +} + +prefix_ senf::safe_data_iterator::value_type & senf::safe_data_iterator::dereference() + const +{ + return *i(); +} + +prefix_ bool senf::safe_data_iterator::equal(safe_data_iterator const & other) + const +{ + SENF_ASSERT(data_ == other.data_); + return i_ == other.i_; +} + +prefix_ senf::safe_data_iterator::difference_type +senf::safe_data_iterator::distance_to(safe_data_iterator const & other) + const +{ + SENF_ASSERT(data_ == other.data_); + return other.i_ - i_; +} + +prefix_ void senf::safe_data_iterator::increment() +{ + ++i_; +} + +prefix_ void senf::safe_data_iterator::decrement() +{ + SENF_ASSERT(i_>0); + --i_; +} + +prefix_ void senf::safe_data_iterator::advance(difference_type n) +{ + SENF_ASSERT( -n < difference_type(i_) ); + i_ += n; +} + +///////////////////////////////cci.e/////////////////////////////////////// +#undef prefix_ + + +// Local Variables: +// mode: c++ +// fill-column: 100 +// comment-column: 40 +// c-file-style: "senf" +// indent-tabs-mode: nil +// ispell-local-dictionary: "american" +// compile-command: "scons -u test" +// End: diff --git a/Packets/SafeIterator.cti b/Packets/SafeIterator.cti new file mode 100644 index 0000000..f845b78 --- /dev/null +++ b/Packets/SafeIterator.cti @@ -0,0 +1,91 @@ +// $Id$ +// +// Copyright (C) 2008 +// Fraunhofer Institute for Open Communication Systems (FOKUS) +// Competence Center NETwork research (NET), St. Augustin, GERMANY +// Stefan Bund +// +// This program 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 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 + \brief SafeIterator inline template implementation */ + +//#include "SafeIterator.ih" + +// Custom includes + +#define prefix_ inline +///////////////////////////////cti.p/////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////// +// senf::SafePacketParserWrapper + +template +prefix_ senf::SafePacketParserWrapper::SafePacketParserWrapper() + : parser_(), i_() +{} + +template +prefix_ senf::SafePacketParserWrapper::SafePacketParserWrapper(Parser parser) + : parser_(parser), i_(parser) +{} + +template +prefix_ senf::SafePacketParserWrapper & senf::SafePacketParserWrapper::operator=(Parser parser) +{ + parser_ = parser; + i_ = parser; + return *this; +} + +template +prefix_ Parser senf::SafePacketParserWrapper::operator*() + const +{ + SENF_ASSERT( i_ ); + parser_->i_ = PacketParserBase::data_iterator(i_); + return *parser_; +} + +template +prefix_ Parser const * senf::SafePacketParserWrapper::operator->() + const +{ + SENF_ASSERT( i_ ); + parser_->i_ = PacketParserBase::data_iterator(i_); + return & (*parser_); +} + +template +prefix_ bool senf::SafePacketParserWrapper::boolean_test() + const +{ + return i_; +} + +///////////////////////////////cti.e/////////////////////////////////////// +#undef prefix_ + + +// Local Variables: +// mode: c++ +// fill-column: 100 +// comment-column: 40 +// c-file-style: "senf" +// indent-tabs-mode: nil +// ispell-local-dictionary: "american" +// compile-command: "scons -u test" +// End: diff --git a/Packets/SafeIterator.hh b/Packets/SafeIterator.hh new file mode 100644 index 0000000..44982a7 --- /dev/null +++ b/Packets/SafeIterator.hh @@ -0,0 +1,180 @@ +// $Id$ +// +// Copyright (C) 2008 +// Fraunhofer Institute for Open Communication Systems (FOKUS) +// Competence Center NETwork research (NET), St. Augustin, GERMANY +// Stefan Bund +// +// This program 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 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 + \brief SafeIterator public header */ + +#ifndef HH_SafeIterator_ +#define HH_SafeIterator_ 1 + +#ifndef HH_Packets_ +#error "Don't include 'SafeIterator.hh' directly, include 'Packets.hh'" +#endif + +// Custom includes +#include + +//#include "SafeIterator.mpp" +///////////////////////////////hh.p//////////////////////////////////////// + +namespace senf { + + /** \brief Re-validating data iterator + + This class is a wrapper around a PacketData::iterator instance. It will revalidate the + iterator on every access. This keeps the iterator valid even when the data container is + resized and thereby possibly relocated. The iterator will always point to the byte at the + same offset from the packets beginning. If data is inserted before this iterators position, + the data pointed to will of course change. + + For this to work, the safe_data_iterator must be initialized with the container to which the + iterator belongs. After this initialization it can be used like any other iterator. + */ + class safe_data_iterator + : public boost::iterator_facade< safe_data_iterator, + PacketData::value_type, + boost::random_access_traversal_tag >, + public comparable_safe_bool + { + public: + typedef PacketData::size_type size_type; + + safe_data_iterator(); ///< Make uninitialized iterator + explicit safe_data_iterator(PacketData & data); + ///< Construct iterator only setting the data container + safe_data_iterator(PacketData & data, PacketData::iterator i); + ///< Initialize iterator to given position + explicit safe_data_iterator(PacketParserBase const & parser); + ///< Initialize iterator from parser + /**< The iterator will point to the parsers start + position. */ + + safe_data_iterator & operator=(PacketData::iterator i); ///< Assign iterator + /**< The iteator \a i must be from the container wo which \c + this iterator has been initialized. */ + safe_data_iterator & operator=(PacketParserBase const & parser); + ///< Assign iterator from parser + /**< The iterator will point to the parser start + position. */ + + operator PacketData::iterator() const; ///< Convert to iterator + + bool boolean_test() const; ///< Check, if iterator is initialized + + PacketData & data() const; ///< Access data container + + private: + friend class boost::iterator_core_access; + + // iterator_facade interface + + value_type & dereference() const; + bool equal(safe_data_iterator const & other) const; + difference_type distance_to(safe_data_iterator const & other) const; + void increment(); + void decrement(); + void advance(difference_type n); + + PacketData::iterator i() const; + + PacketData * data_; + size_type i_; + }; + + /** \brief Iterator re-validating Parser wrapper + + An ordinary parser will be invalidated whenever the raw data container's size is + changed. This can complicate some algorithms considerably. + + This wrapper will update the parsers iterator (the value returned by the i() member) on + every access. This ensures that the iterator will stay valid. + + \attention Beware however, if you insert or remove data before the safe wrapper, the + location will \e not be updated accordingly and therefore the parser will be + invalid. + + Additionally a SafePacketParserWrapper has an uninitialized state. The only allowed operations in + this state are the boolean test for validity and assigning another parser. + + \ingroup packetparser + */ + template + class SafePacketParserWrapper + : public safe_bool< SafePacketParserWrapper > + { + public: + /////////////////////////////////////////////////////////////////////////// + // Types + + /////////////////////////////////////////////////////////////////////////// + ///\name Structors and default members + ///@{ + + // default copy constructor + // default copy assignment + // default destructor + SafePacketParserWrapper(); ///< Create an empty uninitialized SafePacketParserWrapper + + // conversion constructors + SafePacketParserWrapper(Parser parser); ///< Initialize SafePacketParserWrapper from \a parser + + SafePacketParserWrapper & operator=(Parser parser); ///< Assign \a parser to \c this + + ///@} + /////////////////////////////////////////////////////////////////////////// + + Parser operator*() const; ///< Access the stored parser + /**< On every access, the stored parsers iterator will be + updated / re-validated. */ + Parser const * operator->() const; ///< Access the stored parser + /**< On every access, the stored parsers iterator will be + updated / re-validated. */ + bool boolean_test() const; ///< Check validity + + protected: + + private: + mutable boost::optional parser_; + senf::safe_data_iterator i_; + }; + +} + +///////////////////////////////hh.e//////////////////////////////////////// +#endif +#if !defined(HH_Packets__decls_) && !defined(HH_SafeIterator_i_) +#define HH_SafeIterator_i_ +#include "SafeIterator.cci" +//#include "SafeIterator.ct" +#include "SafeIterator.cti" +#endif + + +// Local Variables: +// mode: c++ +// fill-column: 100 +// comment-column: 40 +// c-file-style: "senf" +// indent-tabs-mode: nil +// ispell-local-dictionary: "american" +// compile-command: "scons -u test" +// End: diff --git a/Packets/SafeIterator.test.cc b/Packets/SafeIterator.test.cc new file mode 100644 index 0000000..182dc93 --- /dev/null +++ b/Packets/SafeIterator.test.cc @@ -0,0 +1,75 @@ +// $Id$ +// +// Copyright (C) 2008 +// Fraunhofer Institute for Open Communication Systems (FOKUS) +// Competence Center NETwork research (NET), St. Augustin, GERMANY +// Stefan Bund +// +// This program 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 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 + \brief SafeIterator.test unit tests */ + +//#include "SafeIterator.test.hh" +//#include "SafeIterator.test.ih" + +// Custom includes +#include "Packets.hh" + +#include +#include + +#define prefix_ +///////////////////////////////cc.p//////////////////////////////////////// + +namespace { + struct VoidPacket : public senf::PacketTypeBase {}; +} + +BOOST_AUTO_UNIT_TEST(safePacketParser) +{ + senf::PacketInterpreter::ptr pi (senf::PacketInterpreter::create(6u)); + senf::SafePacketParserWrapper p; + + BOOST_CHECK( !p ); + + p = senf::UInt16Parser(pi->data().begin(),&pi->data()); + + BOOST_CHECK( p ); + (*p) = 0x1234u; + + BOOST_CHECK_EQUAL( (*p), 0x1234u ); + BOOST_CHECK_EQUAL( p->data()[0], 0x12u ); + + p->data().resize(1024u); + BOOST_CHECK_EQUAL( (*p), 0x1234u ); + (*p) = 0x2345u; + BOOST_CHECK_EQUAL( p->data()[0], 0x23u ); +} + +///////////////////////////////cc.e//////////////////////////////////////// +#undef prefix_ + + +// Local Variables: +// mode: c++ +// fill-column: 100 +// comment-column: 40 +// c-file-style: "senf" +// indent-tabs-mode: nil +// ispell-local-dictionary: "american" +// compile-command: "scons -u test" +// End: diff --git a/SConstruct b/SConstruct index 19eadb3..0e0f4d7 100644 --- a/SConstruct +++ b/SConstruct @@ -140,8 +140,20 @@ if not logname: def configFilesOpts(target, source, env, for_signature): return [ '-I%s' % os.path.split(f)[1] for f in env['LOCAL_CONFIG_FILES'] ] +# Options used to debug inlining: +# +# INLINE_OPTS = [ '-finline-limit=20000', '--param','large-function-growth=10000', +# '--param', 'large-function-insns=10000', '--param','inline-unit-growth=10000', +# '-fvisibility-inlines-hidden', '-fno-inline-functions', '-Winline' ] +# +# BEWARE: You need lots of ram to compile with these settings (approx 1G) +# + +INLINE_OPTS = [ '-finline-limit=5000' ] + env.Append( CPPPATH = [ '#/include' ], + CXXFLAGS = [ '-Wall', '-Woverloaded-virtual', '-Wno-long-long' ] + INLINE_OPTS, LIBS = [ 'readline', 'rt', '$BOOSTREGEXLIB', '$BOOSTIOSTREAMSLIB' ], TEST_EXTRA_LIBS = [ '$BOOSTFSLIB' ], DOXY_XREF_TYPES = [ 'bug', 'fixme', 'todo', 'idea' ], diff --git a/Scheduler/Binding.cci b/Scheduler/Binding.cci index fd2cec2..bd8e3e9 100644 --- a/Scheduler/Binding.cci +++ b/Scheduler/Binding.cci @@ -27,11 +27,6 @@ #define prefix_ inline ///////////////////////////////cci.p/////////////////////////////////////// -prefix_ senf::SchedulerBinding::~SchedulerBinding() -{ - disable(); -} - prefix_ void senf::SchedulerBinding::enable() { if (! enabled_) { @@ -53,6 +48,11 @@ prefix_ bool senf::SchedulerBinding::enabled() return enabled_; } +prefix_ senf::SchedulerBinding::~SchedulerBinding() +{ + disable(); +} + ///////////////////////////////cci.e/////////////////////////////////////// #undef prefix_ diff --git a/Scheduler/ClockService.cci b/Scheduler/ClockService.cci index f536931..32c7748 100644 --- a/Scheduler/ClockService.cci +++ b/Scheduler/ClockService.cci @@ -32,6 +32,63 @@ /////////////////////////////////////////////////////////////////////////// // senf::ClockService +//////////////////////////////////////// +// private members + +prefix_ bool senf::ClockService::checkSkew(boost::posix_time::ptime time) +{ + boost::posix_time::ptime h (heartbeat_); // reduce chance for race condition + return time < h || (time - h) > boost::posix_time::seconds(2*CheckInterval); +} + +prefix_ void senf::ClockService::clockSkew(boost::posix_time::ptime time, + boost::posix_time::ptime expected) +{ + base_ += (time - expected); +} + +prefix_ senf::ClockService::clock_type senf::ClockService::clock_m(abstime_type time) +{ + ///\fixme What happens, if base_ is changed in SIGALRM while reading it here ? + + // Idea: Have *two* base values: one is written by the SIGALRM handler, the other is only + // Written by synchronous code. If they differ, we block signals, copy over and continue. If + // they transiently differ because we are reading the SIGALRM value while it is being changed + // this does not matter: We will then still copy it over. + + boost::posix_time::time_duration delta (time - base_); + return clock_type( delta.ticks() ) + * clock_type( 1000000000UL / boost::posix_time::time_duration::ticks_per_second() ); +} + +prefix_ senf::ClockService::clock_type senf::ClockService::now_m() +{ + // We want to make the normal case (no skew) really fast. This first 'checkSkew' *might* + // transiently fail if a SIGALRM is delivered in the midst of the test. updateSkew will + // therefore block signals and do the check again to make sure. + // + // The opposite case (the test returns 'false' even though it should return 'true') is so highly + // improbable that it is treated as academic. (it will be catched by the next SIGALRM) + + boost::posix_time::ptime time (boost::posix_time::microsec_clock::universal_time()); + if (checkSkew(time)) + updateSkew(time); + + // 'clock' will pick up the corrected base_ value if needed. + return clock_m(time); +} + +prefix_ senf::ClockService::abstime_type senf::ClockService::abstime_m(clock_type clock) +{ +#ifdef BOOST_DATE_TIME_POSIX_TIME_STD_CONFIG + return base_ + boost::posix_time::nanoseconds(clock); +#else + return base_ + boost::posix_time::microseconds((clock+500)/1000); +#endif +} + +// public members + prefix_ senf::ClockService::clock_type senf::ClockService::now() { return instance().now_m(); @@ -52,11 +109,6 @@ prefix_ senf::ClockService::clock_type senf::ClockService::from_time_t(time_t co return clock( boost::posix_time::from_time_t(time) ); } -prefix_ senf::ClockService::clock_type senf::ClockService::from_timeval(timeval const & time) -{ - return from_time_t(time.tv_sec) + ClockService::microseconds(time.tv_usec); -} - prefix_ senf::ClockService::clock_type senf::ClockService::nanoseconds(int64_type v) { return v; @@ -127,64 +179,14 @@ prefix_ senf::ClockService::clock_type senf::ClockService::in_days(int64_type v) return v / hours(24); } -prefix_ void senf::ClockService::restart() -{ - instance().restart_m(); -} - -//////////////////////////////////////// -// private members - -prefix_ senf::ClockService::clock_type senf::ClockService::now_m() -{ - // We want to make the normal case (no skew) really fast. This first 'checkSkew' *might* - // transiently fail if a SIGALRM is delivered in the midst of the test. updateSkew will - // therefore block signals and do the check again to make sure. - // - // The opposite case (the test returns 'false' even though it should return 'true') is so highly - // improbable that it is treated as academic. (it will be catched by the next SIGALRM) - - boost::posix_time::ptime time (boost::posix_time::microsec_clock::universal_time()); - if (checkSkew(time)) - updateSkew(time); - - // 'clock' will pick up the corrected base_ value if needed. - return clock_m(time); -} - -prefix_ senf::ClockService::abstime_type senf::ClockService::abstime_m(clock_type clock) -{ -#ifdef BOOST_DATE_TIME_POSIX_TIME_STD_CONFIG - return base_ + boost::posix_time::nanoseconds(clock); -#else - return base_ + boost::posix_time::microseconds((clock+500)/1000); -#endif -} - -prefix_ senf::ClockService::clock_type senf::ClockService::clock_m(abstime_type time) -{ - ///\fixme What happens, if base_ is changed in SIGALRM while reading it here ? - - // Idea: Have *two* base values: one is written by the SIGALRM handler, the other is only - // Written by synchronous code. If they differ, we block signals, copy over and continue. If - // they transiently differ because we are reading the SIGALRM value while it is being changed - // this does not matter: We will then still copy it over. - - boost::posix_time::time_duration delta (time - base_); - return clock_type( delta.ticks() ) - * clock_type( 1000000000UL / boost::posix_time::time_duration::ticks_per_second() ); -} - -prefix_ bool senf::ClockService::checkSkew(boost::posix_time::ptime time) +prefix_ senf::ClockService::clock_type senf::ClockService::from_timeval(timeval const & time) { - boost::posix_time::ptime h (heartbeat_); // reduce chance for race condition - return time < h || (time - h) > boost::posix_time::seconds(2*CheckInterval); + return from_time_t(time.tv_sec) + ClockService::microseconds(time.tv_usec); } -prefix_ void senf::ClockService::clockSkew(boost::posix_time::ptime time, - boost::posix_time::ptime expected) +prefix_ void senf::ClockService::restart() { - base_ += (time - expected); + instance().restart_m(); } ///////////////////////////////cci.e/////////////////////////////////////// diff --git a/Socket/ClientSocketHandle.ct b/Socket/ClientSocketHandle.ct index 2678fa6..549aa97 100644 --- a/Socket/ClientSocketHandle.ct +++ b/Socket/ClientSocketHandle.ct @@ -28,6 +28,7 @@ // Custom includes #include +#include #include "../Utils/Buffer.hh" #define prefix_ @@ -120,9 +121,9 @@ prefix_ std::pair senf::ClientSocketHandle::readfrom(unsigned limit) { std::string rv; - typename SPolicy::AddressingPolicy::Address addr; - this->readfrom(rv,addr,limit); - return std::make_pair(rv,addr); + boost::value_initialized addr; + this->readfrom(rv,addr.data(),limit); + return std::make_pair(rv,addr.data()); } template diff --git a/Socket/FileHandle.cc b/Socket/FileHandle.cc index 2b1e176..baafe7a 100644 --- a/Socket/FileHandle.cc +++ b/Socket/FileHandle.cc @@ -132,6 +132,9 @@ prefix_ bool senf::FileBody::pollCheck(int fd, bool incoming, bool block) return rv>0; } +prefix_ senf::FileBody::~FileBody() +{} + ///////////////////////////////cc.e//////////////////////////////////////// #undef prefix_ diff --git a/Socket/FileHandle.cci b/Socket/FileHandle.cci index 79308ae..e04980a 100644 --- a/Socket/FileHandle.cci +++ b/Socket/FileHandle.cci @@ -96,6 +96,19 @@ prefix_ void senf::FileBody::waitWriteable() /////////////////////////////////////////////////////////////////////////// // senf::FileHandle +prefix_ senf::FileBody & senf::FileHandle::body() +{ + SENF_ASSERT(body_); + return *body_; +} + +prefix_ senf::FileBody const & senf::FileHandle::body() + const +{ + SENF_ASSERT(body_); + return *body_; +} + prefix_ void senf::FileHandle::close() { body().close(); @@ -183,19 +196,6 @@ prefix_ senf::FileHandle::FileHandle(FileBody::ptr body) : body_(body) {} -prefix_ senf::FileBody & senf::FileHandle::body() -{ - SENF_ASSERT(body_); - return *body_; -} - -prefix_ senf::FileBody const & senf::FileHandle::body() - const -{ - SENF_ASSERT(body_); - return *body_; -} - prefix_ senf::FileBody & senf::FileHandle::body(FileHandle & handle) { return handle.body(); diff --git a/Socket/FileHandle.ih b/Socket/FileHandle.ih index e87e319..84df70c 100644 --- a/Socket/FileHandle.ih +++ b/Socket/FileHandle.ih @@ -83,10 +83,11 @@ namespace senf { constructor not some arbitrary id even if you overload all the virtual members. If the file descriptor is -1 the resulting body/handle is not valid() */ + virtual ~FileBody(); - // NO DESTRUCTOR HERE - destructors and virtual functions don't mix. What would be in the - // the destructor is in 'destroyClose()' which is called from FileHandle::~FileHandle() - // *before* the last handle dies. + // NO DESTRUCTOR HERE (that is, only an empty virtual destructor) - destructors and virtual + // functions don't mix. What would be in the the destructor is in 'destroyClose()' which is + // called from FileHandle::~FileHandle() *before* the last handle dies. // no copy // no conversion constructors diff --git a/Socket/Protocols/INet/INet4Address.cci b/Socket/Protocols/INet/INet4Address.cci index 74ac443..b85ddaf 100644 --- a/Socket/Protocols/INet/INet4Address.cci +++ b/Socket/Protocols/INet/INet4Address.cci @@ -44,6 +44,23 @@ prefix_ senf::INet4Address senf::INet4Address::from_inaddr(inaddr_type v) return INet4Address(v,IsInAddr); } +prefix_ senf::INet4Address::inaddr_type & senf::INet4Address::iref() +{ + return *reinterpret_cast(&(*this)[0]); +} + +prefix_ senf::INet4Address::inaddr_type senf::INet4Address::iref() + const +{ + return *reinterpret_cast(&(*this)[0]); +} + +prefix_ senf::INet4Address::inaddr_type senf::INet4Address::inaddr() + const +{ + return iref(); +} + prefix_ senf::INet4Address::INet4Address(inaddr_type addr, InAddr_t) { iref() = addr; @@ -61,25 +78,27 @@ prefix_ bool senf::INet4Address::boolean_test() return inaddr(); } -prefix_ senf::INet4Address::inaddr_type senf::INet4Address::inaddr() +/////////////////////////////////////////////////////////////////////////// +// senf::INet4Network + +prefix_ unsigned senf::INet4Network::prefix_len() const { - return iref(); + return prefix_len_; } -prefix_ senf::INet4Address::inaddr_type & senf::INet4Address::iref() -{ - return *reinterpret_cast(&(*this)[0]); -} +//////////////////////////////////////// +// private members -prefix_ senf::INet4Address::inaddr_type senf::INet4Address::iref() +prefix_ boost::uint32_t senf::INet4Network::mask() const { - return *reinterpret_cast(&(*this)[0]); + // This is correct as long as the system is using 2-complement arithmetic ... + return (~((boost::uint32_t(1u)<<(32u-prefix_len()))-1u)) & 0xFFFFFFFFu; } -/////////////////////////////////////////////////////////////////////////// -// senf::INet4Network +//////////////////////////////////////// +// public members prefix_ senf::INet4Network::INet4Network() : prefix_len_(), address_() @@ -95,12 +114,6 @@ prefix_ senf::INet4Address const & senf::INet4Network::address() return address_; } -prefix_ unsigned senf::INet4Network::prefix_len() - const -{ - return prefix_len_; -} - prefix_ bool senf::INet4Network::boolean_test() const { @@ -135,16 +148,6 @@ prefix_ senf::INet4Network senf::INet4Network::subnet(boost::uint32_t net, unsig return INet4Network(host(net << (32-prefix_len)),prefix_len); } -//////////////////////////////////////// -// private members - -prefix_ boost::uint32_t senf::INet4Network::mask() - const -{ - // This is correct as long as the system is using 2-complement arithmetic ... - return (~((boost::uint32_t(1u)<<(32u-prefix_len()))-1u)) & 0xFFFFFFFFu; -} - /////////////////////////////////////////////////////////////////////////// // namespace members diff --git a/Socket/Protocols/INet/INet6Address.cci b/Socket/Protocols/INet/INet6Address.cci index 1e71471..b2d0e2a 100644 --- a/Socket/Protocols/INet/INet6Address.cci +++ b/Socket/Protocols/INet/INet6Address.cci @@ -86,12 +86,6 @@ prefix_ boost::uint64_t senf::INet6Address::network() ((boost::uint64_t((*this)[7]) & 0xff) ); } -prefix_ bool senf::INet6Address::hasEuid64() - const -{ - return unicast() && ((*this)[0]&0xE0u) != 0u; -} - prefix_ boost::uint64_t senf::INet6Address::id() const { @@ -118,10 +112,16 @@ prefix_ bool senf::INet6Address::groupId() return (*this)[8] & 1u; } -prefix_ bool senf::INet6Address::unicast() +prefix_ senf::INet4Address senf::INet6Address::inet4address() const { - return ! multicast(); + return INet4Address::from_data(&(*this)[12]); +} + +prefix_ bool senf::INet6Address::inet4Mapped() + const +{ + return CheckINet6Network<0u,0u,0u,0u,0u,0xFFFFu,96>::match(*this); } prefix_ bool senf::INet6Address::multicast() @@ -144,34 +144,34 @@ prefix_ senf::INet6Address::ScopeId senf::INet6Address::scope() : GlobalScope; } -prefix_ bool senf::INet6Address::globalScope() +prefix_ bool senf::INet6Address::unicast() const { - return scope() == GlobalScope; + return ! multicast(); } - -prefix_ bool senf::INet6Address::linkScope() + +prefix_ bool senf::INet6Address::hasEuid64() const { - return scope() == LinkScope; + return unicast() && ((*this)[0]&0xE0u) != 0u; } -prefix_ senf::INet4Address senf::INet6Address::inet4address() +prefix_ bool senf::INet6Address::globalScope() const { - return INet4Address::from_data(&(*this)[12]); + return scope() == GlobalScope; } - -prefix_ bool senf::INet6Address::inet4Compatible() + +prefix_ bool senf::INet6Address::linkScope() const { - return CheckINet6Network<0u,96>::match(*this); + return scope() == LinkScope; } -prefix_ bool senf::INet6Address::inet4Mapped() +prefix_ bool senf::INet6Address::inet4Compatible() const { - return CheckINet6Network<0u,0u,0u,0u,0u,0xFFFFu,96>::match(*this); + return CheckINet6Network<0u,96>::match(*this); } prefix_ bool senf::INet6Address::globalMulticastAddr() diff --git a/Socket/Protocols/Raw/LLAddressing.cci b/Socket/Protocols/Raw/LLAddressing.cci index 1054845..dc04dea 100644 --- a/Socket/Protocols/Raw/LLAddressing.cci +++ b/Socket/Protocols/Raw/LLAddressing.cci @@ -31,11 +31,27 @@ #define prefix_ inline ///////////////////////////////cci.p/////////////////////////////////////// +prefix_ void senf::LLSocketAddress::clear() +{ + ::memset(&addr_,0,sizeof(addr_)); + addr_.sll_family = AF_PACKET; +} + +prefix_ void senf::LLSocketAddress::address(MACAddress const & addr) +{ + std::copy(addr.begin(), addr.end(),&addr_.sll_addr[0]); +} + prefix_ senf::LLSocketAddress::LLSocketAddress() { clear(); } +prefix_ void senf::LLSocketAddress::protocol(unsigned prot) +{ + addr_.sll_protocol = htons(prot); +} + prefix_ senf::LLSocketAddress::LLSocketAddress(unsigned prot, std::string const & iface) { clear(); @@ -57,12 +73,6 @@ prefix_ senf::LLSocketAddress::LLSocketAddress(MACAddress const & addr, interface(iface); } -prefix_ void senf::LLSocketAddress::clear() -{ - ::memset(&addr_,0,sizeof(addr_)); - addr_.sll_family = AF_PACKET; -} - prefix_ unsigned senf::LLSocketAddress::protocol() const { @@ -87,16 +97,6 @@ prefix_ senf::MACAddress senf::LLSocketAddress::address() return MACAddress::from_data(&addr_.sll_addr[0]); } -prefix_ void senf::LLSocketAddress::address(MACAddress const & addr) -{ - std::copy(addr.begin(), addr.end(),&addr_.sll_addr[0]); -} - -prefix_ void senf::LLSocketAddress::protocol(unsigned prot) -{ - addr_.sll_protocol = htons(prot); -} - prefix_ struct sockaddr * senf::LLSocketAddress::sockaddr_p() { return reinterpret_cast(&addr_); diff --git a/Socket/SocketPolicy.cc b/Socket/SocketPolicy.cc new file mode 100644 index 0000000..794e6cf --- /dev/null +++ b/Socket/SocketPolicy.cc @@ -0,0 +1,66 @@ +// $Id$ +// +// Copyright (C) 2008 +// Fraunhofer Institute for Open Communication Systems (FOKUS) +// Competence Center NETwork research (NET), St. Augustin, GERMANY +// Stefan Bund +// +// This program 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 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 + \brief SocketPolicy non-inline non-template implementation */ + +#include "SocketPolicy.hh" +#include "SocketPolicy.ih" + +// Custom includes + +//#include "SocketPolicy.mpp" +#define prefix_ +///////////////////////////////cc.p//////////////////////////////////////// + +prefix_ senf::AddressingPolicyBase::~AddressingPolicyBase() +{} + +prefix_ senf::FramingPolicyBase::~FramingPolicyBase() +{} + +prefix_ senf::CommunicationPolicyBase::~CommunicationPolicyBase() +{} + +prefix_ senf::ReadPolicyBase::~ReadPolicyBase() +{} + +prefix_ senf::WritePolicyBase::~WritePolicyBase() +{} + +prefix_ senf::SocketPolicyBase::~SocketPolicyBase() +{} + +///////////////////////////////cc.e//////////////////////////////////////// +#undef prefix_ +//#include "SocketPolicy.mpp" + + +// Local Variables: +// mode: c++ +// fill-column: 100 +// comment-column: 40 +// c-file-style: "senf" +// indent-tabs-mode: nil +// ispell-local-dictionary: "american" +// compile-command: "scons -u test" +// End: diff --git a/Socket/SocketPolicy.hh b/Socket/SocketPolicy.hh index 06d1359..39d358e 100644 --- a/Socket/SocketPolicy.hh +++ b/Socket/SocketPolicy.hh @@ -292,7 +292,7 @@ namespace senf { */ struct AddressingPolicyBase { - virtual ~AddressingPolicyBase() {} + virtual ~AddressingPolicyBase(); class Address { Address(); }; }; @@ -309,7 +309,7 @@ namespace senf { */ struct FramingPolicyBase { - virtual ~FramingPolicyBase() {} + virtual ~FramingPolicyBase(); }; /** \brief Policy defining, how peers are selected @@ -334,7 +334,7 @@ namespace senf { */ struct CommunicationPolicyBase { - virtual ~CommunicationPolicyBase() {} + virtual ~CommunicationPolicyBase(); }; /** \brief Policy defining the readability @@ -357,7 +357,7 @@ namespace senf { */ struct ReadPolicyBase { - virtual ~ReadPolicyBase() {} + virtual ~ReadPolicyBase(); }; /** \brief Policy defining the writability @@ -380,7 +380,7 @@ namespace senf { */ struct WritePolicyBase { - virtual ~WritePolicyBase() {} + virtual ~WritePolicyBase(); }; // The implementation file will for each Policy declared above diff --git a/Socket/SocketPolicy.ih b/Socket/SocketPolicy.ih index f52a46c..9819f00 100644 --- a/Socket/SocketPolicy.ih +++ b/Socket/SocketPolicy.ih @@ -71,7 +71,7 @@ namespace senf { struct SocketPolicyBase { - virtual ~SocketPolicyBase() {} + virtual ~SocketPolicyBase(); # define SP_Declare(x1,x2,SomePolicy) \ virtual BOOST_PP_CAT(SomePolicy,Base) const & BOOST_PP_CAT(the,SomePolicy) () \ diff --git a/Utils/Logger/AreaRegistry.cc b/Utils/Logger/AreaRegistry.cc index c0cbf14..5dc0d9d 100644 --- a/Utils/Logger/AreaRegistry.cc +++ b/Utils/Logger/AreaRegistry.cc @@ -36,6 +36,9 @@ /////////////////////////////////////////////////////////////////////////// // senf::log::detail::AreaBase +prefix_ senf::log::detail::AreaBase::~AreaBase() +{} + prefix_ void senf::log::detail::AreaBase::updateRoutingCache(Target & target, StreamBase const & stream, unsigned limit) diff --git a/Utils/Logger/AreaRegistry.ih b/Utils/Logger/AreaRegistry.ih index a3b6124..709b51c 100644 --- a/Utils/Logger/AreaRegistry.ih +++ b/Utils/Logger/AreaRegistry.ih @@ -47,7 +47,7 @@ namespace detail { /** \brief Internal: Area base class */ struct AreaBase { - virtual ~AreaBase() {}; + virtual ~AreaBase(); std::string fullName() const; virtual std::string v_name() const; diff --git a/Utils/Logger/StreamRegistry.cc b/Utils/Logger/StreamRegistry.cc index c752b93..44f5c96 100644 --- a/Utils/Logger/StreamRegistry.cc +++ b/Utils/Logger/StreamRegistry.cc @@ -34,6 +34,12 @@ unsigned senf::log::detail::StreamBase::nStreams = 0; +/////////////////////////////////////////////////////////////////////////// +// senf::log::detail::StreamBase + +prefix_ senf::log::detail::StreamBase::~StreamBase() +{} + ///////////////////////////////cc.e//////////////////////////////////////// #undef prefix_ //#include "Stream.mpp" diff --git a/Utils/Logger/StreamRegistry.ih b/Utils/Logger/StreamRegistry.ih index c1bf561..f6a4138 100644 --- a/Utils/Logger/StreamRegistry.ih +++ b/Utils/Logger/StreamRegistry.ih @@ -39,7 +39,7 @@ namespace detail { struct StreamBase { StreamBase(); - virtual ~StreamBase() {}; + virtual ~StreamBase(); std::string fullName() const; virtual std::string v_name() const; diff --git a/Utils/Logger/TimeSource.cci b/Utils/Logger/TimeSource.cci index a5173f6..2978ea2 100644 --- a/Utils/Logger/TimeSource.cci +++ b/Utils/Logger/TimeSource.cci @@ -31,14 +31,6 @@ ///////////////////////////////cci.p/////////////////////////////////////// /////////////////////////////////////////////////////////////////////////// -// senf::log::TimeSource - -prefix_ senf::log::time_type senf::log::TimeSource::now() -{ - return detail::TimeSourceManager::instance().now(); -} - -/////////////////////////////////////////////////////////////////////////// // senf::log::detail::TimeSourceManager prefix_ senf::log::detail::TimeSourceManager::TimeSourceManager() @@ -56,6 +48,14 @@ prefix_ void senf::log::detail::TimeSourceManager::timeSource(std::auto_ptr