Stxxl  1.4.0
include/stxxl/bits/mng/typed_block.h
Go to the documentation of this file.
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
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines