- メインページ
- モジュール
- ネームスペース
- データ構造
- ファイル

- ファイル一覧
- グローバル

mist_alloc.h
説明を見る。
1 //
2 // Copyright (c) 2003-2011, MIST Project, Nagoya University
3 // All rights reserved.
4 //
5 // Redistribution and use in source and binary forms, with or without modification,
6 // are permitted provided that the following conditions are met:
7 //
8 // 1. Redistributions of source code must retain the above copyright notice,
9 // this list of conditions and the following disclaimer.
10 //
11 // 2. Redistributions in binary form must reproduce the above copyright notice,
12 // this list of conditions and the following disclaimer in the documentation
13 // and/or other materials provided with the distribution.
14 //
15 // 3. Neither the name of the Nagoya University nor the names of its contributors
16 // may be used to endorse or promote products derived from this software
17 // without specific prior written permission.
18 //
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
20 // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
21 // FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
22 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
25 // IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
26 // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 //
28
33
34 #ifndef __INCLUDE_MIST_ALLOC_H__
35 #define __INCLUDE_MIST_ALLOC_H__
36
37 #include <cstring>
38 #include <memory>
39
40 #ifndef __INCLUDE_MIST_CONF_H__
41 #include "mist_conf.h"
42 #endif
43
44 #ifndef __INCLUDE_MIST_TYPE_TRAIT_H__
45 #include "type_trait.h"
46 #endif
47
48
49 // mist名前空間の始まり
50 _MIST_BEGIN
51
52
53
55 template < bool b >
56 struct mist_memory_operator
57 {
67 template < class Allocator >
68 static typename Allocator::pointer allocate_objects1( Allocator &allocator, typename Allocator::size_type num )
69 {
70 #if _MIST_ALLOCATE_TEST_ != 0
71 ::std::cerr << "Normal Allocator" << ::std::endl;
72 #endif
73 typename Allocator::pointer ptr = allocator.allocate( num, 0 );
74 typename Allocator::value_type obj;
75 for( typename Allocator::size_type i = 0 ; i < num ; i++ ) allocator.construct( &( ptr[i] ), obj );
76 return( ptr );
77 }
78
79
90 template < class Allocator >
91 static typename Allocator::pointer allocate_objects2( Allocator &allocator, typename Allocator::size_type num, typename Allocator::const_reference obj )
92 {
93 #if _MIST_ALLOCATE_TEST_ != 0
94 ::std::cerr << "Normal Allocator" << ::std::endl;
95 #endif
96 typename Allocator::pointer ptr = allocator.allocate( num, 0 );
97 for( typename Allocator::size_type i = 0 ; i < num ; i++ ) allocator.construct( &( ptr[i] ), obj );
98 return( ptr );
99 }
100
101
112 template < class Allocator >
113 static typename Allocator::pointer allocate_objects3( Allocator &allocator, typename Allocator::const_pointer s, typename Allocator::const_pointer e )
114 {
115 #if _MIST_ALLOCATE_TEST_ != 0
116 ::std::cerr << "Normal Allocator" << ::std::endl;
117 #endif
118 typename Allocator::pointer ptr = allocator.allocate( e - s, 0 );
119 for( typename Allocator::pointer p = ptr ; s != e ; p++, s++ ) allocator.construct( p, *s );
120 return( ptr );
121 }
122
123
132 template < class Allocator >
133 static void deallocate_objects( Allocator &allocator, typename Allocator::pointer ptr, typename Allocator::size_type num )
134 {
135 #if _MIST_ALLOCATE_TEST_ != 0
136 ::std::cerr << "Normal Deallocator" << ::std::endl;
137 #endif
138 for( typename Allocator::size_type i = 0 ; i < num ; i++ ) allocator.destroy( &( ptr[i] ) );
139 allocator.deallocate( ptr, num );
140 }
141
142
154 template < class Allocator >
155 static typename Allocator::pointer copy_objects1( Allocator & /* allocator */, typename Allocator::const_pointer s, typename Allocator::const_pointer e, typename Allocator::pointer x )
156 {
157 #if _MIST_ALLOCATE_TEST_ != 0
158 ::std::cerr << "Normal Copy Function" << ::std::endl;
159 #endif
160 while( s != e )
161 {
162 *x = *s;
163 ++x;
164 ++s;
165 }
166 return( x );
167 }
168
169
181 template < class Allocator >
182 static typename Allocator::pointer copy_objects2( Allocator & /* allocator */, typename Allocator::const_pointer ptr, typename Allocator::size_type num, typename Allocator::pointer to )
183 {
184 #if _MIST_ALLOCATE_TEST_ != 0
185 ::std::cerr << "Normal Copy Function" << ::std::endl;
186 #endif
187 for( typename Allocator::size_type i = 0 ; i < num ; i++ ) to[i] = ptr[i];
188 return( to + num );
189 }
190
191
201 template < class Allocator >
202 static void fill_objects1( Allocator & /* allocator */, typename Allocator::pointer ptr, typename Allocator::size_type num, typename Allocator::const_reference obj )
203 {
204 #if _MIST_ALLOCATE_TEST_ != 0
205 ::std::cerr << "Normal Clean Function" << ::std::endl;
206 #endif
207 for( typename Allocator::size_type i = 0 ; i < num ; i++ ) ptr[i] = obj;
208 }
209
210
219 template < class Allocator >
220 static void fill_objects2( Allocator & /* allocator */, typename Allocator::pointer ptr, typename Allocator::size_type num )
221 {
222 #if _MIST_ALLOCATE_TEST_ != 0
223 ::std::cerr << "Normal Clean Function" << ::std::endl;
224 #endif
225 typename Allocator::value_type obj;
226 for( typename Allocator::size_type i = 0 ; i < num ; i++ ) ptr[i] = obj;
227 }
228 };
229
230
231
232
234 template <>
235 struct mist_memory_operator< true >
236 {
246 template < class Allocator >
247 static typename Allocator::pointer allocate_objects1( Allocator &allocator, typename Allocator::size_type num )
248 {
249 #if _MIST_ALLOCATE_TEST_ != 0
250 ::std::cerr << "Memset Allocator" << ::std::endl;
251 #endif
252 typename Allocator::pointer ptr = allocator.allocate( num, 0 );
253 ::memset( ptr, 0, num * sizeof( typename Allocator::value_type ) );
254 return( ptr );
255 }
256
257
268 template < class Allocator >
269 static typename Allocator::pointer allocate_objects2( Allocator &allocator, typename Allocator::size_type num, typename Allocator::const_reference obj )
270 {
271 #if _MIST_ALLOCATE_TEST_ != 0
272 ::std::cerr << "Specialized Allocator" << ::std::endl;
273 #endif
274 typename Allocator::pointer ptr = allocator.allocate( num, 0 );
275 for( typename Allocator::size_type i = 0 ; i < num ; i++ ) ptr[i] = obj;
276 return( ptr );
277 }
278
279
290 template < class Allocator >
291 static typename Allocator::pointer allocate_objects3( Allocator &allocator, typename Allocator::const_pointer s, typename Allocator::const_pointer e )
292 {
293 #if _MIST_ALLOCATE_TEST_ != 0
294 ::std::cerr << "Memcpy Allocator" << ::std::endl;
295 #endif
296 typename Allocator::pointer ptr = allocator.allocate( e - s, 0 );
297 memcpy( ptr, s, ( e - s ) * sizeof( typename Allocator::value_type ) );
298 return( ptr );
299 }
300
301
310 template < class Allocator >
311 static void deallocate_objects( Allocator &allocator, typename Allocator::pointer ptr, typename Allocator::size_type num )
312 {
313 #if _MIST_ALLOCATE_TEST_ != 0
314 ::std::cerr << "Specialized Deallocator" << ::std::endl;
315 #endif
316 allocator.deallocate( ptr, num );
317 }
318
319
331 template < class Allocator >
332 static typename Allocator::pointer copy_objects1( Allocator & /* allocator */, typename Allocator::const_pointer s, typename Allocator::const_pointer e, typename Allocator::pointer x )
333 {
334 #if _MIST_ALLOCATE_TEST_ != 0
335 ::std::cerr << "Memcpy Copy Function" << ::std::endl;
336 #endif
337 memcpy( x, s, ( e - s ) * sizeof( typename Allocator::value_type ) );
338 return( x + ( e - s ) );
339 }
340
341
353 template < class Allocator >
354 static typename Allocator::pointer copy_objects2( Allocator & /* allocator */, typename Allocator::const_pointer ptr, typename Allocator::size_type num, typename Allocator::pointer to )
355 {
356 #if _MIST_ALLOCATE_TEST_ != 0
357 ::std::cerr << "Memcpy Copy Function" << ::std::endl;
358 #endif
359 memcpy( to, ptr, num * sizeof( typename Allocator::value_type ) );
360 return( to + num );
361 }
362
363
373 template < class Allocator >
374 static void fill_objects1( Allocator & /* allocator */, typename Allocator::pointer ptr, typename Allocator::size_type num, typename Allocator::const_reference obj )
375 {
376 #if _MIST_ALLOCATE_TEST_ != 0
377 ::std::cerr << "Memcpy Clean Function" << ::std::endl;
378 #endif
379 memset( ptr, obj, num * sizeof( typename Allocator::value_type ) );
380 }
381
382
391 template < class Allocator >
392 static void fill_objects2( Allocator & /* allocator */, typename Allocator::pointer ptr, typename Allocator::size_type num )
393 {
394 #if _MIST_ALLOCATE_TEST_ != 0
395 ::std::cerr << "Memcpy Clean Function" << ::std::endl;
396 #endif
397 memset( ptr, 0, num * sizeof( typename Allocator::value_type ) );
398 }
399 };
400
401
402
410 template < class T, class Allocator >
411 class mist_allocator : public Allocator
412 {
413 public:
414 typedef Allocator base;
415 typedef typename Allocator::reference reference;
416 typedef typename Allocator::const_reference const_reference;
417 typedef typename Allocator::value_type value_type;
418 typedef typename Allocator::size_type size_type;
419 typedef typename Allocator::difference_type difference_type;
420 typedef typename Allocator::pointer pointer;
421 typedef typename Allocator::const_pointer const_pointer;
422
423 protected:
424 pointer shared_pointer; // 利用可能なメモリへのポインタ（外部とメモリを共有する場合のみ利用）
425 size_type shared_memory; // 利用可能なメモリ量（外部とメモリを共有する場合のみ利用）
426
427
428 public:
430 pointer allocate_objects( size_type num )
431 {
432 if( num == 0 || num > max_size( ) )
433 {
434 return( NULL );
435 }
436 else if( !is_memory_shared( ) )
437 {
438 // 自動でメモリを割り当てる場合
439 return( mist_memory_operator< is_builtin< T >::value >::allocate_objects1( *this, num ) );
440 }
441 else
442 {
443 // 外部割り当てのメモリを利用する場合
444 return( shared_pointer );
445 }
446 }
447
449 pointer allocate_objects( size_type num, const_reference obj )
450 {
451 if( num == 0 || num > max_size( ) )
452 {
453 return( NULL );
454 }
455 else if( !is_memory_shared( ) )
456 {
457 // 自動でメモリを割り当てる場合
458 return( mist_memory_operator< is_builtin< T >::value >::allocate_objects2( *this, num, obj ) );
459 }
460 else
461 {
462 // 外部割り当てのメモリを利用する場合
463 mist_memory_operator< type_and< is_char< T >::value, is_builtin< T >::value >::value >::fill_objects1( *this, shared_pointer, num, obj );
464 return( shared_pointer );
465 }
466 }
467
469 pointer allocate_objects( const_pointer s, const_pointer e )
470 {
471 if( s >= e || e - s > max_size( ) )
472 {
473 return( NULL );
474 }
475 else if( !is_memory_shared( ) )
476 {
477 // 自動でメモリを割り当てる場合
478 return( mist_memory_operator< is_builtin< T >::value >::allocate_objects3( *this, s, e ) );
479 }
480 else
481 {
482 // 外部割り当てのメモリを利用する場合
483 mist_memory_operator< type_and< is_char< T >::value, is_builtin< T >::value >::value >::copy_objects2( *this, s, e - s, shared_pointer );
484 return( shared_pointer );
485 }
486 }
487
489 void deallocate_objects( pointer ptr, size_type num )
490 {
491 if( !is_memory_shared( ) )
492 {
493 // 自動でメモリを割り当てる場合
494 if( num <= 0 ) return;
495 mist_memory_operator< is_builtin< T >::value >::deallocate_objects( *this, ptr, num );
496 }
497 }
498
500 pointer copy_objects( const_pointer s, const_pointer e, pointer x ) const
501 {
502 if( s >= e ) return( x );
503 return( mist_memory_operator< is_builtin< T >::value >::copy_objects1( *this, s, e, x ) );
504 }
505
507 pointer copy_objects( const_pointer ptr, size_type num, pointer to ) const
508 {
509 if( num <= 0 ) return( to );
510 return( mist_memory_operator< is_builtin< T >::value >::copy_objects2( *this, ptr, num, to ) );
511 }
512
514 void fill_objects( pointer ptr, size_type num, const_reference obj ) const
515 {
516 if( num <= 0 ) return;
517 mist_memory_operator< type_and< is_char< T >::value, is_builtin< T >::value >::value >::fill_objects1( *this, ptr, num, obj );
518 }
519
521 void fill_objects( pointer ptr, size_type num ) const
522 {
523 if( num <= 0 ) return;
524 mist_memory_operator< is_builtin< T >::value >::fill_objects2( *this, ptr, num );
525 }
526
531 pointer trim_objects( pointer ptr, size_type num, size_type dest_num )
532 {
533 if( num < dest_num ) return( ptr ); // 開放しようとしている配列の要素数は，トリム後の配列サイズよりサイズよりも小さい例外
534 //if( num < 0 ) return( NULL ); // トリム先の配列サイズが0より小さい例外
535 if( num == dest_num ) return( ptr ); // トリムによる変更の必要なし
536 if( num == 0 ) return( NULL );
537
538 if( !is_memory_shared( ) )
539 {
540 // 自動でメモリを割り当てる場合
541 #if _MIST_ALLOCATOR_MEMORY_TRIM_ != 0
542 deallocate_objects( ptr + dest_num, num - dest_num );
543 fill_objects( ptr, dest_num );
544 #else
545 deallocate_objects( ptr, num );
546 ptr = allocate_objects( dest_num );
547 #endif
548 }
549 return( dest_num == 0 ? NULL : ptr );
550 }
551
556 pointer trim_objects( pointer ptr, size_type num, size_type dest_num, const_reference obj )
557 {
558 if( num < dest_num ) return( ptr ); // 開放しようとしている配列の要素数は，トリム後の配列サイズよりサイズよりも小さい例外
559 if( num < 0 ) return( NULL ); // トリム先の配列サイズが0より小さい例外
560 if( num == dest_num ) return( ptr ); // トリムによる変更の必要なし
561 if( num == 0 ) return( NULL );
562
563 if( !is_memory_shared( ) )
564 {
565 // 自動でメモリを割り当てる場合
566 #if _MIST_ALLOCATOR_MEMORY_TRIM_ != 0
567 deallocate_objects( ptr + dest_num, num - dest_num );
568 fill_objects( ptr, dest_num, obj );
569 #else
570 deallocate_objects( ptr, num );
571 ptr = allocate_objects( dest_num, obj );
572 #endif
573 }
574 return( dest_num == 0 ? NULL : ptr );
575 }
576
578 size_type max_size( ) const
579 {
580 return( shared_memory == 0 ? base::max_size( ) : shared_memory );
581 }
582
584 bool is_memory_shared( ) const
585 {
586 return( shared_memory != 0 );
587 }
588
590 const Allocator &operator=( const Allocator &alloc )
591 {
592 if( &alloc != this )
593 {
594 // 外部メモリを利用しているかどうかは受け継がない
595 base::operator=( alloc );
596 }
597 return( *this );
598 }
599
601 const mist_allocator &operator=( const mist_allocator &alloc )
602 {
603 if( &alloc != this )
604 {
605 // 外部メモリを利用しているかどうかは受け継がない
606 base::operator=( alloc );
607 }
608 return( *this );
609 }
610
611
613 mist_allocator( ) : base( ), shared_pointer( NULL ), shared_memory( 0 ){}
614
615
623 mist_allocator( pointer ptr, size_type mem_shared ) : base( ), shared_pointer( mem_shared == 0 ? NULL : ptr ), shared_memory( ptr == NULL ? 0 : mem_shared ){}
624
625
627 mist_allocator( const Allocator &alloc ) : base( alloc ), shared_pointer( NULL ), shared_memory( 0 ){}
628
629
631 mist_allocator( const mist_allocator &alloc ) : base( alloc ), shared_pointer( NULL ), shared_memory( 0 ){}
632 };
633
634
635
636 // mist名前空間の終わり
637 _MIST_END
638
639 #endif // __INCLUDE_MIST_ALLOC_H__
640