STK++ 0.9.13
STK_MemAllocator.h
Go to the documentation of this file.
1/*--------------------------------------------------------------------*/
2/* Copyright (C) 2004-2016 Serge Iovleff, Université Lille 1, Inria
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU Lesser General Public License as
6 published by the Free Software Foundation; either version 2 of the
7 License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU Lesser General Public License for more details.
13
14 You should have received a copy of the GNU Lesser General Public
15 License along with this program; if not, write to the
16 Free Software Foundation, Inc.,
17 59 Temple Place,
18 Suite 330,
19 Boston, MA 02111-1307
20 USA
21
22 Contact : S..._Dot_I..._At_stkpp_Dot_org (see copyright for ...)
23*/
24
25/*
26 * Project: stkpp::Arrays
27 * Purpose: Define the Base Interface for the Array classes.
28 * Author: Serge Iovleff, S..._Dot_I..._At_stkpp_Dot_org (see copyright for ...)
29 *
30 **/
31
36#ifndef STK_MEMALLOCATOR_H
37#define STK_MEMALLOCATOR_H
38
39#include <cstring>
40#include "../STK_IContainerRef.h"
47
48namespace STK
49{
50
51namespace hidden
52{
53
58template<typename Type_, int Size_> struct MemHandler
59{
62 static Type_* free(Type_* p_data, AllocatorRange const& range) { return p_data;}
66 static Type_* malloc(Type_* p_data, AllocatorRange const& range)
67 {
68 if (!p_data)
69 {
70 if(range.size()>0)
71 {
72 p_data = new Type_[range.size()];
73 p_data -= range.begin();
74 }
75 }
76 return p_data;
77 }
79 template<int OtherSize>
80 static Type_* realloc( Type_* p_data, AllocatorRange const& range, TRange<OtherSize> const& I)
81 {
82 // fixed size, just shift
83 return p_data + range.begin() - I.begin();
84 }
85};
86
90template<class Type_> struct MemHandler<Type_, UnknownSize>
91{
94 static Type_* free(Type_* p_data, AllocatorRange const& range)
95 {
96 // if there is elts
97 if (p_data)
98 {
99 p_data+=range.begin();
100 delete [] p_data; // erase
101 p_data = 0;
102 }
103 return p_data;
104 }
106 static Type_* malloc(Type_* p_data, AllocatorRange const& range)
107 {
108 if(range.size()>0)
109 {
110 p_data = new Type_[range.size()];
111 p_data -= range.begin();
112 }
113 else
114 { p_data = 0;}
115 return p_data;
116 }
118 template<int OtherSize>
119 static Type_* realloc( Type_* p_data, AllocatorRange const& range, TRange<OtherSize> const& I)
120 {
121 Type_* p = 0;
122 p = malloc(p, I);
123 Range r = inf(range, I);
124 for (int i = r.begin(); i<r.end(); ++i) { p[i] = p_data[i];}
125 p_data = free(p_data, range);
126 return p;
127 }
128};
129
133template<int, class Type_> struct MemChooser;
134
139template<class Type_> struct MemChooser<1, Type_>
140{
141 static Type_* memcpy(Type_* p, Type_* q, size_t size)
142 { return static_cast<Type_*>(std::memcpy( p , q, sizeof(Type_)*size));}
143
144 static Type_* memmove(Type_* p, Type_* q, size_t size)
145 { return static_cast<Type_*>(std::memmove( p, q, sizeof(Type_)*size));}
146};
147
150template<class Type_> struct MemChooser<0, Type_>
151{
152 static Type_* memcpy(Type_* p, Type_* q, size_t size)
153 {
154 for (size_t k=0; k<size; k++) { p[k] = q[k];}
155 return p;
156 }
157 static Type_* memmove(Type_* p, Type_* q, size_t size)
158 {
159 if (size == 0) return p;
160 if (p<q) { for (size_t k=0; k<size; k++) { p[k] = q[k];}}
161 else { for (size_t k=size-1; k==0; --k) { p[k] = q[k];}}
162 return p;
163 }
164};
165
166} // namespace hidden
167
179template<typename Type_, int Size_>
181{
185
186 typedef Type_ Type;
188
192
202 MemAllocator( AllocatorRange const& I, Type const& value);
207 MemAllocator( MemAllocator const& T, bool ref = false);
212 template<int OtherSize_>
218 template<int OtherSize_>
225 MemAllocator( Type* const& q, Range const& I, bool ref);
232 MemAllocator( Type* const& q, int size, bool ref);
235
237 inline AllocatorRange const& range() const { return range_;}
239 inline int begin() const { return range_.begin();}
241 inline int end() const { return range_.end();}
243 inline int size() const { return range_.size();}
244
246 inline Type* const& p_data() const { return p_data_;}
247
251 void setValue(TypeConst value)
252 {
253 for(int pos=begin(); pos < end(); ++pos)
254 { p_data_[pos] = value;}
255 }
259 inline void setValue(int pos, TypeConst value)
260 {
261#ifdef STK_BOUNDS_CHECK
262 if (pos < begin())
264 if (pos >= end())
266#endif
267 p_data_[pos] = value;
268 }
269
273 inline TypeConst elt( int pos) const
274 {
275#ifdef STK_BOUNDS_CHECK
276 if (pos < begin())
278 if (pos >= end())
280#endif
281 return p_data_[pos];
282 }
286 inline TypeConst operator[](int i) const { return elt(i);}
290 inline Type& elt(int pos) { return p_data_[pos];}
294 inline Type& operator[](int i) { return elt(i);}
298 inline void swap(int pos1, int pos2)
299 {
300#ifdef STK_BOUNDS_CHECK
305#endif
306 std::swap(p_data_[pos1], p_data_[pos2]);
307 }
308
312 template<int OtherSize>
324 template<int OtherSize>
327 void free();
328
332 template<int OtherSize_, int RangeSize_>
337 template< int RangeSize_>
338 void memmove(int pos, TRange<RangeSize_> const& range);
342 void memmove(int pos, int begin, int size);
343
358 template<int OtherSize_>
360
374 MemAllocator& shift(int first);
382 void setPtr( Type* p_data, Range const& range, bool ref)
384
385 protected:
388
389 private:
395 void shiftPtr( int inc)
396 {
397 if (p_data_) { p_data_ -= inc;}
398 range_.inc(inc);
399 }
408};
409
410/* Default constructor. */
411template<typename Type, int Size_>
413 , p_data_(0)
414 , range_()
415{ malloc(range_);}
416/* constructor with specified Range
417 * @param I range of the data
418 **/
419template<typename Type, int Size_>
423
424/* constructor with specified Range and value
425 * @param I range of the data
426 **/
427template<typename Type, int Size_>
429 : IContainerRef(false), p_data_(0), range_(I)
430{ malloc(I);
431 assign(I, value);
432}
433
434/* Copy constructor. We don't know, how the user classes want to copy the
435 * data if this is not a reference.
436 * @param T the array to copy or reference
437 * @param ref is this a wrapper of T ?
438 * @note if ref is @c false, the derived class is responsible of the data copy
439 **/
440template<typename Type, int Size_>
442 : IContainerRef(ref)
443 , p_data_(ref ? T.p_data(): 0)
444 , range_(T.range())
445{
446 if (!ref)
447 {
448 malloc(range());
449 memcpy(begin(), T, range());
450 }
451}
452
453/* Copy constructor. We don't know, how the user classes want to copy the
454 * data if this is not a reference.
455 * @param T the array to copy or reference
456 * @param ref is this a wrapper of T ?
457 * @note if ref is @c false, the derived class is responsible of the data copy
458 **/
459template<typename Type, int Size_>
460template<int OtherSize_>
462 : IContainerRef(ref)
463 , p_data_(ref ? T.p_data(): 0)
464 , range_(T.range())
465{
466 if (!ref)
467 {
468 malloc(range());
469 memcpy(begin(), T, range());
470 }
471}
472/* constructor by reference.
473 * @param T,I the allocator and range to reference
474 **/
475template<typename Type, int Size_>
476template<int OtherSize_>
479 , p_data_(ref ? T.p_data() : 0)
480 , range_(I)
481{
482 if (!ref)
483 {
484 malloc(I);
485 for(int i=I.begin(); i< I.end(); ++i)
486 { p_data_[i] = T.elt(i);}
487 }
488}
489
490/* @brief Wrapper or copy constructor.
491 * @param q,I ptr and range of the data to wrap
492 * @param ref is this a wrapper ? If @c true data will not be freed when this
493 * object is released
494 **/
495template<typename Type, int Size_>
497 : IContainerRef(ref), p_data_(q), range_(I)
498{ /* derived class have to delete data if ref==false */}
499
500/* Wrapper or copy constructor: second form. This constructor assumes the
501 * data as a C-like array. Thus first index is 0.
502 * @param q, size ptr and size of the data to wrap
503 * @param ref is this a wrapper ? If @c true data will not be freed when this
504 * object is released
505 **/
506template<typename Type, int Size_>
507MemAllocator<Type,Size_>::MemAllocator( Type* const& q, int size, bool ref)
508 : IContainerRef(ref), p_data_(q), range_(AllocatorRange(0,size))
509{ /* derived class have to copy the data if ref==false */}
510
511/* destructor. */
512template<typename Type, int Size_>
515
516/* exchange this with T.
517 * @param T the container to exchange with T
518 **/
519template<typename Type, int Size_>
521{
522 std::swap(p_data_, T.p_data_);
523 std::swap(range_, T.range_);
525}
526/* @brief copy the Allocator T by value.
527 * The memory is free and the Allocator T is physically copied in this.
528 * @param T the allocator to copy by value
529 * @return a copy of this
530 **/
531template<typename Type, int Size_>
533{
534 // allocate memory if necessary
535 malloc(T.range_);
536 memcpy(begin(), T, range());
537 return *this;
538}
539
540/* @brief a value.*/
541template<typename Type, int Size_>
542template<int OtherSize_>
544{
545 for (int pos= I.begin(); pos < I.end(); ++pos) { p_data_[pos] = value;}
546 return *this;
547}
548/* @brief move the Allocator T to this.
549 * The memory is free and T become a reference of this. This method allow
550 * to steal the data of T without physical copy.
551 *
552 * @return this object.
553 * @note the data member ref_ is mutable so that T can be passed as a
554 * constant reference.
555 * @param T the allocator to move to this
556 **/
557template<typename Type, int Size_>
559{
560 if (this == &T) return *this;
561 forcedFree();
562 setPtr(T.p_data_, T.range_, T.isRef());
563 T.setRef(true); // T become a reference of the data it own
564 return *this;
565}
566template<typename Type, int Size_>
568{
569 // check if there is something to do
570 if (first == begin()) return *this;
571 // check for reference
572 if (isRef())
574 // translate data
575 shiftPtr(first - begin());
576 return *this;
577}
578
579template<typename Type, int Size_>
580template<int OtherSize>
582{
583 // there is no necessity to allocate if data is already allocated, range_
584 // is the same and the data is not owned by an other allocator
585 if ((range_ == I)&&(p_data_)&&(!isRef())) return;
586 // allocate memory
587 try
588 {
589 // free any existing data and allocate it again (do nothing for fixed size allocators)
590 p_data_ = MemHandler::free(p_data_, range_);
591 p_data_ = MemHandler::malloc(p_data_, I);
592 setPtr(p_data_, I, false);
593 }
594 catch (std::bad_alloc const& error)
595 {
596 setPtr(0, AllocatorRange(), false);
598 }
599}
600
601template<typename Type, int Size_>
602template<int OtherSize>
604{
605 // there is no necessity to allocate if data is already allocated, range_
606 // is the same and the data is not owned by an other allocator
607 if ((range_ == I)&&(p_data_)&&(!isRef())) return;
608
609 try
610 {
611 // allocate memory and copy data in the same range
612 Type* p = MemHandler::malloc(p_data_, I);
613 // copy data in common range
614 Range r = inf(range_, I);
615 if (r.size()>0)
616 { MemChooser::memcpy(p+r.begin(), p_data_+r.begin(), r.size()); }
617// for (int i = r.begin(); i<r.end(); ++i) { p[i] = p_data_[i];}
618 p_data_ = MemHandler::free(p_data_, range_);
619 setPtr(p, I, false);
620 }
621 catch (std::bad_alloc const& error)
623}
624/* function for main ptr memory deallocation. */
625template<typename Type, int Size_>
627{
628 // nothing to do for reference
629 if (isRef()) return;
630 p_data_ = MemHandler::free(p_data_, range_);
631 // if there is no elements range_ is set to default
632 if (!p_data_) { range_ = AllocatorRange();}
633}
634
635template<typename Type, int Size_>
636template<int OtherSize_, int RangeSize_>
638{
639 if (range.size() <= 0) return;
640#ifdef STK_BOUNDS_CHECK
641 if (pos < begin()) { STKOUT_OF_RANGE_1ARG(MemAllocator::memcpy,pos,begin() > pos);}
642 if (pos >= end()) { STKOUT_OF_RANGE_1ARG(MemAllocator::memcpy,pos,end() <= pos);}
643 if (!T.range().isContaining(range))
644 { STKOUT_OF_RANGE_1ARG(MemAllocator::memcopy,range,range not in T.range());}
645#endif
646 MemChooser::memcpy(p_data_+pos, T.p_data()+range.begin(), range.size());
647}
648
649template<typename Type, int Size_>
650void MemAllocator<Type,Size_>::memmove(int pos, int start, int size)
651{
652 if ((size <= 0)||(start == pos)) return;
653#ifdef STK_BOUNDS_CHECK
654 if (pos < begin())
656 if (pos >= end())
658 if (!range_.isContaining(Range(start,size)))
659 { STKOUT_OF_RANGE_2ARG(MemAllocator::memmove,start,size,Range(start,size) not in range_);}
660#endif
661 MemChooser::memmove( p_data_+pos, p_data_+ start, size);
662}
663
664template<typename Type, int Size_>
665template< int RangeSize_>
667{
668 if ((range.size() <= 0)||(range.begin() == pos)) return;
669#ifdef STK_BOUNDS_CHECK
670 if (pos < begin())
672 if (pos >= end())
674 if (!range_.isContaining(range))
675 { STKOUT_OF_RANGE_1ARG(MemAllocator::memmove,range,range not in range_);}
676#endif
677 MemChooser::memmove( p_data_+pos, p_data_+range.begin(), range.size());
678}
679
680
681} // namespace STK
682
683#endif /* STK_MEMALLOCATOR_H */
In this file we define for the template class Arithmetic for handling the greatest,...
In this file we define the standard Exceptions of the STK++ library.
In this file we define the Runtime Type Identification (RTTI) classes.
In this file we define the macro and utilities function used throughout the stk++ library.
#define STKOUT_OF_RANGE_1ARG(Where, Arg, Error)
Definition STK_Macros.h:93
#define STKRUNTIME_ERROR_1ARG(Where, Arg, Error)
Definition STK_Macros.h:129
#define STKOUT_OF_RANGE_2ARG(Where, Arg1, Arg2, Error)
Definition STK_Macros.h:102
In this file we define the class Range, a range of Index denoting a sub-vector region.
In this file we define the fundamental type String.
String const & error() const
get the last error message.
Definition STK_IRunner.h:82
The MultidimRegression class allows to regress a multidimensional output variable among a multivariat...
int begin() const
get the first index of the TRange.
Definition STK_Range.h:93
Index sub-vector region: Specialization when the size is unknown.
Definition STK_Range.h:265
int end() const
get the ending index of the TRange.
Definition STK_Range.h:299
int size() const
get the size of the TRange (the number of elements).
Definition STK_Range.h:303
Range inf(TRange< SizeI_ > const &I, TRange< SizeJ_ > const &J)
compute inf(I,J).
Definition STK_Range.h:477
const int UnknownSize
This value means that an integer is not known at compile-time, and that instead the value is stored i...
The namespace STK is the main domain space of the Statistical ToolKit project.
TRange< UnknownSize > Range
Definition STK_Range.h:59
template base class for all Allocator classes.
void setValue(int pos, TypeConst value)
This method allows to set a value to the position pos.
~MemAllocator()
destructor.
MemAllocator(Type *const &q, Range const &I, bool ref)
Wrapper or copy constructor.
void memmove(int pos, TRange< RangeSize_ > const &range)
function moving a part of the allocator.
AllocatorRange range_
Range of the data.
Type & elt(int pos)
Get the element number pos.
hidden::RemoveConst< Type >::Type const & TypeConst
Type *const & p_data() const
Get constant pointer on data.
void free()
function for main ptr memory deallocation.
hidden::MemChooser< isNumeric_, Type_ > MemChooser
void exchange(MemAllocator &T)
exchange this with T.
MemAllocator(AllocatorRange const &I, Type const &value)
constructor with specified Range and initial value
void forcedFree()
function for main ptr memory deallocation.
void setRef(bool ref) const
Modify the container : can become a reference or the owner of the data.
void memcpy(int pos, MemAllocator< Type, OtherSize_ > const &T, TRange< RangeSize_ > const &range)
function copying a part of allocator T in this.
void malloc(TRange< OtherSize > const &I)
main method for memory allocation.
void memmove(int pos, int begin, int size)
function moving a part of the allocator.
void setPtr(Type *p_data, Range const &range, bool ref)
Set address and range of allocated data.
MemAllocator & shift(int first)
shift the first index of the data to first.
void realloc(TRange< OtherSize > const &I)
function for main ptr memory reallocation.
AllocatorRange const & range() const
MemAllocator(AllocatorRange const &I)
constructor with specified Range
void swap(int pos1, int pos2)
swap two elements of the Allocator.
TRange< Size_ > AllocatorRange
Type & operator[](int i)
MemAllocator()
Default constructor.
MemAllocator(MemAllocator< Type, OtherSize_ > const &T, AllocatorRange const &I, bool ref=true)
Copy constructor.
void setValue(TypeConst value)
This method allows to set a value to the allocator.
MemAllocator(MemAllocator const &T, bool ref=false)
Copy constructor.
MemAllocator & assign(TRange< OtherSize_ > const &I, Type const &value)
assign a value to allocator.
TypeConst elt(int pos) const
Get the const element number pos.
MemAllocator & assign(MemAllocator const &T)
copy the Allocator T by value.
MemAllocator & move(MemAllocator const &T)
move the Allocator T to this.
MemAllocator(Type *const &q, int size, bool ref)
Wrapper or copy constructor: second form.
hidden::MemHandler< Type_, Size_ > MemHandler
Type * p_data_
Main pointer on the data.
void shiftPtr(int inc)
move main pointer on data
MemAllocator(MemAllocator< Type, OtherSize_ > const &T, bool ref=false)
Copy constructor.
TypeConst operator[](int i) const
void setRef(bool ref) const
Modify the container : can become a reference or the owner of the data.
void exchange(TRef const &T)
swap this with the container T.
bool isRef() const
static Type_ * memcpy(Type_ *p, Type_ *q, size_t size)
static Type_ * memmove(Type_ *p, Type_ *q, size_t size)
static Type_ * memcpy(Type_ *p, Type_ *q, size_t size)
static Type_ * memmove(Type_ *p, Type_ *q, size_t size)
:: :: fundamental types
static Type_ * malloc(Type_ *p_data, AllocatorRange const &range)
p_data should not point on existing data.
static Type_ * realloc(Type_ *p_data, AllocatorRange const &range, TRange< OtherSize > const &I)
realloc main pointer and copy existing data.
static Type_ * free(Type_ *p_data, AllocatorRange const &range)
shift data pointer and delete allocated memory
Helper class allowing to free memory (or not)
TRange< Size_ > AllocatorRange
static Type_ * realloc(Type_ *p_data, AllocatorRange const &range, TRange< OtherSize > const &I)
realloc main pointer and copy existing data.
static Type_ * free(Type_ *p_data, AllocatorRange const &range)
do nothing for fixed size allocators !
static Type_ * malloc(Type_ *p_data, AllocatorRange const &range)
malloc memory.