Changeset 18183

Show
Ignore:
Timestamp:
08/24/08 21:49:13 (5 months ago)
Author:
frsyuki
Message:

lang/c/mpio: added mp::coroutine, mp::async, mp::byte_array, mp::short_queue, removed mp::io

Location:
lang/c/mpio/trunk/mp
Files:
24 added
5 removed
10 modified

Legend:

Unmodified
Added
Removed
  • lang/c/mpio/trunk/mp/Makefile

    r6840 r18183  
    11 
    2 NEED_PREPROCESS = event_class.h event_impl.h dispatch.h ios.h io.h mempool.h sparse_array.h 
     2NEED_PREPROCESS = event.h event_impl.h \ 
     3                  utility.h \ 
     4                  dispatch.h dispatch_impl.h \ 
     5                  io.h io_impl.h ios.h \ 
     6                  state.h \ 
     7                  byte_array.h byte_array_impl.h \ 
     8                  mempool.h mempool_impl.h \ 
     9                  sparse_array.h sparse_array_impl.h \ 
     10                  short_queue.h short_queue_impl.h \ 
     11                  buffer.h buffer_impl.h \ 
     12                  object_callback.h \ 
     13                  object_initializer.h \ 
     14                  async.h async_impl.h \ 
     15                  serialize.h \ 
     16 
    317all: $(NEED_PREPROCESS) 
    418 
     
    620        ruby -e '\ 
    721                def args(n, &block) ;\ 
    8                         Array.new(n) {|i| yield i+1 } .join(", ") ;\ 
     22                        Array.new(n) {|i| yield i+1} .join(", ") ;\ 
    923                end ;\ 
    10                 code = ARGF.read ;\ 
    11                 code.gsub!(/^MP_ARGS_BEGIN$$(.*?)^MP_ARGS_END$$/m) {|s| ;\ 
    12                         re = [] ;\ 
    13                         1.upto(15) {|n| \ 
    14                                 m = s.split("\n")[1..-2].join("\n") ;\ 
    15                                 m.gsub! /MP_ARGS_TEMPLATE/,   args(n) {|i| "typename A#{i}" } ;\ 
    16                                 m.gsub! /MP_ARGS_PARAMS/, args(n) {|i| "A#{i} a#{i}" } ;\ 
    17                                 m.gsub! /MP_ARGS_FUNC/,       args(n) {|i| "a#{i}" } ;\ 
    18                                 re << m ;\ 
     24                src = ARGF.read ;\ 
     25                src.gsub!(/^MP_ARGS_BEGIN$$(.*?)^MP_ARGS_END$$/m) {|code| ;\ 
     26                        result = [] ;\ 
     27                        1.upto(15) {|n| ;\ 
     28                                line = code.split("\n")[1..-2].join("\n") ;\ 
     29                                line.gsub!(/MP_ARGS_TEMPLATE/,   args(n) {|i| "typename A#{i}" }) ;\ 
     30                                line.gsub!(/MP_ARGS_PARAMS_PTR/, args(n) {|i| "A#{i}* a#{i}"   }) ;\ 
     31                                line.gsub!(/MP_ARGS_PARAMS_REF/, args(n) {|i| "A#{i}& a#{i}"   }) ;\ 
     32                                line.gsub!(/MP_ARGS_PARAMS/,     args(n) {|i| "A#{i} a#{i}"    }) ;\ 
     33                                line.gsub!(/MP_ARGS_FUNC/,       args(n) {|i| "a#{i}"          }) ;\ 
     34                                line.gsub!(/MP_ARGS_TYPES_PTR/,  args(n) {|i| "A#{i}*"    }) ;\ 
     35                                line.gsub!(/MP_ARGS_TYPES_REF/,  args(n) {|i| "A#{i}&"    }) ;\ 
     36                                line.gsub!(/MP_ARGS_TYPES/,      args(n) {|i| "A#{i}"     }) ;\ 
     37                                line.gsub!(/MP_ARGS_ITERATOR_BEGIN$$(.*?)^MP_ARGS_ITERATOR_END$$/m) {|sub| ;\ 
     38                                        subresult = [] ;\ 
     39                                        subline = sub.split("\n")[1..-2].join("\n") ;\ 
     40                                        1.upto(n) {|it| ;\ 
     41                                                sublineit = subline.dup ;\ 
     42                                                sublineit.gsub!(/MP_ARGS_ITERATOR_PARAM/,    "a#{it}") ;\ 
     43                                                sublineit.gsub!(/MP_ARGS_ITERATOR_TYPE_PTR/, "A#{it}*") ;\ 
     44                                                sublineit.gsub!(/MP_ARGS_ITERATOR_TYPE_REF/, "A#{it}&") ;\ 
     45                                                sublineit.gsub!(/MP_ARGS_ITERATOR_TYPE/,     "A#{it}") ;\ 
     46                                                sublineit.gsub!(/\[MP_ARGS_ITERATOR\]/,      "#{it}" ) ;\ 
     47                                                if it == 1 ;\ 
     48                                                        sublineit.gsub!(/MP_ARGS_ITERATOR_COLON/, " " ) ;\ 
     49                                                else ;\ 
     50                                                        sublineit.gsub!(/MP_ARGS_ITERATOR_COLON/, "," ) ;\ 
     51                                                end ;\ 
     52                                                subresult << sublineit ;\ 
     53                                        } ;\ 
     54                                        subresult.join("\n") ;\ 
     55                                } ;\ 
     56                                result << line ;\ 
    1957                        } ;\ 
    20                         re.join("\n") ;\ 
     58                        result.join("\n") ;\ 
    2159                } ;\ 
    22                 puts code' \ 
     60                puts src' \ 
    2361        $< > $@ 
    2462 
  • lang/c/mpio/trunk/mp/dispatch.pre.h

    r6840 r18183  
     1// 
     2// mp::dispatch 
     3// 
     4// Copyright (C) 2008 FURUHASHI Sadayuki 
     5// 
     6//    Licensed under the Apache License, Version 2.0 (the "License"); 
     7//    you may not use this file except in compliance with the License. 
     8//    You may obtain a copy of the License at 
     9// 
     10//        http://www.apache.org/licenses/LICENSE-2.0 
     11// 
     12//    Unless required by applicable law or agreed to in writing, software 
     13//    distributed under the License is distributed on an "AS IS" BASIS, 
     14//    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
     15//    See the License for the specific language governing permissions and 
     16//    limitations under the License. 
     17// 
     18 
    119#ifndef MP_DISPATCH_H__ 
    220#define MP_DISPATCH_H__ 
     
    3149        inline const data_t& data(int fd) const; 
    3250        int run(void); 
     51        void end(void); 
    3352private: 
    3453        struct cb_t { 
     
    4463        typedef event<cb_t> event_t; 
    4564        event_t m_event; 
     65        volatile sig_atomic_t m_end_flag; 
    4666}; 
    4767 
     
    6080        int modify(int fd, short oldevent, short newevent, callback_t callback); 
    6181        int run(void); 
     82        void end(void); 
    6283private: 
    6384        struct cb_t { 
     
    6889        typedef event<cb_t> event_t; 
    6990        event_t m_event; 
     91        volatile sig_atomic_t m_end_flag; 
    7092}; 
    71  
    72  
    73 template <typename Data> 
    74 dispatch<Data>::dispatch() {} 
    75 dispatch<void>::dispatch() {} 
    76  
    77 template <typename Data> 
    78 int dispatch<Data>::remove(int fd, short oldevent) 
    79 { 
    80         return m_event.remove(fd, oldevent); 
    81 } 
    82 int dispatch<void>::remove(int fd, short oldevent) 
    83 { 
    84         return m_event.remove(fd, oldevent); 
    85 } 
    86  
    87 template <typename Data> 
    88 int dispatch<Data>::modify(int fd, short oldevent, short newevent) 
    89 { 
    90         return m_event.modify(fd, oldevent, newevent); 
    91 } 
    92 int dispatch<void>::modify(int fd, short oldevent, short newevent) 
    93 { 
    94         return m_event.modify(fd, oldevent, newevent); 
    95 } 
    96  
    97 template <typename Data> 
    98 int dispatch<Data>::modify(int fd, callback_t callback) 
    99 { 
    100         m_event.data(fd).callback = callback; 
    101         return 0; 
    102 } 
    103 int dispatch<void>::modify(int fd, callback_t callback) 
    104 { 
    105         m_event.data(fd).callback = callback; 
    106         return 0; 
    107 } 
    108  
    109 template <typename Data> 
    110 int dispatch<Data>::modify(int fd, callback_t callback, data_t data) 
    111 { 
    112         m_event.data(fd).callback = callback; 
    113         m_event.data(fd).data = data; 
    114         return 0; 
    115 } 
    116  
    117 template <typename Data> 
    118 int dispatch<Data>::modify(int fd, short oldevent, short newevent, callback_t callback) 
    119 { 
    120         m_event.data(fd).callback = callback; 
    121         return modify(fd, oldevent, newevent); 
    122 } 
    123 int dispatch<void>::modify(int fd, short oldevent, short newevent, callback_t callback) 
    124 { 
    125         m_event.data(fd).callback = callback; 
    126         return modify(fd, oldevent, newevent); 
    127 } 
    128  
    129 template <typename Data> 
    130 int dispatch<Data>::modify(int fd, short oldevent, short newevent, callback_t callback, data_t data) 
    131 { 
    132         m_event.data(fd).callback = callback; 
    133         m_event.data(fd).data = data; 
    134         return modify(fd, oldevent, newevent); 
    135 } 
    136  
    137 template <typename Data> 
    138 Data& dispatch<Data>::data(int fd) 
    139 { 
    140         return m_event.data(fd).data; 
    141 } 
    142  
    143 template <typename Data> 
    144 const Data& dispatch<Data>::data(int fd) const 
    145 { 
    146         return m_event.data(fd).data; 
    147 } 
    148  
    149 template <typename Data> 
    150 int dispatch<Data>::run(void) 
    151 { 
    152         cb_t* pcb; 
    153         int fd; 
    154         short event; 
    155         int ret; 
    156         while(1) { 
    157                 while( m_event.next(&fd, &event, &pcb) ) { 
    158                         ret = pcb->callback(fd, event, pcb->data); 
    159                         if( ret != 0 ) { return ret; } 
    160                 } 
    161                 if( (ret = m_event.wait()) < 0 ) { return ret; } 
    162         } 
    163 } 
    164 int dispatch<void>::run(void) 
    165 { 
    166         cb_t* pcb; 
    167         int fd; 
    168         short event; 
    169         int ret; 
    170         while(1) { 
    171                 while( m_event.next(&fd, &event, &pcb) ) { 
    172                         ret = pcb->callback(fd, event); 
    173                         if( ret != 0 ) { return ret; } 
    174                 } 
    175                 if( (ret = m_event.wait()) < 0 ) { return ret; } 
    176         } 
    177 } 
    17893 
    17994 
    18095}  // namespace mp 
    18196 
     97#include "mp/dispatch_impl.h" 
     98 
    18299#endif /* mp/dispatch.h */ 
    183100 
  • lang/c/mpio/trunk/mp/event_impl.pre.h

    r6840 r18183  
     1// 
     2// mp::event 
     3// 
     4// Copyright (C) 2008 FURUHASHI Sadayuki 
     5// 
     6//    Licensed under the Apache License, Version 2.0 (the "License"); 
     7//    you may not use this file except in compliance with the License. 
     8//    You may obtain a copy of the License at 
     9// 
     10//        http://www.apache.org/licenses/LICENSE-2.0 
     11// 
     12//    Unless required by applicable law or agreed to in writing, software 
     13//    distributed under the License is distributed on an "AS IS" BASIS, 
     14//    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
     15//    See the License for the specific language governing permissions and 
     16//    limitations under the License. 
     17// 
     18 
    119#ifndef MP_EVENT_IMPL_H__ 
    220#define MP_EVENT_IMPL_H__ 
  • lang/c/mpio/trunk/mp/functional.h

    r7786 r18183  
     1// 
     2// mp::functional 
     3// 
     4// Copyright (C) 2008 FURUHASHI Sadayuki 
     5// 
     6//    Licensed under the Apache License, Version 2.0 (the "License"); 
     7//    you may not use this file except in compliance with the License. 
     8//    You may obtain a copy of the License at 
     9// 
     10//        http://www.apache.org/licenses/LICENSE-2.0 
     11// 
     12//    Unless required by applicable law or agreed to in writing, software 
     13//    distributed under the License is distributed on an "AS IS" BASIS, 
     14//    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
     15//    See the License for the specific language governing permissions and 
     16//    limitations under the License. 
     17// 
     18 
    119#ifndef MP_FUNCTIONAL_H__ 
    220#define MP_FUNCTIONAL_H__ 
  • lang/c/mpio/trunk/mp/mempool.pre.h

    r6840 r18183  
    1 #ifndef MP_POOL_H__ 
    2 #define MP_POOL_H__ 
     1// 
     2// mp::mempool 
     3// 
     4// Copyright (C) 2008 FURUHASHI Sadayuki 
     5// 
     6//    Licensed under the Apache License, Version 2.0 (the "License"); 
     7//    you may not use this file except in compliance with the License. 
     8//    You may obtain a copy of the License at 
     9// 
     10//        http://www.apache.org/licenses/LICENSE-2.0 
     11// 
     12//    Unless required by applicable law or agreed to in writing, software 
     13//    distributed under the License is distributed on an "AS IS" BASIS, 
     14//    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
     15//    See the License for the specific language governing permissions and 
     16//    limitations under the License. 
     17// 
     18 
     19#ifndef MP_MEMPOOL_H__ 
     20#define MP_MEMPOOL_H__ 
    321 
    422#include <stdexcept> 
    523#include <cstdlib> 
     24#include <limits> 
     25#include "mp/utility.h" 
    626 
    727#ifndef MP_POOL_DEFAULT_ALLOCATION_SIZE 
     
    1333#endif 
    1434 
     35#ifndef MP_POOL_ALLOCATOR_DEFAULT_OBJECTS_IN_CHUNK 
     36#define MP_POOL_ALLOCATOR_DEFAULT_OBJECTS_IN_CHUNK 1024 
     37#endif 
     38 
    1539namespace mp { 
    1640 
    1741static const size_t POOL_DEFAULT_ALLOCATION_SIZE = MP_POOL_DEFAULT_ALLOCATION_SIZE; 
    1842static const size_t POOL_DEFAULT_LOTS_IN_CHUNK = MP_POOL_DEFAULT_LOTS_IN_CHUNK; 
     43static const size_t POOL_ALLOCATOR_DEFAULT_OBJECTS_IN_CHUNK = MP_POOL_ALLOCATOR_DEFAULT_OBJECTS_IN_CHUNK; 
    1944 
    2045template < size_t EstimatedAllocationSize = POOL_DEFAULT_ALLOCATION_SIZE, 
     
    2449        mempool(); 
    2550        ~mempool(); 
    26 public: 
     51 
     52public: 
     53        //! Allocate memory from the pool. 
     54        /* The allocated memory have to be freed using free() function. */ 
    2755        inline void* malloc(size_t size); 
     56 
     57        //! Free the allocated memory. 
    2858        inline void free(void* x); 
     59 
     60        //! Template version of malloc() 
    2961        template <size_t size> 
    3062                inline void* malloc(); 
    31 public: 
    32         template <typename T> 
    33         inline void destroy(T* x) { 
    34                 x->~T(); 
    35                 this->free(x); 
    36         } 
    37         template <typename T> 
    38         inline T* construct() { 
    39                 return new( this->malloc<sizeof(T)>() ) T(); 
    40         } 
     63 
     64public: 
     65        //! Destroy the constructed object. 
     66        template <typename T> 
     67                inline void destroy(T* x); 
     68 
     69        //! Allocate memory from the pool and construct object. 
     70        template <typename T> 
     71                inline T* construct(); 
    4172MP_ARGS_BEGIN 
    4273        template <typename T, MP_ARGS_TEMPLATE> 
    43         inline T* construct(MP_ARGS_PARAMS) { 
    44                 return new( this->malloc<sizeof(T)>() ) T(MP_ARGS_FUNC); 
    45         } 
     74                inline T* construct(MP_ARGS_PARAMS); 
    4675MP_ARGS_END 
     76 
    4777private: 
    4878        struct chunk_t { 
     
    5686                chunk_t* chunk; 
    5787        }; 
     88 
    5889private: 
    5990        chunk_t* m_free; 
    6091        chunk_t* m_used; 
     92 
    6193private: 
    6294        void* expand_free(size_t req); 
    6395        void splice_to_used(chunk_t* chunk); 
    6496        void splice_to_free(chunk_t* chunk); 
     97 
    6598private: 
    6699        mempool(const mempool&); 
     
    68101 
    69102 
    70 template <size_t EstimatedAllocationSize, size_t OptimalLotsInChunk> 
    71 mempool<EstimatedAllocationSize, OptimalLotsInChunk>::mempool() 
    72 { 
    73         m_free = (chunk_t*)std::malloc(sizeof(chunk_t)); 
    74         if( m_free == NULL ) { throw std::bad_alloc(); } 
    75         m_used = (chunk_t*)std::malloc(sizeof(chunk_t)); 
    76         if( m_used == NULL ) { std::free(m_free); throw std::bad_alloc(); } 
    77         m_free->next = m_free; 
    78         m_free->prev = m_free; 
    79         m_used->next = m_used; 
    80         m_used->prev = m_used; 
    81 } 
    82  
    83 template <size_t EstimatedAllocationSize, size_t OptimalLotsInChunk> 
    84 mempool<EstimatedAllocationSize, OptimalLotsInChunk>::~mempool() 
    85 { 
    86         chunk_t* f = m_free->next; 
    87         while(f != m_free) { 
    88                 f = f->next; 
    89                 std::free(f->prev); 
     103template < typename ThreadTag = main_thread_tag, 
     104           size_t EstimatedAllocationSize = POOL_DEFAULT_ALLOCATION_SIZE, 
     105           size_t OptimalLotsInChunk = POOL_DEFAULT_LOTS_IN_CHUNK > 
     106class singleton_mempool { 
     107public: 
     108        typedef mempool<EstimatedAllocationSize, OptimalLotsInChunk> pool_type; 
     109 
     110        static void* malloc(size_t size) 
     111                { return pool().malloc(size); } 
     112 
     113        static void free(void* x) 
     114                { pool().free(x); } 
     115 
     116        template <size_t size> 
     117        static void* malloc() 
     118                { return pool().malloc<size>(); } 
     119 
     120public: 
     121        template <typename T> 
     122        static void destroy(T* x) 
     123                { return pool().destroy<T>(x); } 
     124 
     125        template <typename T> 
     126        static T* construct() 
     127                { return pool().construct<T>(); } 
     128MP_ARGS_BEGIN 
     129        template <typename T, MP_ARGS_TEMPLATE> 
     130        static T* construct(MP_ARGS_PARAMS) 
     131                { return pool().construct<T, MP_ARGS_TYPES>(MP_ARGS_FUNC); } 
     132MP_ARGS_END 
     133 
     134private: 
     135        static pool_type& pool() 
     136        { 
     137                static pool_type object; 
     138                return object; 
    90139        } 
    91         std::free(f); 
    92  
    93         f = m_used; 
    94         while(f->next != m_used) { 
    95                 f = f->next; 
    96                 std::free(f->prev); 
     140}; 
     141 
     142 
     143template < typename T, 
     144                typename ThreadTag = main_thread_tag, 
     145                size_t OptimalObjectsInChunk = POOL_ALLOCATOR_DEFAULT_OBJECTS_IN_CHUNK > 
     146class mempool_allocator { 
     147private: 
     148        typedef singleton_mempool<ThreadTag, sizeof(T), OptimalObjectsInChunk> pool; 
     149 
     150public: 
     151        typedef size_t size_type; 
     152        typedef ptrdiff_t difference_type; 
     153        typedef T* pointer; 
     154        typedef const T* const_pointer; 
     155        typedef T& reference; 
     156        typedef const T& const_reference; 
     157        typedef T value_type; 
     158 
     159        template <class U> 
     160        struct rebind { typedef mempool_allocator<U> other; }; 
     161 
     162        mempool_allocator() throw() {} 
     163        mempool_allocator(const mempool_allocator&) throw() {} 
     164        template <class U> mempool_allocator(const mempool_allocator<U>&) throw() {} 
     165 
     166        ~mempool_allocator() throw() {} 
     167 
     168        pointer address(reference r) 
     169                { return &r; } 
     170 
     171        const_pointer address(const_reference s) 
     172                { return &s; } 
     173 
     174        size_type max_size() throw() 
     175                { return std::numeric_limits<size_t>::max() / sizeof(T); } 
     176 
     177        pointer allocate(size_type num, const_pointer hint = 0) 
     178        { 
     179                const pointer p = static_cast<pointer>( pool::malloc(sizeof(T) * num) ); 
     180                if (p == 0) { throw std::bad_alloc(); } 
     181                return p; 
    97182        } 
    98         std::free(f); 
    99 } 
    100  
    101 template <size_t EstimatedAllocationSize, size_t OptimalLotsInChunk> 
    102 template <size_t size> 
    103 void* mempool<EstimatedAllocationSize, OptimalLotsInChunk>::malloc() 
    104 { 
    105         return this->malloc(size); 
    106 } 
    107  
    108 template <size_t EstimatedAllocationSize, size_t OptimalLotsInChunk> 
    109 void* mempool<EstimatedAllocationSize, OptimalLotsInChunk>::malloc(size_t size) 
    110 { 
    111         size_t req = size + sizeof(data_t); 
    112         for( chunk_t* f = m_free->next; f != m_free; f = f->next ) { 
    113                 if( f->free < req ) { continue; } 
    114                 data_t* data = reinterpret_cast<data_t*>( 
    115                                 ((char*)f) + sizeof(chunk_t) + f->size - f->free 
    116                                 ); 
    117                 f->lots++; 
    118                 f->free -= req; 
    119                 data->chunk = f; 
    120                 if( f->free < EstimatedAllocationSize + sizeof(chunk_t) ) { 
    121                         splice_to_used(f); 
    122                 } 
    123                 return ((char*)data) + sizeof(data_t); 
     183 
     184        void deallocate(pointer p, size_type num) 
     185        { 
     186                if(p == 0) { return; } 
     187                pool::free(p); 
    124188        } 
    125         return expand_free(req); 
    126 } 
    127  
    128 template <size_t EstimatedAllocationSize, size_t OptimalLotsInChunk> 
    129 void mempool<EstimatedAllocationSize, OptimalLotsInChunk>::free(void* x) 
    130 { 
    131         data_t* data = reinterpret_cast<data_t*>( ((char*)x) - sizeof(data_t) ); 
    132         chunk_t* chunk = data->chunk; 
    133         chunk->lots--; 
    134         if( chunk->lots == 0 ) { 
    135                 splice_to_free(chunk); 
    136         } 
    137 } 
    138  
    139 template <size_t EstimatedAllocationSize, size_t OptimalLotsInChunk> 
    140 void* mempool<EstimatedAllocationSize, OptimalLotsInChunk>::expand_free(size_t req) 
    141 { 
    142         const size_t default_chunk_size = (EstimatedAllocationSize + sizeof(chunk_t)) * OptimalLotsInChunk; 
    143         size_t chunk_size = req > default_chunk_size ? req : default_chunk_size; 
    144         chunk_t* n = (chunk_t*)std::malloc(sizeof(chunk_t) + chunk_size); 
    145         if( n == NULL ) { throw std::bad_alloc(); } 
    146         data_t* data = reinterpret_cast<data_t*>( ((char*)n) + sizeof(chunk_t) ); 
    147         n->lots = 1; 
    148         n->size = chunk_size; 
    149         n->free = chunk_size - req; 
    150         data->chunk = n; 
    151         if( n->free < EstimatedAllocationSize + sizeof(chunk_t) ) { 
    152                 n->prev = m_used; 
    153                 n->next = m_used->next; 
    154                 m_used->next->prev = n; 
    155                 m_used->next = n; 
    156         } else { 
    157                 n->prev = m_free; 
    158                 n->next = m_free->next; 
    159                 m_free->next->prev = n; 
    160                 m_free->next = n; 
    161         } 
    162         return ((char*)data) + sizeof(data_t); 
    163 } 
    164  
    165 template <size_t EstimatedAllocationSize, size_t OptimalLotsInChunk> 
    166 void mempool<EstimatedAllocationSize, OptimalLotsInChunk>::splice_to_used(chunk_t* chunk) 
    167 { 
    168         chunk->prev->next = chunk->next; 
    169         chunk->next->prev = chunk->prev; 
    170         chunk->prev = m_used; 
    171         chunk->next = m_used->next; 
    172         m_used->next->prev = chunk; 
    173         m_used->next = chunk; 
    174 } 
    175  
    176 template <size_t EstimatedAllocationSize, size_t OptimalLotsInChunk> 
    177 void mempool<EstimatedAllocationSize, OptimalLotsInChunk>::splice_to_free(chunk_t* chunk) 
    178 { 
    179         chunk->prev->next = chunk->next; 
    180         chunk->next->prev = chunk->prev; 
    181         chunk->next = m_free->next; 
    182         chunk->prev = m_free; 
    183         m_free->next->prev = chunk; 
    184         m_free->next = chunk; 
    185         chunk->free = chunk->size; 
    186 } 
     189 
     190        void construct(pointer p, const T& r) 
     191                { new ( reinterpret_cast<void*>(p) ) T(r); } 
     192 
     193        void destroy(pointer p) 
     194                { p->~T(); } 
     195}; 
    187196 
    188197 
    189198}  // namespace mp 
    190199 
     200template <class T1, class T2> 
     201bool operator==(const mp::mempool_allocator<T1>&, const mp::mempool_allocator<T2>&) throw() { return true; } 
     202 
     203template <class T1, class T2>