ethernet header). Together with it's support classes (especially
senf::PacketRegistryMixin) this class greatly simplifies
implementing the needed table lookups.
+
+ \todo The Packet Libarary really needs a refactoring of the public
+ interfaface ...
+
+ \idea Add the Handle-Body idiom to the mix with a PacketRef (or
+ HeaderRef or InterpreterRef or whatever class). This would
+ have members for all the API defined in Packet now. \c
+ operator-> would return a parser object to interpret the
+ data. This would make awayy with the inheritance relationship
+ ...
+
+ \idea Templating the parsers on the iterator type does not
+ introduce additional coupling (because of the inlining) but
+ looking at it after the fact it looks like severe overdesign
+ and it does introduce some problems (e.g. rebind and all this
+ entails). If we just implement all parsers for
+ Packet::byte_iterator they are no tmplates any more which
+ should simplify things a log.
+
+ \idea we need some better and automatic checking on data access
+ especially after data has changed. Idea 1: give the parser the
+ end iterator as additional member. Enforce, that all parsers
+ must ultimately be based on ParseInt and have ParseInt check
+ against end() at construction time. Idea 2: add a dirty flag
+ to the interpreters. Set this flag whenever the packet is
+ changed and recall check() in operator-> of the PacketRef
+ object if the packet is dirty. Maybe we need both and make
+ them tunable.
*/
\f
PROJECT_NAME = libScheduler
TAGFILES = "$(TOPDIR)/Utils/doc/Utils.tag"
GENERATE_TAGFILE = doc/Scheduler.tag
+ALPHABETICAL_INDEX = NO
--- /dev/null
+namespace senf {
+
+/** \mainpage The SENF Scheduler Library
+
+ The Scheduler library provides a simple yet flexible abstraction
+ of the standard asynchronous UNIX mainloop utilizing \c select or
+ \c poll. The Scheduler library is based on the highly efficient
+ (but linux specific) \c epoll() system call.
+
+ The library provides
+ \li a central \ref Scheduler singleton and
+ \li \ref ReadHelper and \ref WriteHelper templates to simplify
+ common tasks.
+
+ In it's current incarnation, the library only supports network
+ file handles (including pipes etc) and simple timers (especially
+ it does not support asynchronous notification for on-disc file
+ transfers etc). Additional features will be added:
+ \li UNIX signal support
+ \li async IO support for local (disc) file handles
+ \li multi threading support
+ \li IPC support for multithreaded applications
+ */
+
+}
+
+\f
+// Local Variables:
+// mode: c++
+// mode: flyspell
+// mode: auto-fill
+// ispell-local-dictionary: "american"
+// End:
// $Id$
//
+// Copyright (C) 2006 Stefan Bund <g0dil@berlios.de>
+//
+// 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.
// Copyright (C) 2006
-// Definition of inline non-template functions
+/** \file
+ \brief ReadHelper inline non-template implementation */
// Custom includes
#define prefix_ inline
///////////////////////////////cci.p///////////////////////////////////////
-prefix_ senf::ReadUntil::ReadUntil(std::string target_)
+prefix_ senf::ReadUntil::ReadUntil(std::string const & target_)
: target(target_)
{}
-prefix_ std::string::size_type senf::ReadUntil::operator()(std::string data)
+prefix_ std::string::size_type senf::ReadUntil::operator()(std::string const & data)
{
return data.find(target);
}
// $Id$
//
+// Copyright (C) 2006 Stefan Bund <g0dil@berlios.de>
+//
+// 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.
// Copyright (C) 2006
-// Definition of non-inline template functions
+/** \file
+ \brief ReadHelper non-inline template implementation */
#include "ReadHelper.ih"
prefix_ void senf::ReadHelper<Handle>::process(Handle handle,
senf::Scheduler::EventId event)
{
+ /** \fixme Move the done() calls to outside the try/catch block */
try {
if (event != senf::Scheduler::EV_READ)
throw SystemException(EPIPE);
// $Id$
//
+// Copyright (C) 2006 Stefan Bund <g0dil@berlios.de>
+//
+// 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.
// Copyright (C) 2006
-// Definition of inline template functions
+/** \file
+ \brief ReadHelper inline template implementation */
#include "ReadHelper.ih"
template <class Predicate>
prefix_ typename senf::ReadHelper<Handle>::ptr
senf::ReadHelper<Handle>::dispatch(Handle handle, std::string::size_type maxSize,
- Predicate predicate, Callback callback)
+ Predicate const & predicate, Callback callback)
{
return ptr(new ReadHelper(handle, maxSize,
new typename InternalPredicate::template Dispatcher<Predicate>(predicate),
// $Id$
//
+// Copyright (C) 2006 Stefan Bund <g0dil@berlios.de>
+//
+// 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.
// Copyright (C) 2006
+/** \file
+ \brief ReadHelper public header */
#ifndef HH_ReadHelper_
#define HH_ReadHelper_ 1
namespace senf {
- /** \brief
+ /** \brief Asyncronous reading helper
+
+ This class provides a simple asynchronous reading facility. This helper will register with
+ the Scheduler and read incoming data. It will collect the data until a specific numbner of
+ bytes has been read or some Predicate evaluated on the data read thus far signals end of
+ data.
+
+ The ReadHelper accepts the same flexible file handle interfaces as the Scheduler.
+
+ The callback must take a ReadHelper::ptr argument. Using this ReadHelper instance, the
+ callback can access the data read or retrieve state information.
+
+ The ReadHelper separates the data into two parts: data() will return the matched data,
+ tail() will return any surplus data already read. If you don't specify a predicate, tail()
+ will always be empty (there may however some data be left in the socket input buffer after
+ the ReadHelper returns).
+
+ The predicate is any class instance with an <tt>operator(std::string const &)</tt>. This
+ operator is called, whenever some data has been read. If the data is not yet complete, the
+ predicate must return \c std::string::npos. If the ReadHelper should stop readeing more
+ data, the predicate must return the number of bytes which are to be considered 'matched'.
\todo Move all not Handle dependent members to a ReadHandleBase class
+ \todo Add an optional <tt>std::string const & tail</tt> argument to the constructors which
+ takes the tail() of a previous ReadHelper instance.
*/
template <class Handle>
class ReadHelper
///////////////////////////////////////////////////////////////////////////
// Types
- typedef boost::intrusive_ptr<ReadHelper> ptr;
- typedef boost::function<void (ptr)> Callback;
+ typedef boost::intrusive_ptr<ReadHelper> ptr; ///< Smart pointer type for this class
+ typedef boost::function<void (ptr)> Callback; ///< Callback type
///////////////////////////////////////////////////////////////////////////
///\name Structors and default members
///@{
static ptr dispatch(Handle handle, std::string::size_type maxSize,
- Callback callback);
+ Callback callback); ///< Register new ReadHandler instance
+ /**< The registered Callback will be called after \a maxSize
+ bytes have been read or EOF or some error is
+ encountered.
+ \post The returned ReadHelper instance is registered
+ with the Scheduler to handle read events.
+ \param[in] handle file descriptor or handle providing
+ the Handle interface defined above.
+ \param[in] maxSize maximum number of bytes to read
+ \param[in] cb callback
+ \returns Smart pointer to new ReadHelper instance */
template <class Predicate>
- static ptr dispatch(Handle handle, std::string::size_type maxSize, Predicate predicate,
- Callback callback);
+ static ptr dispatch(Handle handle, std::string::size_type maxSize, Predicate const & predicate,
+ Callback callback); ///< Register new ReadHelper instance
+ /**< The registered Callback will be called after the \a
+ predicate returns a Value other than \c
+ std::string::npos, \a maxSize bytes have been read, or
+ EOF or some error condition is encountered.
+ \post The returned ReadHelper instance is registered
+ with the Scheduler to handle read events
+. \param[in] handle file descriptor or handle providing
+ the Handle interface defined above.
+ \param[in] maxSize maximum number of bytes to read
+ \param[in] predicate predicate to check
+ \param[in] cb callback
+ \returns smart pointer to new ReadHelper instance */
///@}
///////////////////////////////////////////////////////////////////////////
- Handle handle() const;
- unsigned maxSize() const;
+ Handle handle() const; ///< Access the handle object
+ unsigned maxSize() const; ///< Return maximum number of bytes to be read
- std::string const & data() const;
- std::string const & tail() const;
+ std::string const & data() const; ///< return data read
+ std::string const & tail() const; ///< return data read but not matched by the predicate
- bool complete() const;
- bool error() const;
- void throw_error() const;
+ bool complete() const; ///< Check wether the read has completed successfully
+ bool error() const; ///< Check for error condition
+ void throw_error() const; ///< If an error occured, throw it
- void revoke();
+ void revoke(); ///< Remove the ReadHelper from the scheduler
protected:
bool complete_;
};
+ /** \brief ReadHelper predicate matching an arbitrary string
+
+ This predicate will terminate the read when the data read matches a given fixed string. All
+ data up to and including the string matched is considered to be part of the data() portion,
+ everything after the matched string is placed into the tail().
+
+ \see ReadHelper
+ */
struct ReadUntil
{
- ReadUntil(std::string target);
- std::string::size_type operator()(std::string data);
+ ReadUntil(std::string const & target);
+ std::string::size_type operator()(std::string const & data);
std::string target;
};
\f
// Local Variables:
// mode: c++
+// c-file-style: "senf"
+// fill-column: 100
// End:
// $Id$
//
+// Copyright (C) 2006 Stefan Bund <g0dil@berlios.de>
+//
+// 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.
// Copyright (C) 2006
+/** \file
+ \brief ReadHelper internal header */
+
#ifndef IH_ReadHelper_
#define IH_ReadHelper_ 1
namespace senf {
+ /** \brief Abstract predicate interface
+ \internal
+ */
template <class Handle>
struct ReadHelper<Handle>::InternalPredicate
{
virtual ~InternalPredicate() {}
+
+ /** \brief template to runtime polymorphic barrier for the predicate interface
+ \internal
+
+ \implementation This class will provide a polymorphic
+ wrapper around the non-polymorphic ReadHelper
+ predicate. This is used, so the predicate can be
+ specified as an arbitrary callable object (even a
+ boost::function or a Boost.Lambda expression) without
+ imposing any inheritance relationship on the predicate
+ */
template <class Predicate>
struct Dispatcher
: public ReadHelper<Handle>::InternalPredicate
// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
/** \file
+ \brief Scheduler non-inline non-template implementation
\idea Implement signal handling (See source for more discussion
about this)
\idea Multithreading support: To support multithreading, the
static member Scheduler::instance() must return a thread-local
value (that is Scheduler::instance() must allocate one Scheduler
- instance per thread)
+ instance per thread). Another possibility would be to distribute
+ the async load unto several threads (one scheduler for multiple
+ threads)
*/
// Here a basic concept of how to add signal support to the scheduler:
// with the scheduler must be blocked as soon as it is registered with
// the scheduler.
-// Definition of non-inline non-template functions
-
#include "Scheduler.hh"
//#include "Scheduler.ih"
if (spec.cb_hup)
spec.cb_hup(EV_HUP);
else if (ev.events & EPOLLERR) {
- /// \fixme This is stupid, if cb_write and cb_read are
- /// the same. The same below. We really have to
- /// exactly define sane semantics of what to do on
- /// EPOLLHUP and EPOLLERR.
+ /** \fixme This is stupid, if cb_write and cb_read are
+ the same. The same below. We really have to
+ exactly define sane semantics of what to do on
+ EPOLLHUP and EPOLLERR. */
if (spec.cb_write) spec.cb_write(EV_HUP);
if (spec.cb_read) spec.cb_read(EV_HUP);
}
// Free Software Foundation, Inc.,
// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-// Definition of inline non-template functions
+/** \file
+ \brief Scheduler inline non-template implementation
+ */
//#include "Scheduler.ih"
// Free Software Foundation, Inc.,
// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-// Definition of inline template functions
+/** \file
+ \brief Scheduler inline template implementation
+ */
//#include "Scheduler.ih"
// Free Software Foundation, Inc.,
// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-/** \mainpage The SENF Scheduler library
-
+/** \file
+ \brief Scheduler public header
*/
#ifndef HH_Scheduler_
/** \brief Singleton class to manage the event loop
- This class manages a single select() type event loop. A
- customer of this class may register any number of file
- descriptiors with this class and pass callback functions to be
- called on input, output or error. This functions are specified
- using boost::function objects
-
- \todo Fix EventId parameter (probably to int) to allow |-ing
- without casting ...
+ This class manages a single select() type event loop. A customer of this class may register
+ any number of file descriptiors with this class and pass callback functions to be called on
+ input, output or error. This functions are specified using boost::function objects (See <a
+ href="http://www.boost.org/doc/html/function.html">Boost.Function</a>)
+
+ The Scheduler is based on a generic handle representation. The only information needed from
+ a handle, is the intrinsic file descriptor. Any object for which the statement
+ \code
+ int fd = retrieve_filehandle(object);
+ \endcode
+ is valid and places the relevent file descriptor into fd can be used as a Handle type. There
+ is an implementation of retrieve_filehandle(int) within the library to handle explicit file
+ descrptors. The <a href="../../../Socket/doc/html/index.html">Socket library</a> provides an
+ implementation of <tt>retrive_filehandle(FileHandle handle)</tt>. If you want to support
+ some other handle type, just define an apropriate \c retrieve_filehandle function <em>in
+ that types namespace</em>.
+
+ It is important to note, that for every combination of file descriptor and event, only a \e
+ single handler may be installed. Installing more handlers does not make sense. If you need
+ to distribute data to serveral interested parties, you must take care of this yourself.
+
+ \todo Fix EventId parameter (probably to int) to allow |-ing without casting ...
*/
class Scheduler
: boost::noncopyable
///////////////////////////////////////////////////////////////////////////
// Types
+ /// \brief Types of file descriptor events */
enum EventId { EV_NONE=0,
EV_READ=1, EV_PRIO=2, EV_WRITE=4, EV_HUP=8, EV_ERR=16,
EV_ALL=31 };
+ /** \brief Template typedef for Callback type
+
+ This is a template typedef (which does not exist in C++) that is, a template class whose
+ sole member is a typedef symbol defining the callback type given the handle type.
+
+ The Callback is any callable object taking a \c Handle and an \c EventId as argument.
+ */
template <class Handle>
struct GenericCallback {
typedef boost::function<void (typename boost::call_traits<Handle>::param_type,
EventId) > Callback;
};
- typedef boost::function<void (EventId)> SimpleCallback;
+ /** \brief Callback type for timer events */
typedef boost::function<void ()> TimerCallback;
///////////////////////////////////////////////////////////////////////////
// default destructor
// no conversion constructors
+ /** \brief Return Scheduler instance
+
+ This static member is used to access the singleton instance. This member is save to
+ return a correctly initialized Scheduler instance even if called at global construction
+ time
+
+ \implementation This static member just defines the Scheduler as a static method
+ variable. The C++ standard then provides above guaratee. The instance will be
+ initialized the first time, the code flow passes the variable declaration found in
+ the instance() body.
+ */
static Scheduler & instance();
///@}
template <class Handle>
void add(Handle const & handle,
typename GenericCallback<Handle>::Callback const & cb,
- int eventMask = EV_ALL);
+ int eventMask = EV_ALL); ///< Add file handle event callback
+ /**< add() will add a callback to the Scheduler. The
+ callbeck will be called for the given type of event on
+ the given arbitrary file-descriptor or
+ handle-like object. If there already is a Callback
+ register ed for one of the events requested, the new
+ handler will replace the old one.
+ \param[in] handle file descriptor or handle providing
+ the Handle interface defined above.
+ \param[in] cb callback
+ \param[in] eventMask arbitrary combination via '|'
+ operator of EventId designators. */
template <class Handle>
- void remove(Handle const & handle, int eventMask = EV_ALL);
-
- void timeout(unsigned long timeout, TimerCallback const & cb);
-
- void process();
- void terminate();
+ void remove(Handle const & handle, int eventMask = EV_ALL); ///< Remove event callback
+ /**< remove() will remove any callback registered for any of
+ the given events on the given file descriptor or handle
+ like object.
+ \param[in] handle file descriptor or handle providing
+ the Handle interface defined above.
+ \param[in] eventMask arbitrary combination via '|'
+ operator of EventId designators. */
+
+ void timeout(unsigned long timeout, TimerCallback const & cb); ///< Add timeout event
+ /**< \param[in] timeout timeout in milliseconds
+ \param[in] cb callback to call after \a timeout
+ milliseconds
+ \todo Return some kind of handle/pointer and add
+ support to update or revoke a timeout */
+
+ void process(); ///< Event handler main loop
+ /**< This member must be called at some time to enter the
+ event handler main loop. Only while this function is
+ running any events are handled. The call will return
+ only, if any callback calls terminate(). */
+ void terminate(); ///< Called by callbacks to terminate the main loop
+ /**< This member may be called by any callback to tell the
+ main loop to terminate. The main loop will return to
+ it's caller after the currently running callback
+ returns. */
protected:
private:
+ typedef boost::function<void (EventId)> SimpleCallback;
+
Scheduler();
void do_add(int fd, SimpleCallback const & cb, int eventMask = EV_ALL);
void do_remove(int fd, int eventMask = EV_ALL);
+ /** \brief Descriptor event specification
+ \internal */
struct EventSpec
{
SimpleCallback cb_read;
int epollMask() const;
};
+ /** \brief Timer event specification
+ \internal */
struct TimerSpec
{
TimerSpec() : timeout(), cb() {}
bool terminate_;
};
+ /** \brief Default file descriptor accessor
+
+ retrieve_filehandle() provides the Scheduler with support for explicit file descriptors as
+ file handle argument.
+
+ \relates Scheduler
+ */
int retrieve_filehandle(int fd);
}
///////////////////////////////hh.e////////////////////////////////////////
#include "Scheduler.cci"
-#include "Scheduler.ct"
+//#include "Scheduler.ct"
#include "Scheduler.cti"
#endif
// Local Variables:
// mode: c++
// c-file-style: "senf"
+// fill-column: 100
// End:
// $Id$
//
+// Copyright (C) 2006 Stefan Bund <g0dil@berlios.de>
+//
+// 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.
// Copyright (C) 2006
-// Definition of non-inline template functions
+/** \file
+ \brief WriteHelper non-inline template implementation */
//#include "WriteHelper.ih"
prefix_ void senf::WriteHelper<Handle>::process(Handle handle,
senf::Scheduler::EventId event)
{
+ /** \fixme Move the done() calls to outside the try/catch block */
try {
if (event != senf::Scheduler::EV_WRITE)
throw senf::SystemException(EPIPE);
// $Id$
//
+// Copyright (C) 2006 Stefan Bund <g0dil@berlios.de>
+//
+// 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.
// Copyright (C) 2006
-// Definition of inline template functions
+/** \file
+ \brief WriteHelper inline template implementation */
//#include "WriteHelper.ih"
// $Id$
//
+// Copyright (C) 2006 Stefan Bund <g0dil@berlios.de>
+//
+// 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.
// Copyright (C) 2006
+/** \file
+ \brief WriteHelper public header */
+
#ifndef HH_WriteHelper_
#define HH_WriteHelper_ 1
namespace senf {
+ /** \brief Asyncronous writing helper
+
+ This class provides a simple asyncronous writing facility. This helper will register with
+ the Scheduler to write the requested data. It will stay registered until the data has benen
+ completely sent or some error condition is encountered. As soon as the WriteHelper is done,
+ the callback will be called.
+
+ The WriteHelper accepts the same flexible file handle interfaces as the Scheduler.
+
+ The callback must take a WriteHelper::ptr argument. Using this WriteHelper instance, the
+ callback can access the state information and check the termination status.
+ \todo Add additional interface to better access the intermediate status (data sent so far)
+ */
template <class Handle>
class WriteHelper
: public senf::intrusive_refcount
///////////////////////////////////////////////////////////////////////////
// Types
- typedef boost::intrusive_ptr<WriteHelper> ptr;
- typedef boost::function<void (ptr)> Callback;
+ typedef boost::intrusive_ptr<WriteHelper> ptr; ///< Smart pointer type for this class
+ typedef boost::function<void (ptr)> Callback; ///< Callback type
///////////////////////////////////////////////////////////////////////////
///\name Structors and default members
///@{
static ptr dispatch(Handle handle, std::string data, Callback callback);
+ ///< Register new WriteHelper instance
+ /**< The registered callback will be called after all \a
+ data has been sent or when some error condition is
+ encountered.
+ \param[in] handle file descriptor or handle providing
+ the Handle interface defined above.
+ \param[in] data data to send
+ \param[in] cb callback
+ \returns smart pointer to new WriteHelper instance */
///@}
///////////////////////////////////////////////////////////////////////////
Handle handle() const;
- std::string const & data() const;
+ std::string const & data() const; ///< Return the data
+ /**< After all data has been sent, this member will return
+ an empty string. Until then, the complete string will
+ be returned. */
- bool complete() const;
- bool error() const;
- void throw_error() const;
+ bool complete() const; ///< Check wether the write has completed successfully
+ bool error() const; ///< Check for error condition
+ void throw_error() const; ///< If an error occured, throw it
- void revoke();
+ void revoke(); ///< Remove the WriteHelper from the scheduler
protected:
\f
// Local Variables:
// mode: c++
+// c-file-style: "senf"
+// fill-column: 100
// End:
// $Id$
//
-// Copyright (C) 2006
+// Copyright (C) 2006 Stefan Bund <g0dil@senf.berlios.de>
+//
+// 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.
-// Definition of non-inline non-template functions
+/** \file
+ \brief DaemonTools non-inline non-template implementation */
#include "DaemonTools.hh"
//#include "DaemonTools.ih"
// $Id$
//
-// Copyright (C) 2006
+// Copyright (C) 2006 Stefan Bund <g0dil@senf.berlios.de>
+//
+// 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 DaemonTools public header */
+
+/** \defgroup process Process Management
+
+ This collection of utilities provides help in managing daemon processes.
+
+ \idea Add communication between parent and child process to daemonize() and add things like
+ init_done(), failure() etc which allow the daemon process to tell the frontend of successful
+ startup or failure. This proabably means moving all the methods into a DaemonTools class (as
+ statics or via a singleton). This would also allow for automatic pid file creation and
+ removal (remove in global destructor).
+
+ \idea Add a DaemonProcess baseclass whith init() and main() abstract members which wraps the
+ startup process. DaeminProcess::run() would fork, call init(), create a pid file and then
+ call main(). Exceptions during init()'s execution would be passed to the parent
+ process. This is based on the above API.
+
+ \idea A closeall()/closemost() function which is useful when starting child processes. We'll use
+ getrlimit to now the biggest filehandle and close all of em. closemost() takes a number of
+ file handles as arg and will keep those open.
+
+ \idea We might want to add other oft used utitlities: chroot(), setreuid(), pipes() / IPC ...
+ */
#ifndef HH_DaemonTools_
#define HH_DaemonTools_ 1
namespace senf {
+ /// \addtogroup process
+ /// @{
- void daemonize();
- void redirect_stdio(std::string const & path = "/dev/null");
+ void daemonize(); ///< Make the current process a daemon process
+ /**< daemonize() will fork, detach from the controlling
+ terminal and start a new process group. */
+ void redirect_stdio(std::string const & path = "/dev/null"); ///< Redirect STDIN, STDOUT and STDERR
+ /**< All standard file-descriptors will be redirected to the
+ given path defaulting to <tt>/dev/null</tg>
+ \param[in] path path to redirect to */
+ /// @}
}
///////////////////////////////hh.e////////////////////////////////////////
\f
// Local Variables:
// mode: c++
+// c-file-style: "senf"
+// fill-column: 100
// End:
PROJECT_NAME = libUtils
GENERATE_TAGFILE = doc/Utils.tag
+ALPHABETICAL_INDEX = NO
// Free Software Foundation, Inc.,
// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-// Definition of non-inline non-template functions
+/** \file
+ \brief Exception non-inline non-template implementation */
#include "Exception.hh"
//#include "Exception.ih"
prefix_ void senf::SystemException::init()
{
+ // We normallyl don't want to consume memory in an exception,
+ // however all other solutions to format the message are terribly
+ // ugly (since thay must use a static and shared buffer ...)
std::stringstream s;
if (where)
s << where << ": ";
// $Id$
//
-// Copyright (C) 2006
-// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS)
-// Kompetenzzentrum fuer Satelitenkommunikation (SatCom)
-// Stefan Bund <stefan.bund@fokus.fraunhofer.de>
+// Copyright (C) 2006 Stefan Bund <g0dil@senf.berlios.de>
//
// 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
// Free Software Foundation, Inc.,
// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-// Definition of non-inline template functions
-
-//#include "Scheduler.ih"
+/** \file
+ \brief Exception inline non-template implementation */
// Custom includes
-#define prefix_
-///////////////////////////////ct.p////////////////////////////////////////
+#define prefix_ inline
+///////////////////////////////cci.p///////////////////////////////////////
+
+prefix_ senf::SystemException::SystemException(int err_)
+ : where(0), err(err_)
+{
+ init();
+}
+
+prefix_ senf::SystemException::SystemException(char const * where_, int err_)
+ : where(where_), err(err_)
+{
+ init();
+}
+
+prefix_ senf::SystemException::~SystemException()
+ throw()
+{}
-///////////////////////////////ct.e////////////////////////////////////////
+///////////////////////////////cci.e///////////////////////////////////////
#undef prefix_
\f
// Local Variables:
// mode: c++
-// c-file-style: "senf"
// End:
// Free Software Foundation, Inc.,
// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+/** \file
+ \brief Exception public header */
+
#ifndef HH_Exception_
#define HH_Exception_ 1
namespace senf {
+ /** \brief Exception handling standard UNIX errors (errno)
+
+ This exception is thrown to signal generic errno failuers.
+
+ \todo make where and err accessors and make the member vars private
- struct SystemException : public std::exception
+ \idea Add a template class derived from SystemException which
+ takes the error number as a numeric argument. This allows
+ catching specific errno conditions: ErrnoException<EPIPE> etc.
+
+ \idea Add a generic error thrower which takes the origin
+ string and errno value as an argument and will throw a
+ corresponding template class instance. This would just be a
+ big switch statement containing all possible errno values,
+ probably created using some makro metaprogramming.
+ */
+ class SystemException : public std::exception
{
- explicit SystemException(int err_) : where(0), err(err_) { init(); }
- SystemException(char const * where_, int err_) : where(where_), err(err_) { init(); }
+ public:
+ explicit SystemException(int err); ///< SystemException without error lokus info
+ /**< \param[in] err errror number (the errno value) */
+ SystemException(char const * where, int err); ///< SystemException with error lokus info
+ /**< \param[in] where description of error origin
+ \param[in] err error number (the errno value) */
- virtual char const * what() const throw();
+ virtual char const * what() const throw(); ///< Return verbose error description
- char const * where;
- int err;
+ char const * where; ///< Error origin
+ int err; ///< Error number
- virtual ~SystemException() throw() {}
+ virtual ~SystemException() throw();
private:
void init();
std::string buffer_;
}
///////////////////////////////hh.e////////////////////////////////////////
-//#include "Exception.cci"
+#include "Exception.cci"
//#include "Exception.ct"
//#include "Exception.cti"
#endif
--- /dev/null
+namespace senf {
+
+/** \mainpage The SENF Utilities Library
+
+ The Utilities Library is a collection of independent
+ utilities. We have
+ <dl>
+
+ <dt>SystemException</dt><dd>standard exception for system errors
+ (errno)</dd>
+
+ <dt>\ref time</dt><dd>Very rudimentary microsecond time
+ support</dd>
+
+ <dt>\ref process</dt><dd>Some simple process management and daemon
+ helpers<?dd>
+
+ <dt>\ref membind</dt><dd>a simple <a
+ href="http://www.boost.org/libs/bind/bind.html">Boost.Bind</a>
+ extension</dd>
+
+ <dt>intrusive_refcount</dt><dd>mixin to simplify writing classes for
+ use with <a
+ href="http://www.boost.org/libs/smart_ptr/intrusive_ptr.html">boost::intrusive_ptr</a></dd>
+
+ <dt>SafeBool</dt><dd>a mixin class to provide a really safe
+ replacement for <tt>operator bool</tt></dd>
+
+ <dt>prettyName()</dt><dd>an interface to the C++ demangler of g++
+ to get formated type names from typeinfo objects</dd>
+
+ </dl>
+ */
+
+}
+
+\f
+// Local Variables:
+// mode: c++
+// mode: flyspell
+// mode: auto-fill
+// ispell-local-dictionary: "american"
+// End:
// $Id$
//
-// Copyright (C) 2006
+// Copyright (C) 2006 Stefan Bund <g0dil@senf.berlios.de>
+//
+// 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.
-// Definition of non-inline non-template functions
+/** \file
+ \brief MicroTime non-inline non-template implementation */
#include "MicroTime.hh"
//#include "MicroTime.ih"
// $Id$
//
-// Copyright (C) 2006
+// Copyright (C) 2006 Stefan Bund <g0dil@senf.berlios.de>
+//
+// 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 MicroTime public header */
+
+/** \defgroup time Microseconds Time
+
+ MicroTime provides extremely rudimentary support for a time data
+ type precise to 10<sup>-6</sup> seconds. Up to now, the only
+ supported members are the datatype (which just uses a 64 bit
+ integer) and the now() function to get the current UTC time in
+ microsecods since the Epoch.
+
+ \idea This thing only exists as a quick hack. We can probably make
+ use of Boost.Time or some such thing so it probably does not
+ make sense to extend this further. We should however check the
+ performance of Boost.Time since this is used heavily in the
+ Scheduler.
+ */
#ifndef HH_MicroTime_
#define HH_MicroTime_ 1
///////////////////////////////hh.p////////////////////////////////////////
namespace senf {
+
+ /// \addtogroup time
+ /// @{
+ typedef boost::uint64_t MicroTime; ///< Microsecond accurent time datatype
- typedef boost::uint64_t MicroTime;
+ MicroTime now(); ///< Get current UTC time with microsecond accuracy
- MicroTime now();
+ /// @}
}
namespace senf {
-
- // This is a direct copy of a safe bool solution by Bjorn Karlsson
- // from http://www.artima.com/cppsource/safebool.html
- //
- // Usage:
- // class TestableWithVirtual
- // : public safe_bool<>
- // {
- // protected:
- // bool boolean_test() const
- // {
- // // Perform Boolean logic here
- // }
- // };
- //
- // class TestableWithoutVirtual
- // : public safe_bool <TestableWithoutVirtual>
- // {
- // public:
- // bool boolean_test() const
- // {
- // // Perform Boolean logic here
- // }
- // };
-
+ /** \brief internal SafeBool base class
+ \internal
+ */
class SafeBoolBase
{
protected:
typedef void (SafeBoolBase::*bool_type)() const;
void this_type_does_not_support_comparisons() const;
+ // Just here to make them protected ...
+
SafeBoolBase();
SafeBoolBase(const SafeBoolBase&);
SafeBoolBase& operator=(const SafeBoolBase&);
~SafeBoolBase();
};
- template <typename T=void>
+ /** \brief Mixin class for safe boolean conversion support
+
+ This is a direct yet simplified copy of a safe bool solution
+ by Bjorn Karlsson from
+ http://www.artima.com/cppsource/safebool.html
+
+ This mixin provides the client class with safe boolean
+ testing. It is a safe replacement for <tt>operator
+ bool</tt>. <tt>operator bool</tt> is problematic since \c bool
+ is an integer type. This conversion operator makes the class
+ usable in any numeric context, which can be quite
+ dangerous. The <tt>operator void *</tt> solution is much
+ better in this respect but still allows two instances of any
+ class having such a <tt>void *</tt> conversion to be compared
+ for equality. This again will produce absolutely unexpected
+ results since it will not check wethere the objects are
+ identical, it will only check, that both return the same
+ boolean state.
+
+ This solutions solves all these problems by returning a
+ pointer-to-member which cannot be converted to any other
+ type. By providing explicit implementations of \c operator==
+ and \c operator!= which fail in an obvious way at compile
+ time, this hazard is removed.
+
+ To make a class boolean testable, just inherit from the mixin
+ and implement \c boolean_test:
+
+ \code
+ class Testable
+ : public SafeBool<Testable>
+ {
+ public:
+ bool boolean_test() const
+ {
+ // Perform Boolean logic here
+ }
+ };
+
+ Testable t = ...;
+
+ if (t) {
+ ...
+ }
+ \endcode
+
+ \todo Either rename intrusive_refcount to IntrusiveRefcount or
+ SafeBool to safe_bool (I tend to the latter ...)
+ */
+ template <typename T>
class SafeBool
: public SafeBoolBase
{
// Free Software Foundation, Inc.,
// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-// Definition of non-inline non-template functions
+/** \file
+ \brief TypeInfo non-inline non-template implementation */
#include "TypeInfo.hh"
//#include "TypeInfo.ih"
// Free Software Foundation, Inc.,
// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+/** \file
+ \brief TypeInfo public header */
+
#ifndef HH_TypeInfo_
#define HH_TypeInfo_ 1
namespace senf {
+ /** \brief Try to return readable type for given type_info
+
+ This function will try to return a demangled type name for the
+ given type_info object. If the demangling fails, the possibly
+ mangled name (type->name()) will be returned.
+
+ This function depends on the liberty library provided by the
+ linux binutils or binutils-dev packages. It also depends on an
+ internal header file. If the API should change, this header
+ file (which resides in impl/demangle.h) must be updated from
+ the binutils sources.
+ \param[in] type type_info object
+ \returns type name, possibly demangled
+ */
std::string prettyName(std::type_info const & type);
}
// Free Software Foundation, Inc.,
// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-// Definition of inline non-template functions
+/** \file
+ \brief intrusive_refcount inline non-template implementation */
//#include "intrusive_refcount.ih"
// Free Software Foundation, Inc.,
// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+/** \file
+ \brief intrusive_refcount public header */
+
#ifndef HH_intrusive_refcount_
#define HH_intrusive_refcount_ 1
namespace senf {
+ /** \brief Reference count mixin for intrusive_ptr
+
+ This class provides a simple internally managed refcount and supplies the <a
+ href="http://www.boost.org/libs/smart_ptr/intrusive_ptr.html">boost::intrusive_ptr</a>
+ required interface. To make a class compatible with \c boost::intrusive_ptr, just derive
+ publicly from intrusive_refcount.
- /** \brief
+ Two additional benifits of using intrusive_refcount are
+ \li The object can access it's own refcount
+ \li It is valid and safe to convert a plain object pointer to an intrusive_ptr at any time
+ (not only after new)
*/
class intrusive_refcount
: public boost::noncopyable
{
public:
- typedef unsigned refcount_t;
+ typedef unsigned refcount_t; ///< reference count type
virtual ~intrusive_refcount();
- refcount_t refcount();
- bool is_shared();
+ refcount_t refcount(); ///< current refcount
+ bool is_shared(); ///< return \c true if refcount() > 1
protected:
intrusive_refcount();
// Local Variables:
// mode: c++
// c-file-style: "senf"
+// fill-column: 100
// End:
// Free Software Foundation, Inc.,
// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+/** \file
+ \brief membind public header */
+
+/** \defgroup membind Bound Member Functions
+
+ The membind() family of function templates simplifies the creation
+ of simple bound member function pointers:
+
+ \code
+ struct Foo {
+ int test(int x);
+ };
+
+ Foo * foo = ...;
+ boost::function<int (int)> f = senf::membind(&Foo::test,foo);
+ int rv = f(1); // Calls foo->test(1)
+ \endcode
+
+ \idea Make the \a ob argument type an additional P template
+ parameter (using call_traits for the exact arg type? Probably
+ we'll get deduction problems then) . The only operation this
+ object musst suppoprt is ob->*fn. This would allow the use of
+ smart pointers. We should keep the T & version to still support
+ ob.*fn use.
+ */
+
#ifndef HH_membind_
#define HH_membind_ 1
namespace senf {
-
#define scOBTYPE T *
#include "Utils/impl/membind.hh"
#undef scOBTYPE
#include "Utils/impl/membind.hh"
#undef scOBTYPE
+#ifdef DOXYGEN
+
+ /// \addtogroup membind
+ /// @{
+
+ /** \brief Build bound member function object
+
+ membind() supports up to 9 function parameters (represented as
+ \a Args here). The \a ob argument can be either a pointer or a
+ reference to \a T
+ \param[in] fn member function pointer
+ \param[in] ob object instance to bind this pointer to
+ \returns Boost.Function object representing a bound call of \a
+ fn on \a ob
+ */
+ template <typename R, typename T, typename Args>
+ boost::function<R (Args)> membind(R (T::* fn)( Args ), T * ob);
+
+ /// @}
+
+#endif
+
}
///////////////////////////////hh.e////////////////////////////////////////
#!/usr/bin/perl -n
-if (/^\s*\\code\s*$/ .. /\\endcode/) {
- $i=length((/^(\s*)/)[0]) if /^\s*\\code\s*$/;
- print substr($_,$i);
+s/\s*$//;
+while (s/\t/' 'x(8-length($`)%8)/e) {}
+
+if (/^\s*\\code$/ .. /\\endcode/ && !/^$/) {
+ $i=length($1) if /^(\s*)\\code$/;
+ print substr($_,$i),"\n";
} else {
- print;
+ print $_,"\n";
}
dl.xref-bug, dl.xref-fix, dl.xref-todo, dl.xref-idea {
border: 1px solid #CC8888;
padding: 2px 3px;
- margin: 4px 0;
+ margin: 4px 8px 4px 2px;
background-color: #FFEEEE;
color: #666666;
font-size: 9px;