3
0
mirror of https://github.com/triqs/dft_tools synced 2024-12-26 14:23:38 +01:00
dft_tools/triqs/arrays/storages/shared_block.hpp
Olivier Parcollet fc2a620eae arrays: new ref counting and weak views
- improve the mem_block and shared_block.
- the reference counting is now done in the mem_block and shared_block, removing the need of shared_ptr.

- speed tests shows that shared_ptr is very slow (due to thread safety?)
the new version is much better, though not perfect.

- Hence introducing weak views.

- also :
-- clean the guard mechanism for python (to allow returning from python without any python ref left).
-- clean code, add documentation for mem_block
-- remove nan init, which was not working, and corresponding test
-- serialisation of view still unchanged (need to forbid serialization of view ??).

- tests ok, incl. valgrind tests.
2013-07-23 08:13:44 +02:00

111 lines
4.1 KiB
C++

/*******************************************************************************
*
* TRIQS: a Toolbox for Research in Interacting Quantum Systems
*
* Copyright (C) 2011 by O. Parcollet
*
* TRIQS 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 3 of the License, or (at your option) any later
* version.
*
* TRIQS 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
* TRIQS. If not, see <http://www.gnu.org/licenses/>.
*
******************************************************************************/
#ifndef TRIQS_STORAGE_SHARED_POINTER_H
#define TRIQS_STORAGE_SHARED_POINTER_H
#include <string.h>
#include <limits>
#include "./mem_block.hpp"
namespace triqs { namespace arrays { namespace storages {
/*
* This is a shared memory block, similar to a shared_ptr<mem_block>
* but a lot faster and adapted to model the Storage concept.
*/
template<typename ValueType, bool Weak=false>
class shared_block {
static_assert( !std::is_const<ValueType>::value, "oops : internal error : shared_block should never be instanciated with a const");
mem_block<ValueType> * sptr;
ValueType * restrict data_; // for optimization on some compilers. ?? obsolete : to be removed ?
size_t s;
void construct_delegate(size_t size) {
s = size;
if (size ==0) { sptr = nullptr; data_=nullptr; }
else { sptr = new mem_block<ValueType>(size); data_ = sptr->p;}
}
public:
typedef ValueType value_type;
static constexpr bool is_weak = Weak;
/// Construct a new block of memory of given size
explicit shared_block(size_t size, Tag::no_init) { construct_delegate(size); }
explicit shared_block(size_t size, Tag::default_init) {// C++11 : delegate to previous constructor when gcc 4.6 support is out.
construct_delegate(size);
const auto s = this->size(); for (size_t u=0; u<s; ++u) data_[u] = ValueType();
}
#ifdef TRIQS_WITH_PYTHON_SUPPORT
explicit shared_block(PyObject * arr, bool weak): sptr(new mem_block<ValueType>(arr,weak)) { data_ = sptr->p; s= sptr->size(); }
#endif
explicit shared_block() { sptr =nullptr; data_=nullptr; s=0; }
shared_block(shared_block const & X) noexcept { sptr =X.sptr; data_ = X.data_; s= X.s; if (sptr) inc_ref<Weak>(sptr); }
shared_block(shared_block<ValueType,!Weak> const & X) noexcept { sptr =X.sptr; data_ = X.data_; s= X.s; if (sptr) inc_ref<Weak>(sptr); }
shared_block(shared_block && X) noexcept { sptr =X.sptr; data_ = X.data_; s= X.s; X.sptr=nullptr; }
~shared_block() { if (sptr) dec_ref<Weak>(sptr); }
shared_block & operator=(shared_block const & X) noexcept {
if (sptr) dec_ref<Weak>(sptr); sptr =X.sptr; if (sptr) inc_ref<Weak>(sptr);
data_ = X.data_; s = X.s;
return *this;
}
shared_block & operator=(shared_block && X) noexcept {
if (sptr) dec_ref<Weak>(sptr); sptr =X.sptr; X.sptr=nullptr;
data_ = X.data_; s = X.s;
return *this;
}
/// True copy of the data
shared_block clone() const {
shared_block res;
if (!empty()) { res.sptr = new mem_block<ValueType> (*sptr); res.data_ = res.sptr->p; res.s = s;}
return res;
}
value_type & operator[](size_t i) const { return data_[i];}
bool empty() const {return (sptr==nullptr);}
size_t size() const {return s;}
//size_t size() const {return (empty () ? 0 : sptr->size());}
#ifdef TRIQS_WITH_PYTHON_SUPPORT
PyObject * new_python_ref() const {return sptr->new_python_ref();}
#endif
private:
friend class shared_block<ValueType,!Weak>;
friend class boost::serialization::access;
template<class Archive> void serialize(Archive & ar, const unsigned int version) {
ar & boost::serialization::make_nvp("ptr",sptr); data_ = (sptr ? sptr->p : nullptr); s = (sptr ? sptr->size() : 0);
}
};
}}}//namespace
#endif