/*////////////////////////////////////////////////////////////////////////////// // CMT Cosmic Muon Tomography project ////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// Copyright (c) 2014, Universita' degli Studi di Padova, INFN sez. di Padova All rights reserved Authors: Andrea Rigoni Garola < andrea.rigoni@pd.infn.it > ------------------------------------------------------------------ This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 3.0 of the License, or (at your option) any later version. This library 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library. //////////////////////////////////////////////////////////////////////////////*/ #ifndef U_CORE_VECTOR_H #define U_CORE_VECTOR_H #include #include #include #include #include #include #include #include namespace uLib { // MetaAllocator Implementation ... template class MetaAllocator { public: using value_type = T; using pointer = T *; using const_pointer = const T *; using reference = T &; using const_reference = const T &; using size_type = std::size_t; using difference_type = std::ptrdiff_t; template struct rebind { using other = MetaAllocator; }; MetaAllocator() noexcept = default; template constexpr MetaAllocator(const MetaAllocator &) noexcept {} T *allocate(std::size_t n) { if (n == 0) return nullptr; DataAllocator *da = new DataAllocator(n, false); T *ptr = da->GetRAMData(); std::lock_guard lock(GetMutex()); GetAllocationMap()[ptr] = da; return ptr; } void deallocate(T *p, std::size_t /*n*/) noexcept { if (!p) return; std::lock_guard lock(GetMutex()); auto &map = GetAllocationMap(); auto it = map.find(p); if (it != map.end()) { delete it->second; map.erase(it); } } static DataAllocator *GetDataAllocator(T *p) { if (!p) return nullptr; std::lock_guard lock(GetMutex()); auto &map = GetAllocationMap(); auto it = map.find(p); if (it != map.end()) { return it->second; } return nullptr; } private: static std::map *> &GetAllocationMap() { static std::map *> allocMap; return allocMap; } static std::mutex &GetMutex() { static std::mutex mtx; return mtx; } }; template bool operator==(const MetaAllocator &, const MetaAllocator &) { return true; } template bool operator!=(const MetaAllocator &, const MetaAllocator &) { return false; } // Vector Implemetation ... wraps std::vector template class Vector : public std::vector> { typedef std::vector> BaseClass; typedef MetaAllocator Allocator; public: typedef T TypeData; typedef __gnu_cxx::__normal_iterator Iterator; typedef __gnu_cxx::__normal_iterator ConstIterator; typedef CommaInitializer, T> VectorCommaInit; typedef typename BaseClass::iterator iterator; typedef typename BaseClass::const_iterator const_iterator; typedef typename BaseClass::size_type size_type; typedef typename BaseClass::reference reference; Vector(unsigned int size) : BaseClass(size) {} Vector(unsigned int size, T &value) : BaseClass(size, value) {} Vector() : BaseClass(0) {} Vector(std::initializer_list init) : BaseClass(init) {} inline VectorCommaInit operator<<(T scalar) { return VectorCommaInit(this, scalar); } void MoveToVRAM() { if (auto alloc = MetaAllocator::GetDataAllocator(BaseClass::data())) { alloc->MoveToVRAM(); } } void MoveToRAM() { if (auto alloc = MetaAllocator::GetDataAllocator(BaseClass::data())) { alloc->MoveToRAM(); } } T *GetVRAMData() { if (auto alloc = MetaAllocator::GetDataAllocator(BaseClass::data())) { return alloc->GetVRAMData(); } return nullptr; } const T *GetVRAMData() const { if (auto alloc = MetaAllocator::GetDataAllocator( const_cast(BaseClass::data()))) { return alloc->GetVRAMData(); } return nullptr; } inline void PrintSelf(std::ostream &o); // Overrides for auto-sync // T &operator[](size_t i) { this->MoveToRAM(); return BaseClass::operator[](i); } const T &operator[](size_t i) const { const_cast(this)->MoveToRAM(); return BaseClass::operator[](i); } T &at(size_t i) { this->MoveToRAM(); return BaseClass::at(i); } const T &at(size_t i) const { const_cast(this)->MoveToRAM(); return BaseClass::at(i); } T &front() { this->MoveToRAM(); return BaseClass::front(); } const T &front() const { const_cast(this)->MoveToRAM(); return BaseClass::front(); } T &back() { this->MoveToRAM(); return BaseClass::back(); } const T &back() const { const_cast(this)->MoveToRAM(); return BaseClass::back(); } T *data() noexcept { this->MoveToRAM(); return BaseClass::data(); } const T *data() const noexcept { const_cast(this)->MoveToRAM(); return BaseClass::data(); } Iterator begin() noexcept { this->MoveToRAM(); return BaseClass::begin(); } ConstIterator begin() const noexcept { const_cast(this)->MoveToRAM(); return BaseClass::begin(); } Iterator end() noexcept { this->MoveToRAM(); return BaseClass::end(); } ConstIterator end() const noexcept { const_cast(this)->MoveToRAM(); return BaseClass::end(); } auto rbegin() noexcept { this->MoveToRAM(); return BaseClass::rbegin(); } auto rbegin() const noexcept { const_cast(this)->MoveToRAM(); return BaseClass::rbegin(); } auto rend() noexcept { this->MoveToRAM(); return BaseClass::rend(); } auto rend() const noexcept { const_cast(this)->MoveToRAM(); return BaseClass::rend(); } void push_back(const T &x) { this->MoveToRAM(); BaseClass::push_back(x); } void push_back(T &&x) { this->MoveToRAM(); BaseClass::push_back(std::move(x)); } template reference emplace_back(Args &&...args) { this->MoveToRAM(); return BaseClass::emplace_back(std::forward(args)...); } void pop_back() { this->MoveToRAM(); BaseClass::pop_back(); } template iterator emplace(const_iterator pos, Args &&...args) { this->MoveToRAM(); return BaseClass::emplace(pos, std::forward(args)...); } iterator insert(const_iterator pos, const T &x) { this->MoveToRAM(); return BaseClass::insert(pos, x); } iterator insert(const_iterator pos, T &&x) { this->MoveToRAM(); return BaseClass::insert(pos, std::move(x)); } template iterator insert(const_iterator pos, InputIt first, InputIt last) { this->MoveToRAM(); return BaseClass::insert(pos, first, last); } iterator erase(const_iterator pos) { this->MoveToRAM(); return BaseClass::erase(pos); } iterator erase(const_iterator first, const_iterator last) { this->MoveToRAM(); return BaseClass::erase(first, last); } void resize(size_t n) { this->MoveToRAM(); BaseClass::resize(n); } void resize(size_t n, const T &x) { this->MoveToRAM(); BaseClass::resize(n, x); } void reserve(size_t n) { this->MoveToRAM(); BaseClass::reserve(n); } void clear() noexcept { this->MoveToRAM(); BaseClass::clear(); } template void assign(InputIt first, InputIt last) { this->MoveToRAM(); BaseClass::assign(first, last); } void assign(size_type count, const T &value) { this->MoveToRAM(); BaseClass::assign(count, value); } void remove_element(unsigned int index) { this->MoveToRAM(); std::swap(this->at(index), this->back()); this->pop_back(); } void remove_element(T &t) { this->MoveToRAM(); std::swap(t, this->back()); this->pop_back(); } }; template void Vector::PrintSelf(std::ostream &o) { o << " *** uLib Vector *** \n"; o << " n. of items = " << this->size() << "\n"; for (int i = 0; i < this->size(); ++i) o << (T)this->at(i) << " "; o << "\n"; } template std::ostream &operator<<(std::ostream &o, const Vector &v) { for (int i = 0; i < v.size(); ++i) o << (T)v.at(i) << " "; o << "\n"; return o; } template std::ofstream &operator<<(std::ofstream &o, const Vector &v) { for (int i = 0; i < v.size(); ++i) o << (T)v.at(i) << " "; return o; } template std::istream &operator>>(std::istream &is, Vector &v) { T value; while (is >> value) { if (is.fail()) v.push_back(0); else v.push_back(value); } return is; } // Smart pointer Vector Implementation // template class SmartVector : public SmartPointer> { typedef SmartPointer> Base; public: SmartVector() : Base(new Vector()) {} SmartVector(const SmartVector ©) : Base(copy) {} SmartVector(unsigned int size) : Base(new Vector((int)size)) {} virtual ~SmartVector() {} T &operator[](int p) { return Base::get()->at(p); } void swap_elements(unsigned int first, unsigned int second) { std::swap(Base::get()->at(first), Base::get()->at(second)); } void remove_element(unsigned int index) { std::swap(Base::get()->at(index), Base::get()->back()); Base::get()->pop_back(); } void remove_element(T &t) { std::swap(t, Base::get()->back()); Base::get()->pop_back(); } }; // ------ Utils ------------------------------------------------------------- // // RIFARE con iteratore ! template inline unsigned long VectorSplice(const _Tp &_it, const _Tp &_end, const float value, _CmpT _comp) { _Tp it = _it; _Tp end = _end - 1; for (; it != end;) { if (_comp(*it, value)) ++it; else if (_comp(*end, value)) std::swap(*it, *end--); else --end; } return it - _it; } } // namespace uLib #endif // VECTOR_H