OpenCores
URL https://opencores.org/ocsvn/scarts/scarts/trunk

Subversion Repositories scarts

[/] [scarts/] [trunk/] [toolchain/] [scarts-gcc/] [gcc-4.1.1/] [libstdc++-v3/] [include/] [ext/] [bitmap_allocator.h] - Blame information for rev 17

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 17 jlechner
// Bitmap Allocator. -*- C++ -*-
2
 
3
// Copyright (C) 2004, 2005 Free Software Foundation, Inc.
4
//
5
// This file is part of the GNU ISO C++ Library.  This library is free
6
// software; you can redistribute it and/or modify it under the
7
// terms of the GNU General Public License as published by the
8
// Free Software Foundation; either version 2, or (at your option)
9
// any later version.
10
 
11
// This library is distributed in the hope that it will be useful,
12
// but WITHOUT ANY WARRANTY; without even the implied warranty of
13
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
// GNU General Public License for more details.
15
 
16
// You should have received a copy of the GNU General Public License along
17
// with this library; see the file COPYING.  If not, write to the Free
18
// Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
19
// USA.
20
 
21
// As a special exception, you may use this file as part of a free software
22
// library without restriction.  Specifically, if other files instantiate
23
// templates or use macros or inline functions from this file, or you compile
24
// this file and link it with other files to produce an executable, this
25
// file does not by itself cause the resulting executable to be covered by
26
// the GNU General Public License.  This exception does not however
27
// invalidate any other reasons why the executable file might be covered by
28
// the GNU General Public License.
29
 
30
/** @file ext/bitmap_allocator.h
31
 *  This file is a GNU extension to the Standard C++ Library.
32
 */
33
 
34
#ifndef _BITMAP_ALLOCATOR_H
35
#define _BITMAP_ALLOCATOR_H 1
36
 
37
// For std::size_t, and ptrdiff_t.
38
#include <cstddef>
39
 
40
// For __throw_bad_alloc().
41
#include <bits/functexcept.h>
42
 
43
// For std::pair.
44
#include <utility>
45
 
46
// For greater_equal, and less_equal.
47
#include <functional>
48
 
49
// For operator new.
50
#include <new>
51
 
52
// For __gthread_mutex_t, __gthread_mutex_lock and __gthread_mutex_unlock.
53
#include <bits/gthr.h>
54
 
55
// Define this to enable error checking withing the allocator
56
// itself(to debug the allocator itself).
57
//#define _BALLOC_SANITY_CHECK
58
 
59
/** @brief The constant in the expression below is the alignment
60
 * required in bytes.
61
 */
62
#define _BALLOC_ALIGN_BYTES 8
63
 
64
#if defined _BALLOC_SANITY_CHECK
65
#include <cassert>
66
#define _BALLOC_ASSERT(_EXPR) assert(_EXPR)
67
#else
68
#define _BALLOC_ASSERT(_EXPR)
69
#endif
70
 
71
 
72
namespace __gnu_cxx
73
{
74
#if defined __GTHREADS
75
  namespace
76
  {
77
    /** @brief  If true, then the application being compiled will be
78
     *  using threads, so use mutexes as a synchronization primitive,
79
     *  else do no use any synchronization primitives.
80
     */
81
    bool const __threads_enabled = __gthread_active_p();
82
  }
83
#endif
84
 
85
#if defined __GTHREADS
86
  /** @class  _Mutex bitmap_allocator.h bitmap_allocator.h
87
   *
88
   *  @brief  _Mutex is an OO-Wrapper for __gthread_mutex_t.
89
   *
90
   *  It does not allow you to copy or assign an already initialized
91
   *  mutex. This is used merely as a convenience for the locking
92
   *  classes.
93
   */
94
  class _Mutex
95
  {
96
    __gthread_mutex_t _M_mut;
97
 
98
    // Prevent Copying and assignment.
99
    _Mutex(_Mutex const&);
100
    _Mutex& operator=(_Mutex const&);
101
 
102
  public:
103
    _Mutex()
104
    {
105
      if (__threads_enabled)
106
        {
107
#if !defined __GTHREAD_MUTEX_INIT
108
          __GTHREAD_MUTEX_INIT_FUNCTION(&_M_mut);
109
#else
110
          __gthread_mutex_t __mtemp = __GTHREAD_MUTEX_INIT;
111
          _M_mut = __mtemp;
112
#endif
113
        }
114
    }
115
 
116
    ~_Mutex()
117
    {
118
      // Gthreads does not define a Mutex Destruction Function.
119
    }
120
 
121
    __gthread_mutex_t*
122
    _M_get() { return &_M_mut; }
123
  };
124
 
125
  /** @class  _Lock bitmap_allocator.h bitmap_allocator.h
126
   *
127
   *  @brief  _Lock is a simple manual locking class which allows you to
128
   *  manually lock and unlock a mutex associated with the lock.
129
   *
130
   *  There is no automatic locking or unlocking happening without the
131
   *  programmer's explicit instructions. This class unlocks the mutex
132
   *  ONLY if it has not been locked. However, this check does not
133
   *  apply for locking, and wayward use may cause dead-locks.
134
   */
135
  class _Lock
136
  {
137
    _Mutex* _M_pmt;
138
    bool _M_locked;
139
 
140
    // Prevent Copying and assignment.
141
    _Lock(_Lock const&);
142
    _Lock& operator=(_Lock const&);
143
 
144
  public:
145
    _Lock(_Mutex* __mptr)
146
    : _M_pmt(__mptr), _M_locked(false)
147
    { }
148
 
149
    void
150
    _M_lock()
151
    {
152
      if (__threads_enabled)
153
        {
154
          _M_locked = true;
155
          __gthread_mutex_lock(_M_pmt->_M_get());
156
        }
157
    }
158
 
159
    void
160
    _M_unlock()
161
    {
162
      if (__threads_enabled)
163
        {
164
          if (__builtin_expect(_M_locked, true))
165
            {
166
              __gthread_mutex_unlock(_M_pmt->_M_get());
167
              _M_locked = false;
168
            }
169
        }
170
    }
171
 
172
    ~_Lock() { }
173
  };
174
 
175
  /** @class  _Auto_Lock bitmap_allocator.h bitmap_allocator.h
176
   *
177
   *  @brief  _Auto_Lock locks the associated mutex on construction, and
178
   *  unlocks on destruction.
179
   *
180
   *  There are no checks performed, and this class follows the RAII
181
   *  principle.
182
   */
183
  class _Auto_Lock
184
  {
185
    _Mutex* _M_pmt;
186
    // Prevent Copying and assignment.
187
    _Auto_Lock(_Auto_Lock const&);
188
    _Auto_Lock& operator=(_Auto_Lock const&);
189
 
190
    void
191
    _M_lock()
192
    {
193
      if (__threads_enabled)
194
        __gthread_mutex_lock(_M_pmt->_M_get());
195
    }
196
 
197
    void
198
    _M_unlock()
199
    {
200
      if (__threads_enabled)
201
        __gthread_mutex_unlock(_M_pmt->_M_get());
202
    }
203
 
204
  public:
205
    _Auto_Lock(_Mutex* __mptr) : _M_pmt(__mptr)
206
    { this->_M_lock(); }
207
 
208
    ~_Auto_Lock() { this->_M_unlock(); }
209
  };
210
#endif 
211
 
212
  namespace balloc
213
  {
214
    /** @class  __mini_vector bitmap_allocator.h bitmap_allocator.h
215
     *
216
     *  @brief  __mini_vector<> is a stripped down version of the
217
     *  full-fledged std::vector<>.
218
     *
219
     *  It is to be used only for built-in types or PODs. Notable
220
     *  differences are:
221
     *
222
     *  @detail
223
     *  1. Not all accessor functions are present.
224
     *  2. Used ONLY for PODs.
225
     *  3. No Allocator template argument. Uses ::operator new() to get
226
     *  memory, and ::operator delete() to free it.
227
     *  Caveat: The dtor does NOT free the memory allocated, so this a
228
     *  memory-leaking vector!
229
     */
230
    template<typename _Tp>
231
      class __mini_vector
232
      {
233
        __mini_vector(const __mini_vector&);
234
        __mini_vector& operator=(const __mini_vector&);
235
 
236
      public:
237
        typedef _Tp value_type;
238
        typedef _Tp* pointer;
239
        typedef _Tp& reference;
240
        typedef const _Tp& const_reference;
241
        typedef std::size_t size_type;
242
        typedef std::ptrdiff_t difference_type;
243
        typedef pointer iterator;
244
 
245
      private:
246
        pointer _M_start;
247
        pointer _M_finish;
248
        pointer _M_end_of_storage;
249
 
250
        size_type
251
        _M_space_left() const throw()
252
        { return _M_end_of_storage - _M_finish; }
253
 
254
        pointer
255
        allocate(size_type __n)
256
        { return static_cast<pointer>(::operator new(__n * sizeof(_Tp))); }
257
 
258
        void
259
        deallocate(pointer __p, size_type)
260
        { ::operator delete(__p); }
261
 
262
      public:
263
        // Members used: size(), push_back(), pop_back(),
264
        // insert(iterator, const_reference), erase(iterator),
265
        // begin(), end(), back(), operator[].
266
 
267
        __mini_vector() : _M_start(0), _M_finish(0),
268
                          _M_end_of_storage(0)
269
        { }
270
 
271
#if 0
272
        ~__mini_vector()
273
        {
274
          if (this->_M_start)
275
            {
276
              this->deallocate(this->_M_start, this->_M_end_of_storage
277
                               - this->_M_start);
278
            }
279
        }
280
#endif
281
 
282
        size_type
283
        size() const throw()
284
        { return _M_finish - _M_start; }
285
 
286
        iterator
287
        begin() const throw()
288
        { return this->_M_start; }
289
 
290
        iterator
291
        end() const throw()
292
        { return this->_M_finish; }
293
 
294
        reference
295
        back() const throw()
296
        { return *(this->end() - 1); }
297
 
298
        reference
299
        operator[](const size_type __pos) const throw()
300
        { return this->_M_start[__pos]; }
301
 
302
        void
303
        insert(iterator __pos, const_reference __x);
304
 
305
        void
306
        push_back(const_reference __x)
307
        {
308
          if (this->_M_space_left())
309
            {
310
              *this->end() = __x;
311
              ++this->_M_finish;
312
            }
313
          else
314
            this->insert(this->end(), __x);
315
        }
316
 
317
        void
318
        pop_back() throw()
319
        { --this->_M_finish; }
320
 
321
        void
322
        erase(iterator __pos) throw();
323
 
324
        void
325
        clear() throw()
326
        { this->_M_finish = this->_M_start; }
327
      };
328
 
329
    // Out of line function definitions.
330
    template<typename _Tp>
331
      void __mini_vector<_Tp>::
332
      insert(iterator __pos, const_reference __x)
333
      {
334
        if (this->_M_space_left())
335
          {
336
            size_type __to_move = this->_M_finish - __pos;
337
            iterator __dest = this->end();
338
            iterator __src = this->end() - 1;
339
 
340
            ++this->_M_finish;
341
            while (__to_move)
342
              {
343
                *__dest = *__src;
344
                --__dest; --__src; --__to_move;
345
              }
346
            *__pos = __x;
347
          }
348
        else
349
          {
350
            size_type __new_size = this->size() ? this->size() * 2 : 1;
351
            iterator __new_start = this->allocate(__new_size);
352
            iterator __first = this->begin();
353
            iterator __start = __new_start;
354
            while (__first != __pos)
355
              {
356
                *__start = *__first;
357
                ++__start; ++__first;
358
              }
359
            *__start = __x;
360
            ++__start;
361
            while (__first != this->end())
362
              {
363
                *__start = *__first;
364
                ++__start; ++__first;
365
              }
366
            if (this->_M_start)
367
              this->deallocate(this->_M_start, this->size());
368
 
369
            this->_M_start = __new_start;
370
            this->_M_finish = __start;
371
            this->_M_end_of_storage = this->_M_start + __new_size;
372
          }
373
      }
374
 
375
    template<typename _Tp>
376
      void __mini_vector<_Tp>::
377
      erase(iterator __pos) throw()
378
      {
379
        while (__pos + 1 != this->end())
380
          {
381
            *__pos = __pos[1];
382
            ++__pos;
383
          }
384
        --this->_M_finish;
385
      }
386
 
387
 
388
    template<typename _Tp>
389
      struct __mv_iter_traits
390
      {
391
        typedef typename _Tp::value_type value_type;
392
        typedef typename _Tp::difference_type difference_type;
393
      };
394
 
395
    template<typename _Tp>
396
      struct __mv_iter_traits<_Tp*>
397
      {
398
        typedef _Tp value_type;
399
        typedef std::ptrdiff_t difference_type;
400
      };
401
 
402
    enum
403
      {
404
        bits_per_byte = 8,
405
        bits_per_block = sizeof(size_t) * size_t(bits_per_byte)
406
      };
407
 
408
    template<typename _ForwardIterator, typename _Tp, typename _Compare>
409
      _ForwardIterator
410
      __lower_bound(_ForwardIterator __first, _ForwardIterator __last,
411
                    const _Tp& __val, _Compare __comp)
412
      {
413
        typedef typename __mv_iter_traits<_ForwardIterator>::value_type
414
          _ValueType;
415
        typedef typename __mv_iter_traits<_ForwardIterator>::difference_type
416
          _DistanceType;
417
 
418
        _DistanceType __len = __last - __first;
419
        _DistanceType __half;
420
        _ForwardIterator __middle;
421
 
422
        while (__len > 0)
423
          {
424
            __half = __len >> 1;
425
            __middle = __first;
426
            __middle += __half;
427
            if (__comp(*__middle, __val))
428
              {
429
                __first = __middle;
430
                ++__first;
431
                __len = __len - __half - 1;
432
              }
433
            else
434
              __len = __half;
435
          }
436
        return __first;
437
      }
438
 
439
    template<typename _InputIterator, typename _Predicate>
440
      inline _InputIterator
441
      __find_if(_InputIterator __first, _InputIterator __last, _Predicate __p)
442
      {
443
        while (__first != __last && !__p(*__first))
444
          ++__first;
445
        return __first;
446
      }
447
 
448
    /** @brief The number of Blocks pointed to by the address pair
449
     *  passed to the function.
450
     */
451
    template<typename _AddrPair>
452
      inline size_t
453
      __num_blocks(_AddrPair __ap)
454
      { return (__ap.second - __ap.first) + 1; }
455
 
456
    /** @brief The number of Bit-maps pointed to by the address pair
457
     *  passed to the function.
458
     */
459
    template<typename _AddrPair>
460
      inline size_t
461
      __num_bitmaps(_AddrPair __ap)
462
      { return __num_blocks(__ap) / size_t(bits_per_block); }
463
 
464
    // _Tp should be a pointer type.
465
    template<typename _Tp>
466
      class _Inclusive_between
467
      : public std::unary_function<typename std::pair<_Tp, _Tp>, bool>
468
      {
469
        typedef _Tp pointer;
470
        pointer _M_ptr_value;
471
        typedef typename std::pair<_Tp, _Tp> _Block_pair;
472
 
473
      public:
474
        _Inclusive_between(pointer __ptr) : _M_ptr_value(__ptr)
475
        { }
476
 
477
        bool
478
        operator()(_Block_pair __bp) const throw()
479
        {
480
          if (std::less_equal<pointer>()(_M_ptr_value, __bp.second)
481
              && std::greater_equal<pointer>()(_M_ptr_value, __bp.first))
482
            return true;
483
          else
484
            return false;
485
        }
486
      };
487
 
488
    // Used to pass a Functor to functions by reference.
489
    template<typename _Functor>
490
      class _Functor_Ref
491
      : public std::unary_function<typename _Functor::argument_type,
492
                                   typename _Functor::result_type>
493
      {
494
        _Functor& _M_fref;
495
 
496
      public:
497
        typedef typename _Functor::argument_type argument_type;
498
        typedef typename _Functor::result_type result_type;
499
 
500
        _Functor_Ref(_Functor& __fref) : _M_fref(__fref)
501
        { }
502
 
503
        result_type
504
        operator()(argument_type __arg)
505
        { return _M_fref(__arg); }
506
      };
507
 
508
    /** @class  _Ffit_finder bitmap_allocator.h bitmap_allocator.h
509
     *
510
     *  @brief  The class which acts as a predicate for applying the
511
     *  first-fit memory allocation policy for the bitmap allocator.
512
     */
513
    // _Tp should be a pointer type, and _Alloc is the Allocator for
514
    // the vector.
515
    template<typename _Tp>
516
      class _Ffit_finder
517
      : public std::unary_function<typename std::pair<_Tp, _Tp>, bool>
518
      {
519
        typedef typename std::pair<_Tp, _Tp> _Block_pair;
520
        typedef typename balloc::__mini_vector<_Block_pair> _BPVector;
521
        typedef typename _BPVector::difference_type _Counter_type;
522
 
523
        size_t* _M_pbitmap;
524
        _Counter_type _M_data_offset;
525
 
526
      public:
527
        _Ffit_finder() : _M_pbitmap(0), _M_data_offset(0)
528
        { }
529
 
530
        bool
531
        operator()(_Block_pair __bp) throw()
532
        {
533
          // Set the _rover to the last physical location bitmap,
534
          // which is the bitmap which belongs to the first free
535
          // block. Thus, the bitmaps are in exact reverse order of
536
          // the actual memory layout. So, we count down the bimaps,
537
          // which is the same as moving up the memory.
538
 
539
          // If the used count stored at the start of the Bit Map headers
540
          // is equal to the number of Objects that the current Block can
541
          // store, then there is definitely no space for another single
542
          // object, so just return false.
543
          _Counter_type __diff =
544
            __gnu_cxx::balloc::__num_bitmaps(__bp);
545
 
546
          if (*(reinterpret_cast<size_t*>
547
                (__bp.first) - (__diff + 1))
548
              == __gnu_cxx::balloc::__num_blocks(__bp))
549
            return false;
550
 
551
          size_t* __rover = reinterpret_cast<size_t*>(__bp.first) - 1;
552
 
553
          for (_Counter_type __i = 0; __i < __diff; ++__i)
554
            {
555
              _M_data_offset = __i;
556
              if (*__rover)
557
                {
558
                  _M_pbitmap = __rover;
559
                  return true;
560
                }
561
              --__rover;
562
            }
563
          return false;
564
        }
565
 
566
 
567
        size_t*
568
        _M_get() const throw()
569
        { return _M_pbitmap; }
570
 
571
        _Counter_type
572
        _M_offset() const throw()
573
        { return _M_data_offset * size_t(bits_per_block); }
574
      };
575
 
576
 
577
    /** @class  _Bitmap_counter bitmap_allocator.h bitmap_allocator.h
578
     *
579
     *  @brief  The bitmap counter which acts as the bitmap
580
     *  manipulator, and manages the bit-manipulation functions and
581
     *  the searching and identification functions on the bit-map.
582
     */
583
    // _Tp should be a pointer type.
584
    template<typename _Tp>
585
      class _Bitmap_counter
586
      {
587
        typedef typename balloc::__mini_vector<typename std::pair<_Tp, _Tp> >
588
        _BPVector;
589
        typedef typename _BPVector::size_type _Index_type;
590
        typedef _Tp pointer;
591
 
592
        _BPVector& _M_vbp;
593
        size_t* _M_curr_bmap;
594
        size_t* _M_last_bmap_in_block;
595
        _Index_type _M_curr_index;
596
 
597
      public:
598
        // Use the 2nd parameter with care. Make sure that such an
599
        // entry exists in the vector before passing that particular
600
        // index to this ctor.
601
        _Bitmap_counter(_BPVector& Rvbp, long __index = -1) : _M_vbp(Rvbp)
602
        { this->_M_reset(__index); }
603
 
604
        void
605
        _M_reset(long __index = -1) throw()
606
        {
607
          if (__index == -1)
608
            {
609
              _M_curr_bmap = 0;
610
              _M_curr_index = static_cast<_Index_type>(-1);
611
              return;
612
            }
613
 
614
          _M_curr_index = __index;
615
          _M_curr_bmap = reinterpret_cast<size_t*>
616
            (_M_vbp[_M_curr_index].first) - 1;
617
 
618
          _BALLOC_ASSERT(__index <= (long)_M_vbp.size() - 1);
619
 
620
          _M_last_bmap_in_block = _M_curr_bmap
621
            - ((_M_vbp[_M_curr_index].second
622
                - _M_vbp[_M_curr_index].first + 1)
623
               / size_t(bits_per_block) - 1);
624
        }
625
 
626
        // Dangerous Function! Use with extreme care. Pass to this
627
        // function ONLY those values that are known to be correct,
628
        // otherwise this will mess up big time.
629
        void
630
        _M_set_internal_bitmap(size_t* __new_internal_marker) throw()
631
        { _M_curr_bmap = __new_internal_marker; }
632
 
633
        bool
634
        _M_finished() const throw()
635
        { return(_M_curr_bmap == 0); }
636
 
637
        _Bitmap_counter&
638
        operator++() throw()
639
        {
640
          if (_M_curr_bmap == _M_last_bmap_in_block)
641
            {
642
              if (++_M_curr_index == _M_vbp.size())
643
                _M_curr_bmap = 0;
644
              else
645
                this->_M_reset(_M_curr_index);
646
            }
647
          else
648
            --_M_curr_bmap;
649
          return *this;
650
        }
651
 
652
        size_t*
653
        _M_get() const throw()
654
        { return _M_curr_bmap; }
655
 
656
        pointer
657
        _M_base() const throw()
658
        { return _M_vbp[_M_curr_index].first; }
659
 
660
        _Index_type
661
        _M_offset() const throw()
662
        {
663
          return size_t(bits_per_block)
664
            * ((reinterpret_cast<size_t*>(this->_M_base())
665
                - _M_curr_bmap) - 1);
666
        }
667
 
668
        _Index_type
669
        _M_where() const throw()
670
        { return _M_curr_index; }
671
      };
672
 
673
    /** @brief  Mark a memory address as allocated by re-setting the
674
     *  corresponding bit in the bit-map.
675
     */
676
    inline void
677
    __bit_allocate(size_t* __pbmap, size_t __pos) throw()
678
    {
679
      size_t __mask = 1 << __pos;
680
      __mask = ~__mask;
681
      *__pbmap &= __mask;
682
    }
683
 
684
    /** @brief  Mark a memory address as free by setting the
685
     *  corresponding bit in the bit-map.
686
     */
687
    inline void
688
    __bit_free(size_t* __pbmap, size_t __pos) throw()
689
    {
690
      size_t __mask = 1 << __pos;
691
      *__pbmap |= __mask;
692
    }
693
  } // namespace balloc
694
 
695
  /** @brief  Generic Version of the bsf instruction.
696
   */
697
  inline size_t
698
  _Bit_scan_forward(size_t __num)
699
  { return static_cast<size_t>(__builtin_ctzl(__num)); }
700
 
701
  /** @class  free_list bitmap_allocator.h bitmap_allocator.h
702
   *
703
   *  @brief  The free list class for managing chunks of memory to be
704
   *  given to and returned by the bitmap_allocator.
705
   */
706
  class free_list
707
  {
708
    typedef size_t* value_type;
709
    typedef balloc::__mini_vector<value_type> vector_type;
710
    typedef vector_type::iterator iterator;
711
 
712
    struct _LT_pointer_compare
713
    {
714
      bool
715
      operator()(const size_t* __pui,
716
                 const size_t __cui) const throw()
717
      { return *__pui < __cui; }
718
    };
719
 
720
#if defined __GTHREADS
721
    _Mutex*
722
    _M_get_mutex()
723
    {
724
      static _Mutex _S_mutex;
725
      return &_S_mutex;
726
    }
727
#endif
728
 
729
    vector_type&
730
    _M_get_free_list()
731
    {
732
      static vector_type _S_free_list;
733
      return _S_free_list;
734
    }
735
 
736
    /** @brief  Performs validation of memory based on their size.
737
     *
738
     *  @param  __addr The pointer to the memory block to be
739
     *  validated.
740
     *
741
     *  @detail  Validates the memory block passed to this function and
742
     *  appropriately performs the action of managing the free list of
743
     *  blocks by adding this block to the free list or deleting this
744
     *  or larger blocks from the free list.
745
     */
746
    void
747
    _M_validate(size_t* __addr) throw()
748
    {
749
      vector_type& __free_list = _M_get_free_list();
750
      const vector_type::size_type __max_size = 64;
751
      if (__free_list.size() >= __max_size)
752
        {
753
          // Ok, the threshold value has been reached.  We determine
754
          // which block to remove from the list of free blocks.
755
          if (*__addr >= *__free_list.back())
756
            {
757
              // Ok, the new block is greater than or equal to the
758
              // last block in the list of free blocks. We just free
759
              // the new block.
760
              ::operator delete(static_cast<void*>(__addr));
761
              return;
762
            }
763
          else
764
            {
765
              // Deallocate the last block in the list of free lists,
766
              // and insert the new one in it's correct position.
767
              ::operator delete(static_cast<void*>(__free_list.back()));
768
              __free_list.pop_back();
769
            }
770
        }
771
 
772
      // Just add the block to the list of free lists unconditionally.
773
      iterator __temp = __gnu_cxx::balloc::__lower_bound
774
        (__free_list.begin(), __free_list.end(),
775
         *__addr, _LT_pointer_compare());
776
 
777
      // We may insert the new free list before _temp;
778
      __free_list.insert(__temp, __addr);
779
    }
780
 
781
    /** @brief  Decides whether the wastage of memory is acceptable for
782
     *  the current memory request and returns accordingly.
783
     *
784
     *  @param __block_size The size of the block available in the free
785
     *  list.
786
     *
787
     *  @param __required_size The required size of the memory block.
788
     *
789
     *  @return true if the wastage incurred is acceptable, else returns
790
     *  false.
791
     */
792
    bool
793
    _M_should_i_give(size_t __block_size,
794
                     size_t __required_size) throw()
795
    {
796
      const size_t __max_wastage_percentage = 36;
797
      if (__block_size >= __required_size &&
798
          (((__block_size - __required_size) * 100 / __block_size)
799
           < __max_wastage_percentage))
800
        return true;
801
      else
802
        return false;
803
    }
804
 
805
  public:
806
    /** @brief This function returns the block of memory to the
807
     *  internal free list.
808
     *
809
     *  @param  __addr The pointer to the memory block that was given
810
     *  by a call to the _M_get function.
811
     */
812
    inline void
813
    _M_insert(size_t* __addr) throw()
814
    {
815
#if defined __GTHREADS
816
      _Auto_Lock __bfl_lock(_M_get_mutex());
817
#endif
818
      // Call _M_validate to decide what should be done with
819
      // this particular free list.
820
      this->_M_validate(reinterpret_cast<size_t*>(__addr) - 1);
821
      // See discussion as to why this is 1!
822
    }
823
 
824
    /** @brief  This function gets a block of memory of the specified
825
     *  size from the free list.
826
     *
827
     *  @param  __sz The size in bytes of the memory required.
828
     *
829
     *  @return  A pointer to the new memory block of size at least
830
     *  equal to that requested.
831
     */
832
    size_t*
833
    _M_get(size_t __sz) throw(std::bad_alloc);
834
 
835
    /** @brief  This function just clears the internal Free List, and
836
     *  gives back all the memory to the OS.
837
     */
838
    void
839
    _M_clear();
840
  };
841
 
842
 
843
  // Forward declare the class.
844
  template<typename _Tp>
845
    class bitmap_allocator;
846
 
847
  // Specialize for void:
848
  template<>
849
    class bitmap_allocator<void>
850
    {
851
    public:
852
      typedef void*       pointer;
853
      typedef const void* const_pointer;
854
 
855
      // Reference-to-void members are impossible.
856
      typedef void  value_type;
857
      template<typename _Tp1>
858
        struct rebind
859
        {
860
          typedef bitmap_allocator<_Tp1> other;
861
        };
862
    };
863
 
864
  template<typename _Tp>
865
    class bitmap_allocator : private free_list
866
    {
867
    public:
868
      typedef std::size_t    size_type;
869
      typedef std::ptrdiff_t difference_type;
870
      typedef _Tp*        pointer;
871
      typedef const _Tp*  const_pointer;
872
      typedef _Tp&        reference;
873
      typedef const _Tp&  const_reference;
874
      typedef _Tp         value_type;
875
      template<typename _Tp1>
876
        struct rebind
877
        {
878
          typedef bitmap_allocator<_Tp1> other;
879
        };
880
 
881
    private:
882
      template<size_t _BSize, size_t _AlignSize>
883
        struct aligned_size
884
        {
885
          enum
886
            {
887
              modulus = _BSize % _AlignSize,
888
              value = _BSize + (modulus ? _AlignSize - (modulus) : 0)
889
            };
890
        };
891
 
892
      struct _Alloc_block
893
      {
894
        char __M_unused[aligned_size<sizeof(value_type),
895
                        _BALLOC_ALIGN_BYTES>::value];
896
      };
897
 
898
 
899
      typedef typename std::pair<_Alloc_block*, _Alloc_block*> _Block_pair;
900
 
901
      typedef typename
902
      balloc::__mini_vector<_Block_pair> _BPVector;
903
 
904
#if defined _BALLOC_SANITY_CHECK
905
      // Complexity: O(lg(N)). Where, N is the number of block of size
906
      // sizeof(value_type).
907
      void
908
      _S_check_for_free_blocks() throw()
909
      {
910
        typedef typename
911
          __gnu_cxx::balloc::_Ffit_finder<_Alloc_block*> _FFF;
912
        _FFF __fff;
913
        typedef typename _BPVector::iterator _BPiter;
914
        _BPiter __bpi =
915
          __gnu_cxx::balloc::__find_if
916
          (_S_mem_blocks.begin(), _S_mem_blocks.end(),
917
           __gnu_cxx::balloc::_Functor_Ref<_FFF>(__fff));
918
 
919
        _BALLOC_ASSERT(__bpi == _S_mem_blocks.end());
920
      }
921
#endif
922
 
923
      /** @brief  Responsible for exponentially growing the internal
924
       *  memory pool.
925
       *
926
       *  @throw  std::bad_alloc. If memory can not be allocated.
927
       *
928
       *  @detail  Complexity: O(1), but internally depends upon the
929
       *  complexity of the function free_list::_M_get. The part where
930
       *  the bitmap headers are written has complexity: O(X),where X
931
       *  is the number of blocks of size sizeof(value_type) within
932
       *  the newly acquired block. Having a tight bound.
933
       */
934
      void
935
      _S_refill_pool() throw(std::bad_alloc)
936
      {
937
#if defined _BALLOC_SANITY_CHECK
938
        _S_check_for_free_blocks();
939
#endif
940
 
941
        const size_t __num_bitmaps = (_S_block_size
942
                                      / size_t(balloc::bits_per_block));
943
        const size_t __size_to_allocate = sizeof(size_t)
944
          + _S_block_size * sizeof(_Alloc_block)
945
          + __num_bitmaps * sizeof(size_t);
946
 
947
        size_t* __temp =
948
          reinterpret_cast<size_t*>
949
          (this->_M_get(__size_to_allocate));
950
        *__temp = 0;
951
        ++__temp;
952
 
953
        // The Header information goes at the Beginning of the Block.
954
        _Block_pair __bp =
955
          std::make_pair(reinterpret_cast<_Alloc_block*>
956
                         (__temp + __num_bitmaps),
957
                         reinterpret_cast<_Alloc_block*>
958
                         (__temp + __num_bitmaps)
959
                         + _S_block_size - 1);
960
 
961
        // Fill the Vector with this information.
962
        _S_mem_blocks.push_back(__bp);
963
 
964
        size_t __bit_mask = 0; // 0 Indicates all Allocated.
965
        __bit_mask = ~__bit_mask; // 1 Indicates all Free.
966
 
967
        for (size_t __i = 0; __i < __num_bitmaps; ++__i)
968
          __temp[__i] = __bit_mask;
969
 
970
        _S_block_size *= 2;
971
      }
972
 
973
 
974
      static _BPVector _S_mem_blocks;
975
      static size_t _S_block_size;
976
      static __gnu_cxx::balloc::
977
      _Bitmap_counter<_Alloc_block*> _S_last_request;
978
      static typename _BPVector::size_type _S_last_dealloc_index;
979
#if defined __GTHREADS
980
      static _Mutex _S_mut;
981
#endif
982
 
983
    public:
984
 
985
      /** @brief  Allocates memory for a single object of size
986
       *  sizeof(_Tp).
987
       *
988
       *  @throw  std::bad_alloc. If memory can not be allocated.
989
       *
990
       *  @detail  Complexity: Worst case complexity is O(N), but that
991
       *  is hardly ever hit. If and when this particular case is
992
       *  encountered, the next few cases are guaranteed to have a
993
       *  worst case complexity of O(1)!  That's why this function
994
       *  performs very well on average. You can consider this
995
       *  function to have a complexity referred to commonly as:
996
       *  Amortized Constant time.
997
       */
998
      pointer
999
      _M_allocate_single_object() throw(std::bad_alloc)
1000
      {
1001
#if defined __GTHREADS
1002
        _Auto_Lock __bit_lock(&_S_mut);
1003
#endif
1004
 
1005
        // The algorithm is something like this: The last_request
1006
        // variable points to the last accessed Bit Map. When such a
1007
        // condition occurs, we try to find a free block in the
1008
        // current bitmap, or succeeding bitmaps until the last bitmap
1009
        // is reached. If no free block turns up, we resort to First
1010
        // Fit method.
1011
 
1012
        // WARNING: Do not re-order the condition in the while
1013
        // statement below, because it relies on C++'s short-circuit
1014
        // evaluation. The return from _S_last_request->_M_get() will
1015
        // NOT be dereference able if _S_last_request->_M_finished()
1016
        // returns true. This would inevitably lead to a NULL pointer
1017
        // dereference if tinkered with.
1018
        while (_S_last_request._M_finished() == false
1019
               && (*(_S_last_request._M_get()) == 0))
1020
          {
1021
            _S_last_request.operator++();
1022
          }
1023
 
1024
        if (__builtin_expect(_S_last_request._M_finished() == true, false))
1025
          {
1026
            // Fall Back to First Fit algorithm.
1027
            typedef typename
1028
              __gnu_cxx::balloc::_Ffit_finder<_Alloc_block*> _FFF;
1029
            _FFF __fff;
1030
            typedef typename _BPVector::iterator _BPiter;
1031
            _BPiter __bpi =
1032
              __gnu_cxx::balloc::__find_if
1033
              (_S_mem_blocks.begin(), _S_mem_blocks.end(),
1034
               __gnu_cxx::balloc::_Functor_Ref<_FFF>(__fff));
1035
 
1036
            if (__bpi != _S_mem_blocks.end())
1037
              {
1038
                // Search was successful. Ok, now mark the first bit from
1039
                // the right as 0, meaning Allocated. This bit is obtained
1040
                // by calling _M_get() on __fff.
1041
                size_t __nz_bit = _Bit_scan_forward(*__fff._M_get());
1042
                balloc::__bit_allocate(__fff._M_get(), __nz_bit);
1043
 
1044
                _S_last_request._M_reset(__bpi - _S_mem_blocks.begin());
1045
 
1046
                // Now, get the address of the bit we marked as allocated.
1047
                pointer __ret = reinterpret_cast<pointer>
1048
                  (__bpi->first + __fff._M_offset() + __nz_bit);
1049
                size_t* __puse_count =
1050
                  reinterpret_cast<size_t*>
1051
                  (__bpi->first)
1052
                  - (__gnu_cxx::balloc::__num_bitmaps(*__bpi) + 1);
1053
 
1054
                ++(*__puse_count);
1055
                return __ret;
1056
              }
1057
            else
1058
              {
1059
                // Search was unsuccessful. We Add more memory to the
1060
                // pool by calling _S_refill_pool().
1061
                _S_refill_pool();
1062
 
1063
                // _M_Reset the _S_last_request structure to the first
1064
                // free block's bit map.
1065
                _S_last_request._M_reset(_S_mem_blocks.size() - 1);
1066
 
1067
                // Now, mark that bit as allocated.
1068
              }
1069
          }
1070
 
1071
        // _S_last_request holds a pointer to a valid bit map, that
1072
        // points to a free block in memory.
1073
        size_t __nz_bit = _Bit_scan_forward(*_S_last_request._M_get());
1074
        balloc::__bit_allocate(_S_last_request._M_get(), __nz_bit);
1075
 
1076
        pointer __ret = reinterpret_cast<pointer>
1077
          (_S_last_request._M_base() + _S_last_request._M_offset() + __nz_bit);
1078
 
1079
        size_t* __puse_count = reinterpret_cast<size_t*>
1080
          (_S_mem_blocks[_S_last_request._M_where()].first)
1081
          - (__gnu_cxx::balloc::
1082
             __num_bitmaps(_S_mem_blocks[_S_last_request._M_where()]) + 1);
1083
 
1084
        ++(*__puse_count);
1085
        return __ret;
1086
      }
1087
 
1088
      /** @brief  Deallocates memory that belongs to a single object of
1089
       *  size sizeof(_Tp).
1090
       *
1091
       *  @detail  Complexity: O(lg(N)), but the worst case is not hit
1092
       *  often!  This is because containers usually deallocate memory
1093
       *  close to each other and this case is handled in O(1) time by
1094
       *  the deallocate function.
1095
       */
1096
      void
1097
      _M_deallocate_single_object(pointer __p) throw()
1098
      {
1099
#if defined __GTHREADS
1100
        _Auto_Lock __bit_lock(&_S_mut);
1101
#endif
1102
        _Alloc_block* __real_p = reinterpret_cast<_Alloc_block*>(__p);
1103
 
1104
        typedef typename _BPVector::iterator _Iterator;
1105
        typedef typename _BPVector::difference_type _Difference_type;
1106
 
1107
        _Difference_type __diff;
1108
        long __displacement;
1109
 
1110
        _BALLOC_ASSERT(_S_last_dealloc_index >= 0);
1111
 
1112
 
1113
        if (__gnu_cxx::balloc::_Inclusive_between<_Alloc_block*>
1114
            (__real_p)
1115
            (_S_mem_blocks[_S_last_dealloc_index]))
1116
          {
1117
            _BALLOC_ASSERT(_S_last_dealloc_index <= _S_mem_blocks.size() - 1);
1118
 
1119
            // Initial Assumption was correct!
1120
            __diff = _S_last_dealloc_index;
1121
            __displacement = __real_p - _S_mem_blocks[__diff].first;
1122
          }
1123
        else
1124
          {
1125
            _Iterator _iter =
1126
              __gnu_cxx::balloc::
1127
              __find_if(_S_mem_blocks.begin(),
1128
                        _S_mem_blocks.end(),
1129
                        __gnu_cxx::balloc::
1130
                        _Inclusive_between<_Alloc_block*>(__real_p));
1131
 
1132
            _BALLOC_ASSERT(_iter != _S_mem_blocks.end());
1133
 
1134
            __diff = _iter - _S_mem_blocks.begin();
1135
            __displacement = __real_p - _S_mem_blocks[__diff].first;
1136
            _S_last_dealloc_index = __diff;
1137
          }
1138
 
1139
        // Get the position of the iterator that has been found.
1140
        const size_t __rotate = (__displacement
1141
                                 % size_t(balloc::bits_per_block));
1142
        size_t* __bitmapC =
1143
          reinterpret_cast<size_t*>
1144
          (_S_mem_blocks[__diff].first) - 1;
1145
        __bitmapC -= (__displacement / size_t(balloc::bits_per_block));
1146
 
1147
        balloc::__bit_free(__bitmapC, __rotate);
1148
        size_t* __puse_count = reinterpret_cast<size_t*>
1149
          (_S_mem_blocks[__diff].first)
1150
          - (__gnu_cxx::balloc::__num_bitmaps(_S_mem_blocks[__diff]) + 1);
1151
 
1152
        _BALLOC_ASSERT(*__puse_count != 0);
1153
 
1154
        --(*__puse_count);
1155
 
1156
        if (__builtin_expect(*__puse_count == 0, false))
1157
          {
1158
            _S_block_size /= 2;
1159
 
1160
            // We can safely remove this block.
1161
            // _Block_pair __bp = _S_mem_blocks[__diff];
1162
            this->_M_insert(__puse_count);
1163
            _S_mem_blocks.erase(_S_mem_blocks.begin() + __diff);
1164
 
1165
            // Reset the _S_last_request variable to reflect the
1166
            // erased block. We do this to protect future requests
1167
            // after the last block has been removed from a particular
1168
            // memory Chunk, which in turn has been returned to the
1169
            // free list, and hence had been erased from the vector,
1170
            // so the size of the vector gets reduced by 1.
1171
            if ((_Difference_type)_S_last_request._M_where() >= __diff--)
1172
              _S_last_request._M_reset(__diff);
1173
 
1174
            // If the Index into the vector of the region of memory
1175
            // that might hold the next address that will be passed to
1176
            // deallocated may have been invalidated due to the above
1177
            // erase procedure being called on the vector, hence we
1178
            // try to restore this invariant too.
1179
            if (_S_last_dealloc_index >= _S_mem_blocks.size())
1180
              {
1181
                _S_last_dealloc_index =(__diff != -1 ? __diff : 0);
1182
                _BALLOC_ASSERT(_S_last_dealloc_index >= 0);
1183
              }
1184
          }
1185
      }
1186
 
1187
    public:
1188
      bitmap_allocator() throw()
1189
      { }
1190
 
1191
      bitmap_allocator(const bitmap_allocator&)
1192
      { }
1193
 
1194
      template<typename _Tp1>
1195
        bitmap_allocator(const bitmap_allocator<_Tp1>&) throw()
1196
        { }
1197
 
1198
      ~bitmap_allocator() throw()
1199
      { }
1200
 
1201
      pointer
1202
      allocate(size_type __n)
1203
      {
1204
        if (__builtin_expect(__n > this->max_size(), false))
1205
          std::__throw_bad_alloc();
1206
 
1207
        if (__builtin_expect(__n == 1, true))
1208
          return this->_M_allocate_single_object();
1209
        else
1210
          {
1211
            const size_type __b = __n * sizeof(value_type);
1212
            return reinterpret_cast<pointer>(::operator new(__b));
1213
          }
1214
      }
1215
 
1216
      pointer
1217
      allocate(size_type __n, typename bitmap_allocator<void>::const_pointer)
1218
      { return allocate(__n); }
1219
 
1220
      void
1221
      deallocate(pointer __p, size_type __n) throw()
1222
      {
1223
        if (__builtin_expect(__p != 0, true))
1224
          {
1225
            if (__builtin_expect(__n == 1, true))
1226
              this->_M_deallocate_single_object(__p);
1227
            else
1228
              ::operator delete(__p);
1229
          }
1230
      }
1231
 
1232
      pointer
1233
      address(reference __r) const
1234
      { return &__r; }
1235
 
1236
      const_pointer
1237
      address(const_reference __r) const
1238
      { return &__r; }
1239
 
1240
      size_type
1241
      max_size() const throw()
1242
      { return size_type(-1) / sizeof(value_type); }
1243
 
1244
      void
1245
      construct(pointer __p, const_reference __data)
1246
      { ::new(__p) value_type(__data); }
1247
 
1248
      void
1249
      destroy(pointer __p)
1250
      { __p->~value_type(); }
1251
    };
1252
 
1253
  template<typename _Tp1, typename _Tp2>
1254
    bool
1255
    operator==(const bitmap_allocator<_Tp1>&,
1256
               const bitmap_allocator<_Tp2>&) throw()
1257
    { return true; }
1258
 
1259
  template<typename _Tp1, typename _Tp2>
1260
    bool
1261
    operator!=(const bitmap_allocator<_Tp1>&,
1262
               const bitmap_allocator<_Tp2>&) throw()
1263
  { return false; }
1264
 
1265
  // Static member definitions.
1266
  template<typename _Tp>
1267
    typename bitmap_allocator<_Tp>::_BPVector
1268
    bitmap_allocator<_Tp>::_S_mem_blocks;
1269
 
1270
  template<typename _Tp>
1271
    size_t bitmap_allocator<_Tp>::_S_block_size =
1272
    2 * size_t(balloc::bits_per_block);
1273
 
1274
  template<typename _Tp>
1275
    typename __gnu_cxx::bitmap_allocator<_Tp>::_BPVector::size_type
1276
    bitmap_allocator<_Tp>::_S_last_dealloc_index = 0;
1277
 
1278
  template<typename _Tp>
1279
    __gnu_cxx::balloc::_Bitmap_counter
1280
  <typename bitmap_allocator<_Tp>::_Alloc_block*>
1281
    bitmap_allocator<_Tp>::_S_last_request(_S_mem_blocks);
1282
 
1283
#if defined __GTHREADS
1284
  template<typename _Tp>
1285
    __gnu_cxx::_Mutex
1286
    bitmap_allocator<_Tp>::_S_mut;
1287
#endif
1288
 
1289
 
1290
}
1291
 
1292
#endif 
1293
 
1294
//  LocalWords:  namespace GTHREADS bool const gthread endif Mutex mutex

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.