Stxxl
1.4.0
|
00001 /*************************************************************************** 00002 * include/stxxl/bits/mng/typed_block.h 00003 * 00004 * Part of the STXXL. See http://stxxl.sourceforge.net 00005 * 00006 * Copyright (C) 2002-2004 Roman Dementiev <dementiev@mpi-sb.mpg.de> 00007 * Copyright (C) 2008-2010 Andreas Beckmann <beckmann@cs.uni-frankfurt.de> 00008 * 00009 * Distributed under the Boost Software License, Version 1.0. 00010 * (See accompanying file LICENSE_1_0.txt or copy at 00011 * http://www.boost.org/LICENSE_1_0.txt) 00012 **************************************************************************/ 00013 00014 #ifndef STXXL_TYPED_BLOCK_HEADER 00015 #define STXXL_TYPED_BLOCK_HEADER 00016 00017 #include <stxxl/bits/io/request.h> 00018 #include <stxxl/bits/common/aligned_alloc.h> 00019 #include <stxxl/bits/mng/bid.h> 00020 00021 #ifndef STXXL_VERBOSE_TYPED_BLOCK 00022 #define STXXL_VERBOSE_TYPED_BLOCK STXXL_VERBOSE2 00023 #endif 00024 00025 00026 __STXXL_BEGIN_NAMESPACE 00027 00028 //! \ingroup mnglayer 00029 //! \{ 00030 00031 00032 template <unsigned bytes> 00033 class filler_struct__ 00034 { 00035 typedef unsigned char byte_type; 00036 byte_type filler_array_[bytes]; 00037 00038 public: 00039 filler_struct__() { STXXL_VERBOSE_TYPED_BLOCK("[" << (void *)this << "] filler_struct__ is constructed"); } 00040 }; 00041 00042 template <> 00043 class filler_struct__<0> 00044 { 00045 typedef unsigned char byte_type; 00046 00047 public: 00048 filler_struct__() { STXXL_VERBOSE_TYPED_BLOCK("[" << (void *)this << "] filler_struct__<> is constructed"); } 00049 }; 00050 00051 //! \brief Contains data elements for \c stxxl::typed_block , not intended for direct use 00052 template <class T, unsigned Size_> 00053 class element_block 00054 { 00055 public: 00056 typedef T type; 00057 typedef T value_type; 00058 typedef T & reference; 00059 typedef const T & const_reference; 00060 typedef type * pointer; 00061 typedef pointer iterator; 00062 typedef const type * const_iterator; 00063 00064 enum 00065 { 00066 size = Size_ //!< number of elements in the block 00067 }; 00068 00069 //! Array of elements of type T 00070 T elem[size]; 00071 00072 element_block() { STXXL_VERBOSE_TYPED_BLOCK("[" << (void *)this << "] element_block is constructed"); } 00073 00074 //! An operator to access elements in the block 00075 reference operator [] (int i) 00076 { 00077 return elem[i]; 00078 } 00079 00080 //! \brief Returns \c iterator pointing to the first element 00081 iterator begin() 00082 { 00083 return elem; 00084 } 00085 00086 //! \brief Returns \c const_iterator pointing to the first element 00087 const_iterator begin() const 00088 { 00089 return elem; 00090 } 00091 00092 //! \brief Returns \c const_iterator pointing to the first element 00093 const_iterator cbegin() const 00094 { 00095 return begin(); 00096 } 00097 00098 //! \brief Returns \c iterator pointing to the end element 00099 iterator end() 00100 { 00101 return elem + size; 00102 } 00103 00104 //! \brief Returns \c const_iterator pointing to the end element 00105 const_iterator end() const 00106 { 00107 return elem + size; 00108 } 00109 00110 //! \brief Returns \c const_iterator pointing to the end element 00111 const_iterator cend() const 00112 { 00113 return end(); 00114 } 00115 }; 00116 00117 //! \brief Contains BID references for \c stxxl::typed_block , not intended for direct use 00118 template <class T, unsigned Size_, unsigned RawSize_, unsigned NBids_ = 0> 00119 class block_w_bids : public element_block<T, Size_> 00120 { 00121 public: 00122 enum 00123 { 00124 raw_size = RawSize_, 00125 nbids = NBids_ 00126 }; 00127 00128 typedef BID<raw_size> bid_type; 00129 00130 //! Array of BID references 00131 bid_type ref[nbids]; 00132 00133 //! An operator to access bid references 00134 bid_type & operator () (int i) 00135 { 00136 return ref[i]; 00137 } 00138 00139 block_w_bids() { STXXL_VERBOSE_TYPED_BLOCK("[" << (void *)this << "] block_w_bids is constructed"); } 00140 }; 00141 00142 template <class T, unsigned Size_, unsigned RawSize_> 00143 class block_w_bids<T, Size_, RawSize_, 0>: public element_block<T, Size_> 00144 { 00145 public: 00146 enum 00147 { 00148 raw_size = RawSize_, 00149 nbids = 0 00150 }; 00151 00152 typedef BID<raw_size> bid_type; 00153 00154 block_w_bids() { STXXL_VERBOSE_TYPED_BLOCK("[" << (void *)this << "] block_w_bids<> is constructed"); } 00155 }; 00156 00157 //! \brief Contains per block information for \c stxxl::typed_block , not intended for direct use 00158 template <class T_, unsigned RawSize_, unsigned NBids_, class InfoType_ = void> 00159 class block_w_info : 00160 public block_w_bids<T_, ((RawSize_ - sizeof(BID<RawSize_>) * NBids_ - sizeof(InfoType_)) / sizeof(T_)), RawSize_, NBids_> 00161 { 00162 public: 00163 //! \brief Type of per block information element 00164 typedef InfoType_ info_type; 00165 00166 //! \brief Per block information element 00167 info_type info; 00168 00169 block_w_info() { STXXL_VERBOSE_TYPED_BLOCK("[" << (void *)this << "] block_w_info is constructed"); } 00170 }; 00171 00172 template <class T_, unsigned RawSize_, unsigned NBids_> 00173 class block_w_info<T_, RawSize_, NBids_, void>: 00174 public block_w_bids<T_, ((RawSize_ - sizeof(BID<RawSize_>) * NBids_) / sizeof(T_)), RawSize_, NBids_> 00175 { 00176 public: 00177 typedef void info_type; 00178 00179 block_w_info() { STXXL_VERBOSE_TYPED_BLOCK("[" << (void *)this << "] block_w_info<> is constructed"); } 00180 }; 00181 00182 //! \brief Contains per block filler for \c stxxl::typed_block , not intended for direct use 00183 template <typename BaseType_, unsigned FillSize_ = 0> 00184 class add_filler : 00185 public BaseType_ 00186 { 00187 private: 00188 //! \brief Per block filler element 00189 filler_struct__<FillSize_> filler; 00190 00191 public: 00192 add_filler() { STXXL_VERBOSE_TYPED_BLOCK("[" << (void *)this << "] add_filler is constructed"); } 00193 }; 00194 00195 template <typename BaseType_> 00196 class add_filler<BaseType_, 0>: 00197 public BaseType_ 00198 { 00199 public: 00200 add_filler() { STXXL_VERBOSE_TYPED_BLOCK("[" << (void *)this << "] add_filler<> is constructed"); } 00201 }; 00202 00203 //! \brief Helper to compute the size of the filler , not intended for direct use 00204 template <typename Tp_, unsigned RawSize_> 00205 class expand_struct : 00206 public add_filler<Tp_, RawSize_ - sizeof(Tp_)> 00207 { }; 00208 00209 //! \brief Block containing elements of fixed length 00210 00211 //! \tparam RawSize_ size of block in bytes 00212 //! \tparam T_ type of block's records 00213 //! \tparam NRef_ number of block references (BIDs) that can be stored in the block (default is 0) 00214 //! \tparam InfoType_ type of per block information (default is no information - void) 00215 //! 00216 //! The data array of type T_ is contained in the parent class \c stxxl::element_block, see related information there. 00217 //! The BID array of references is contained in the parent class \c stxxl::block_w_bids, see related information there. 00218 //! The "per block information" is contained in the parent class \c stxxl::block_w_info, see related information there. 00219 //! \warning If \c RawSize_ > 2MB object(s) of this type can not be allocated on the stack (as a 00220 //! function variable for example), because Linux POSIX library limits the stack size for the 00221 //! main thread to (2MB - system page size) 00222 template <unsigned RawSize_, class T_, unsigned NRef_ = 0, class InfoType_ = void> 00223 class typed_block : 00224 public expand_struct<block_w_info<T_, RawSize_, NRef_, InfoType_>, RawSize_> 00225 { 00226 typedef expand_struct<block_w_info<T_, RawSize_, NRef_, InfoType_>, RawSize_> Base; 00227 00228 public: 00229 typedef T_ value_type; 00230 typedef value_type & reference; 00231 typedef const value_type & const_reference; 00232 typedef value_type * pointer; 00233 typedef pointer iterator; 00234 typedef const value_type * const_pointer; 00235 typedef const_pointer const_iterator; 00236 00237 enum constants 00238 { 00239 raw_size = RawSize_, //!< size of block in bytes 00240 size = Base::size, //!< number of elements in block 00241 has_only_data = (raw_size == (size * sizeof(value_type))) //!< no meta info, bids or (non-empty) fillers included in the block, allows value_type array addressing across block boundaries 00242 }; 00243 00244 typedef BID<raw_size> bid_type; 00245 00246 typed_block() 00247 { 00248 STXXL_STATIC_ASSERT(sizeof(typed_block) == raw_size); 00249 STXXL_VERBOSE_TYPED_BLOCK("[" << (void *)this << "] typed_block is constructed"); 00250 #if 0 00251 assert(((long)this) % BLOCK_ALIGN == 0); 00252 #endif 00253 } 00254 00255 #if 0 00256 typed_block(const typed_block & tb) 00257 { 00258 STXXL_STATIC_ASSERT(sizeof(typed_block) == raw_size); 00259 STXXL_MSG("[" << (void *)this << "] typed_block is copy constructed from [" << (void *)&tb << "]"); 00260 STXXL_UNUSED(tb); 00261 } 00262 #endif 00263 00264 /*! \brief Writes block to the disk(s) 00265 *! \param bid block identifier, points the file(disk) and position 00266 *! \param on_cmpl completion handler 00267 *! \return \c pointer_ptr object to track status I/O operation after the call 00268 */ 00269 request_ptr write(const bid_type & bid, 00270 completion_handler on_cmpl = default_completion_handler()) 00271 { 00272 STXXL_VERBOSE_BLOCK_LIFE_CYCLE("BLC:write " << FMT_BID(bid)); 00273 return bid.storage->awrite(this, bid.offset, raw_size, on_cmpl); 00274 } 00275 00276 /*! \brief Reads block from the disk(s) 00277 *! \param bid block identifier, points the file(disk) and position 00278 *! \param on_cmpl completion handler 00279 *! \return \c pointer_ptr object to track status I/O operation after the call 00280 */ 00281 request_ptr read(const bid_type & bid, 00282 completion_handler on_cmpl = default_completion_handler()) 00283 { 00284 STXXL_VERBOSE_BLOCK_LIFE_CYCLE("BLC:read " << FMT_BID(bid)); 00285 return bid.storage->aread(this, bid.offset, raw_size, on_cmpl); 00286 } 00287 00288 static void * operator new (size_t bytes) 00289 { 00290 unsigned_type meta_info_size = bytes % raw_size; 00291 STXXL_VERBOSE1("typed::block operator new: Meta info size: " << meta_info_size); 00292 00293 void * result = aligned_alloc<BLOCK_ALIGN>(bytes - meta_info_size, meta_info_size); 00294 #ifdef STXXL_VALGRIND_TYPED_BLOCK_INITIALIZE_ZERO 00295 memset(result, 0, bytes); 00296 #endif 00297 char * tmp = (char *)result; 00298 tmp += RawSize_; 00299 while (tmp < ((char *)result) + bytes) 00300 { 00301 tmp += RawSize_; 00302 } 00303 return result; 00304 } 00305 00306 static void * operator new[] (size_t bytes) 00307 { 00308 unsigned_type meta_info_size = bytes % raw_size; 00309 STXXL_VERBOSE1("typed::block operator new[]: Meta info size: " << meta_info_size); 00310 00311 void * result = aligned_alloc<BLOCK_ALIGN>(bytes - meta_info_size, meta_info_size); 00312 #ifdef STXXL_VALGRIND_TYPED_BLOCK_INITIALIZE_ZERO 00313 memset(result, 0, bytes); 00314 #endif 00315 char * tmp = (char *)result; 00316 tmp += RawSize_; 00317 while (tmp < ((char *)result) + bytes) 00318 { 00319 tmp += RawSize_; 00320 } 00321 return result; 00322 } 00323 00324 static void * operator new (size_t /*bytes*/, void * ptr) // construct object in existing memory 00325 { 00326 return ptr; 00327 } 00328 00329 static void operator delete (void * ptr) 00330 { 00331 aligned_dealloc<BLOCK_ALIGN>(ptr); 00332 } 00333 00334 static void operator delete[] (void * ptr) 00335 { 00336 aligned_dealloc<BLOCK_ALIGN>(ptr); 00337 } 00338 00339 static void operator delete (void *, void *) 00340 { } 00341 00342 #if 1 00343 // STRANGE: implementing destructor makes g++ allocate 00344 // additional 4 bytes in the beginning of every array 00345 // of this type !? makes aligning to 4K boundaries difficult 00346 // 00347 // http://www.cc.gatech.edu/grads/j/Seung.Won.Jun/tips/pl/node4.html : 00348 // "One interesting thing is the array allocator requires more memory 00349 // than the array size multiplied by the size of an element, by a 00350 // difference of delta for metadata a compiler needs. It happens to 00351 // be 8 bytes long in g++." 00352 ~typed_block() 00353 { 00354 STXXL_VERBOSE_TYPED_BLOCK("[" << (void *)this << "] typed_block is destructed"); 00355 } 00356 #endif 00357 }; 00358 00359 //! \} 00360 00361 __STXXL_END_NAMESPACE 00362 00363 #endif // !STXXL_TYPED_BLOCK_HEADER 00364 // vim: et:ts=4:sw=4