From: g0dil Date: Wed, 4 Aug 2010 14:53:30 +0000 (+0000) Subject: Utils: Add pimpl_tr (no documentation as of yet) X-Git-Url: http://g0dil.de/git?a=commitdiff_plain;h=7c7bdbf90e2ff5a93f6e92b3c2f3e62cba74ac24;p=senf.git Utils: Add pimpl_tr (no documentation as of yet) git-svn-id: https://svn.berlios.de/svnroot/repos/senf/trunk@1659 270642c3-0616-0410-b53a-bc976706d245 --- diff --git a/senf/Utils/pimpl_ptr.cti b/senf/Utils/pimpl_ptr.cti new file mode 100644 index 0000000..4ae797a --- /dev/null +++ b/senf/Utils/pimpl_ptr.cti @@ -0,0 +1,159 @@ +// $Id$ +// +// Copyright (C) 2010 +// 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 pimpl_ptr inline template implementation */ + +//#include "pimpl_ptr.ih" + +// Custom includes +#include "IgnoreValue.hh" + +#define prefix_ inline +///////////////////////////////cti.p/////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////// +// senf::pimpl_ptr + +template +prefix_ senf::pimpl_ptr::pimpl_ptr(T* pointee) + : p (pointee) +{ + // Is it fair to assume pointer assignment to be atomic on multi-threaded platforms ? + doCopy_ = &myCopyFn; + doDelete_ = &myDeleteFn; +} + +template +prefix_ senf::pimpl_ptr::pimpl_ptr(const pimpl_ptr & rhs) + : p (doCopy_(rhs.p)) +{} + +template +prefix_ senf::pimpl_ptr::~pimpl_ptr() + throw() +{ + doDelete_(p); +} + +template +prefix_ const T* senf::pimpl_ptr::get() + const throw() +{ + return p; +} + +template +prefix_ T* senf::pimpl_ptr::get() + throw() +{ + return p; +} + +template +prefix_ const T* senf::pimpl_ptr::operator->() + const throw() +{ + return p; +} + +template +prefix_ T* senf::pimpl_ptr::operator->() + throw() +{ + return p; +} + +template +prefix_ const T& senf::pimpl_ptr::operator*() + const throw() +{ + return *p; +} + +template +prefix_ T& senf::pimpl_ptr::operator*() + throw() +{ + return *p; +} + +template +prefix_ void senf::pimpl_ptr::swap(pimpl_ptr & with) + throw() +{ + std::swap(p, with.p); +} + +template +prefix_ senf::pimpl_ptr & +senf::pimpl_ptr::operator=(const pimpl_ptr & rhs) +{ + T* pp = doCopy_(rhs.p); + doDelete_(p); + p = pp; + return *this; +} + +template +prefix_ void senf::pimpl_ptr::myDeleteFn(T* p) +{ + return CloneAllocator::deallocate_clone(p); +} + +template +prefix_ T* senf::pimpl_ptr::myCopyFn(const T* p) +{ + return CloneAllocator::allocate_clone(*p); +} + +/////////////////////////////////////////////////////////////////////////// + +template +prefix_ void std::swap(senf::pimpl_ptr & lhs, + senf::pimpl_ptr & rhs) + throw() +{ + lhs.swap(rhs); +} + +template +typename senf::pimpl_ptr::Copier + senf::pimpl_ptr::doCopy_ (0); + +template +typename senf::pimpl_ptr::Deleter + senf::pimpl_ptr::doDelete_ (0); + +///////////////////////////////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/senf/Utils/pimpl_ptr.hh b/senf/Utils/pimpl_ptr.hh new file mode 100644 index 0000000..43ef8fb --- /dev/null +++ b/senf/Utils/pimpl_ptr.hh @@ -0,0 +1,96 @@ +// $Id$ +// +// Copyright (C) 2010 +// 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 pimpl_ptr public header */ + +#ifndef HH_SENF_senf_Utils_pimpl_ptr_ +#define HH_SENF_senf_Utils_pimpl_ptr_ 1 + +// Custom includes +#include +#include + +//#include "pimpl_ptr.mpp" +///////////////////////////////hh.p//////////////////////////////////////// + +namespace senf +{ + + template + class pimpl_ptr + { + typedef void (*Deleter)(T* p); + typedef T* (*Copier)(const T* p); + + public: + explicit pimpl_ptr(T* pointee); + pimpl_ptr(const pimpl_ptr & rhs); + ~pimpl_ptr() throw(); + + const T* get() const throw(); + T* get() throw(); + + const T* operator->() const throw(); + T* operator->() throw(); + + const T& operator*() const throw(); + T& operator*() throw(); + + void swap(pimpl_ptr& with) throw(); + + pimpl_ptr & operator=(const pimpl_ptr & rhs); + + private: + static Copier doCopy_; + static Deleter doDelete_; + T* p; + + static void myDeleteFn(T* p); + static T* myCopyFn(const T* p); + }; + +} + +namespace std +{ + template + void swap(senf::pimpl_ptr& lhs, senf::pimpl_ptr& rhs) + throw(); +} + +///////////////////////////////hh.e//////////////////////////////////////// +//#include "pimpl_ptr.cci" +//#include "pimpl_ptr.ct" +#include "pimpl_ptr.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/senf/Utils/pimpl_ptr.test.cc b/senf/Utils/pimpl_ptr.test.cc new file mode 100644 index 0000000..28acd08 --- /dev/null +++ b/senf/Utils/pimpl_ptr.test.cc @@ -0,0 +1,159 @@ +// $Id$ +// +// Copyright (C) 2010 +// 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 pimpl_ptr.test unit tests */ + +//#include "pimpl_ptr.test.hh" +//#include "pimpl_ptr.test.ih" + +// Custom includes +#include "pimpl_ptr.hh" + +#include +#include + +#define prefix_ +///////////////////////////////cc.p//////////////////////////////////////// + +namespace { + + struct PimplTest + { + struct Impl; + senf::pimpl_ptr impl_; + + explicit PimplTest(int v); + }; + + unsigned implConstruct (0); + unsigned implClone (0); + unsigned implDestroy (0); + + struct PimplTest::Impl + { + Impl(int v) : value (v) { ++ implConstruct; } + Impl(Impl const & other) : value (other.value) { ++ implClone; } + ~Impl() { ++ implDestroy; } + + int value; + }; + + prefix_ PimplTest::PimplTest(int v) + : impl_ (new Impl(v)) + {} + +} + +BOOST_AUTO_UNIT_TEST(pimpl_ptr) +{ + { + PimplTest ob1 (1); + PimplTest ob2 (ob1); + PimplTest ob3 (3); + + BOOST_CHECK_EQUAL( implConstruct, 2u ); + BOOST_CHECK_EQUAL( implClone, 1u ); + BOOST_CHECK_EQUAL( implDestroy, 0u ); + + BOOST_CHECK( ob1.impl_.get() != ob2.impl_.get() ); + BOOST_CHECK( ob2.impl_.get() != ob3.impl_.get() ); + BOOST_CHECK( ob3.impl_.get() != ob1.impl_.get() ); + + BOOST_CHECK_EQUAL( ob1.impl_->value, 1 ); + BOOST_CHECK_EQUAL( ob2.impl_->value, 1 ); + BOOST_CHECK_EQUAL( ob3.impl_->value, 3 ); + + ob3 = ob1; + + BOOST_CHECK_EQUAL( implConstruct, 2u ); + BOOST_CHECK_EQUAL( implClone, 2u ); + BOOST_CHECK_EQUAL( implDestroy, 1u ); + + BOOST_CHECK( ob3.impl_.get() != ob1.impl_.get() ); + + BOOST_CHECK_EQUAL( ob1.impl_->value, 1 ); + BOOST_CHECK_EQUAL( ob3.impl_->value, 1 ); + + ob3.impl_->value = 3; + + BOOST_CHECK_EQUAL( ob1.impl_->value, 1 ); + BOOST_CHECK_EQUAL( ob3.impl_->value, 3 ); + + struct PimplTest::Impl * p1 (ob1.impl_.get()); + struct PimplTest::Impl * p3 (ob3.impl_.get()); + + std::swap(ob3.impl_, ob1.impl_); + + BOOST_CHECK_EQUAL( implConstruct, 2u ); + BOOST_CHECK_EQUAL( implClone, 2u ); + BOOST_CHECK_EQUAL( implDestroy, 1u ); + + BOOST_CHECK_EQUAL( ob1.impl_->value, 3 ); + BOOST_CHECK_EQUAL( ob3.impl_->value, 1 ); + + BOOST_CHECK_EQUAL( ob1.impl_.get(), p3 ); + BOOST_CHECK_EQUAL( ob3.impl_.get(), p1 ); + } + + BOOST_CHECK_EQUAL( implConstruct, 2u ); + BOOST_CHECK_EQUAL( implClone, 2u ); + BOOST_CHECK_EQUAL( implDestroy, 4u ); +} + +#ifdef COMPILE_CHECK + +namespace { + + // We need this template arg to delay the constructor instantiation + // until within COMPILE_FAIL. Otherwise the CompileCheck builder has no + // way to associate the error message with the test ... + template + struct PimplTestIncomplete + { + struct Impl; + senf::pimpl_ptr impl_; + PimplTestIncomplete() : impl_ (0) {} + }; + +} + +COMPILE_FAIL(pimpl_ptr_incomplete) +{ + PimplTestIncomplete<> ob; +} + +#endif + +///////////////////////////////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: