#define prefix_
///////////////////////////////cc.p////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////
+// senf::FileBody
+
+prefix_ void senf::FileBody::close()
+{
+ if (!valid())
+ throwErrno(EBADF);
+ v_close();
+ fd_ = -1;
+}
+
+prefix_ void senf::FileBody::terminate()
+{
+ if (valid()) {
+ v_terminate();
+ fd_ = -1;
+ }
+}
+
+prefix_ void senf::FileBody::destroyClose()
+{
+ if (valid())
+ try {
+ close();
+ }
+ catch (...) {
+ terminate();
+ }
+}
+
prefix_ void senf::FileBody::v_close()
{
if (::close(fd_) != 0)
: fd_(fd)
{}
-prefix_ senf::FileBody::~FileBody()
-{
- if (valid())
- try {
- close();
- }
- catch (...) {
- terminate();
- }
-}
-
-prefix_ void senf::FileBody::close()
-{
- if (!valid())
- throwErrno(EBADF);
- v_close();
- fd_ = -1;
-}
-
-prefix_ void senf::FileBody::terminate()
-{
- if (valid()) {
- v_terminate();
- fd_ = -1;
- }
-}
-
prefix_ senf::FileHandle senf::FileBody::handle()
{
return FileHandle(ptr(this));
: body_(0)
{}
+prefix_ senf::FileHandle::~FileHandle()
+{
+ if (body_ && ! body().is_shared())
+ body().destroyClose();
+}
+
prefix_ senf::FileHandle::FileHandle(std::auto_ptr<FileBody> body)
: body_(body.release())
{}
///@{
FileHandle();
+ ~FileHandle();
// my default constructor
// default copy constructor
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 copy
// no conversion constructors
void close();
void terminate();
+ void destroyClose();
bool readable() const;
void waitReadable() const;
#define prefix_
///////////////////////////////cc.p////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////
+// senf::SocketBody
+
+prefix_ void senf::SocketBody::state(SocketStateMap & map, unsigned lod)
+{
+ map["file.handle"] << fd();
+ map["file.refcount"] << refcount();
+ map["socket.server"] << isServer();
+ map["socket.protocol"] << v_protocolName();
+ map["socket.protocol.policy"] << prettyName(typeid(protocol().policy()));
+ protocol().state(map,lod);
+}
+
prefix_ void senf::SocketBody::v_close()
{
protocol().close();
return protocol().eof();
}
-prefix_ void senf::SocketBody::state(SocketStateMap & map, unsigned lod)
-{
- map["file.handle"] << fd();
- map["file.refcount"] << refcount();
- map["socket.server"] << isServer();
- map["socket.protocol"] << v_protocolName();
- map["socket.protocol.policy"] << prettyName(typeid(protocol().policy()));
- protocol().state(map,lod);
-}
-
///////////////////////////////////////////////////////////////////////////
// senf::detail::StateMapOrdering
MySocketHandle()
: senf::SocketHandle<senf::test::SomeProtocol::Policy>(
std::auto_ptr<senf::SocketBody>(
- new senf::ProtocolSocketBody<senf::test::SomeProtocol>(false)))
+ new senf::ProtocolSocketBody<senf::test::SomeProtocol>(false, 0)))
{}
};
>::policy OtherSocketPolicy;
typedef senf::SocketHandle<OtherSocketPolicy> OtherSocketHandle;
- MySocketHandle myh;
- OtherSocketHandle osh (myh);
- osh = myh;
-
- typedef senf::SocketHandle<senf::test::SomeProtocol::Policy> SomeSocketHandle;
- SomeSocketHandle ssh = senf::static_socket_cast<SomeSocketHandle>(osh);
-
- BOOST_CHECK_NO_THROW( senf::dynamic_socket_cast<SomeSocketHandle>(osh) );
-
- typedef senf::SocketHandle< senf::MakeSocketPolicy<
- OtherSocketPolicy,
- senf::NoAddressingPolicy
- >::policy> SomeOtherSocketHandle;
-
- BOOST_CHECK_THROW( senf::dynamic_socket_cast<SomeOtherSocketHandle>(osh),
- std::bad_cast );
- BOOST_CHECK_THROW( senf::dynamic_socket_cast<SomeSocketHandle>(
- senf::FileHandle(FDHandle())),
- std::bad_cast );
-
- BOOST_CHECK_EQUAL( myh.dumpState(),
- "file.handle: -1\n"
- "file.refcount: 3\n"
- "handle: senf::SocketHandle<senf::SocketPolicy<senf::test::SomeAddressingPolicy, senf::test::SomeFramingPolicy, senf::test::SomeCommunicationPolicy, senf::test::SomeReadPolicy, senf::test::SomeWritePolicy> >\n"
- "socket.protocol: senf::test::SomeProtocol\n"
- "socket.protocol.policy: senf::SocketPolicy<senf::test::SomeAddressingPolicy, senf::test::SomeFramingPolicy, senf::test::SomeCommunicationPolicy, senf::test::SomeReadPolicy, senf::test::SomeWritePolicy>\n"
- "socket.server: false\n" );
+ {
+ MySocketHandle myh;
+ OtherSocketHandle osh (myh);
+ osh = myh;
+
+ typedef senf::SocketHandle<senf::test::SomeProtocol::Policy> SomeSocketHandle;
+ SomeSocketHandle ssh = senf::static_socket_cast<SomeSocketHandle>(osh);
+
+ BOOST_CHECK_NO_THROW( senf::dynamic_socket_cast<SomeSocketHandle>(osh) );
+
+ typedef senf::SocketHandle< senf::MakeSocketPolicy<
+ OtherSocketPolicy,
+ senf::NoAddressingPolicy
+ >::policy> SomeOtherSocketHandle;
+
+ BOOST_CHECK_THROW( senf::dynamic_socket_cast<SomeOtherSocketHandle>(osh),
+ std::bad_cast );
+ BOOST_CHECK_THROW( senf::dynamic_socket_cast<SomeSocketHandle>(
+ senf::FileHandle(FDHandle())),
+ std::bad_cast );
+
+ BOOST_CHECK_EQUAL( myh.dumpState(),
+ "file.handle: 0\n"
+ "file.refcount: 3\n"
+ "handle: senf::SocketHandle<senf::SocketPolicy<senf::test::SomeAddressingPolicy, senf::test::SomeFramingPolicy, senf::test::SomeCommunicationPolicy, senf::test::SomeReadPolicy, senf::test::SomeWritePolicy> >\n"
+ "socket.protocol: senf::test::SomeProtocol\n"
+ "socket.protocol.policy: senf::SocketPolicy<senf::test::SomeAddressingPolicy, senf::test::SomeFramingPolicy, senf::test::SomeCommunicationPolicy, senf::test::SomeReadPolicy, senf::test::SomeWritePolicy>\n"
+ "socket.server: false\n" );
+ }
+
+ // Ensure, the destructor is called and calls the correct close() implementation
+ BOOST_CHECK_EQUAL( senf::test::SomeProtocol::closeCount(), 1u );
}
///////////////////////////////cc.e////////////////////////////////////////
//#include "SocketProtocol.mpp"
#define prefix_
///////////////////////////////cc.p////////////////////////////////////////
+
prefix_ void senf::SocketProtocol::close()
const
{
virtual void close() const; ///< Close socket
/**< This override will automatically \c shutdown() the
socket whenever it is closed.
- \throws senf::SystemException */
+ \throws senf::SystemException
+ \fixme Move into (at least) BSDSOcketProtocol */
virtual void terminate() const; ///< Forcibly close socket
/**< This override will automatically \c shutdown() the
disable SO_LINGER to ensure, that v_terminate will not
block. Like the overriden method, this member will ignore
failures and will never throw. It is therefore safe to be
- called from a destructor. */
+ called from a destructor.
+ \fixme Move into (at least) BSDSocketProtocol */
virtual void state(SocketStateMap & map, unsigned lod) const;
///< Return socket state information
#include "SocketProtocol.hh"
#include "SocketPolicy.test.hh"
#include "ProtocolClientSocketHandle.hh"
+#include "../Utils/Logger/SenfLog.hh"
//#include "SocketProtocol.test.mpp"
///////////////////////////////hh.p////////////////////////////////////////
public:
~SomeProtocol() {}
- void init_client() const {}
- void init_server() const {}
+ void init_client() const { fd(0); }
+ void init_server() const { fd(0); }
unsigned available() const
{ return Policy::ReadPolicy::TEST_SIZE; }
bool eof() const
{ return false; }
+
+ virtual void close() const {
+ SENF_LOG(( "Closing socket ..." ));
+ closeCount(1);
+ }
+
+ static unsigned closeCount(unsigned inc=0) {
+ static unsigned counter (0);
+ counter += inc;
+ return counter;
+ }
};
}}
scons all_docs
scons linklint
scons fixlinks
- scons $(destdir)/usr/include $(destdir)/usr/share/doc $(SCONS_OPTIONS) \
+ scons $(destdir)/usr/include $(destdir)/usr/share/doc \
PREFIX='$(destdir)/usr' \
DOCINSTALLDIR='$$PREFIX/share/doc/libsenf-doc/html' \
INCLUDEINSTALLDIR='$$PREFIX/include/senf'
# 1. Scanning the Doxyfile's
#
# The doxygen builder scans all documentation source files which have
-# the text 'doxyfile' in any case within them. It understands @INCLUDE
-# directives and will find all the dependencies of the documentation:
+# the text 'doxyfile' in any case in their name. It understands
+# @INCLUDE directives and will find all the dependencies of the
+# documentation:
#
# * All the source files as selected by INPUT, INPUT_PATTERN,
# RECURSIVE and so on.
#
# * 'doclib/dot' calls the real dot binary. If the resulting image is
# more than 800 pixels wide, dot is called again, this time using
-# the oposite rang direction (top-bottom vs. left-right). Then the
-# image with the smaller width is selected and returned.
+# the oposite rank direction (top-bottom vs. left-right). The image
+# with the smaller width is selected and returned.
#
# * after doxygen is finished, the list of referenced tag-files is
# checked. For each tag file the directory is found, where the
# documentation is generated (by scanning the Doxyfile which is
# repsonsible for building the tag file). For every tag file, the
-# correct 'insstalldox' command is generated
+# correct 'installdox' command is generated.
#
# * The stamp files are created
#
# namespace.
#
# * All html files are processed by 'doclib/html-munge.xsl'. However,
-# since the documentation generated by doxygen is completely broken
-# we need to preprocess the html files with a simple 'sed' script
-# and 'tidy' before 'xsltproc' even accepts the html code.
+# since the documentation generated by doxygen is completely invalid
+# html we need to preprocess the html files with a simple 'sed'
+# script and 'tidy' before 'xsltproc' even accepts the html code.
#
# * We use the generated xml output of doxygen to generate an XML
# fragment for the global cross reference. This fragment is