Thrill  0.1
typed_block.hpp
Go to the documentation of this file.
1 /***************************************************************************
2  * foxxll/mng/typed_block.hpp
3  *
4  * Constructs a typed_block object containing as many elements elements plus
5  * some metadata as fits into the given block size.
6  *
7  * Part of FOXXLL. See http://foxxll.org
8  *
9  * Copyright (C) 2002-2004 Roman Dementiev <[email protected]>
10  * Copyright (C) 2008-2010 Andreas Beckmann <[email protected]>
11  * Copyright (C) 2013 Timo Bingmann <[email protected]>
12  *
13  * Distributed under the Boost Software License, Version 1.0.
14  * (See accompanying file LICENSE_1_0.txt or copy at
15  * http://www.boost.org/LICENSE_1_0.txt)
16  **************************************************************************/
17 
18 #ifndef FOXXLL_MNG_TYPED_BLOCK_HEADER
19 #define FOXXLL_MNG_TYPED_BLOCK_HEADER
20 
22 #include <foxxll/config.hpp>
23 #include <foxxll/io/request.hpp>
24 #include <foxxll/mng/bid.hpp>
25 
26 namespace foxxll {
27 
28 #ifdef FOXXLL_VERBOSE_TYPED_BLOCK
29 constexpr bool debug_typed_block = true;
30 #else
31 constexpr bool debug_typed_block = false;
32 #endif
33 
34 //! \addtogroup foxxll_mnglayer
35 //! \{
36 
37 //! Block Manager Internals \internal
38 namespace mng_local {
39 
40 //! \defgroup foxxll_mnglayer_internals Internals
41 //! \ingroup foxxll_mnglayer
42 //! Internals and support classes
43 //! \{
44 
45 template <size_t Bytes>
47 {
48  using byte_type = unsigned char;
50 
51 public:
53  {
54  TLX_LOGC(debug_typed_block)
55  << "[" << static_cast<void*>(this) << "] filler_struct is constructed";
56  }
57 };
58 
59 template <>
60 class filler_struct<0>
61 {
62  using byte_type = unsigned char;
63 
64 public:
66  {
67  TLX_LOGC(debug_typed_block)
68  << "[" << static_cast<void*>(this) << "] filler_struct<> is constructed";
69  }
70 };
71 
72 //! Contains data elements for \c foxxll::typed_block , not intended for direct use.
73 template <typename Type, size_t kSize>
75 {
76 public:
77  using type = Type;
78  using value_type = Type;
79  using reference = Type &;
80  using const_reference = const Type &;
81  using pointer = type *;
82  using iterator = pointer;
83  using const_iterator = const type *;
84 
85  static constexpr size_t size = kSize; //!< number of elements in the block
86 
87  //! Array of elements of type Type
88  value_type elem[kSize];
89 
91  {
92  TLX_LOGC(debug_typed_block)
93  << "[" << static_cast<void*>(this) << "] element_block is constructed";
94  }
95 
96  //! An operator to access elements in the block
97  reference operator [] (size_t i)
98  {
99  return elem[i];
100  }
101 
102  //! Returns \c iterator pointing to the first element.
104  {
105  return elem;
106  }
107 
108  //! Returns \c const_iterator pointing to the first element.
110  {
111  return elem;
112  }
113 
114  //! Returns \c const_iterator pointing to the first element.
116  {
117  return begin();
118  }
119 
120  //! Returns \c iterator pointing to the end element.
122  {
123  return elem + size;
124  }
125 
126  //! Returns \c const_iterator pointing to the end element.
128  {
129  return elem + size;
130  }
131 
132  //! Returns \c const_iterator pointing to the end element.
134  {
135  return end();
136  }
137 };
138 
139 //! Contains BID references for \c foxxll::typed_block , not intended for direct use.
140 template <typename Type, size_t Size, size_t RawSize, size_t NBids = 0>
141 class block_w_bids : public element_block<Type, Size>
142 {
143 public:
144  static constexpr size_t raw_size = RawSize;
145  static constexpr size_t kNBIDs = NBids;
146 
148 
149  //! Array of BID references
150  bid_type ref[kNBIDs];
151 
152  //! An operator to access bid references
153  bid_type& operator () (size_t i)
154  {
155  return ref[i];
156  }
157 
159  {
160  TLX_LOGC(debug_typed_block)
161  << "[" << static_cast<void*>(this) << "] block_w_bids is constructed";
162  }
163 };
164 
165 template <typename Type, size_t Size, size_t RawSize>
166 class block_w_bids<Type, Size, RawSize, 0>
167  : public element_block<Type, Size>
168 {
169 public:
170  static constexpr size_t raw_size = RawSize;
171  static constexpr size_t kNBIDs = 0;
172 
174 
176  {
177  TLX_LOGC(debug_typed_block)
178  << "[" << static_cast<void*>(this) << "] block_w_bids<> is constructed";
179  }
180 };
181 
182 //! Contains per block information for \c foxxll::typed_block , not intended for direct use.
183 template <typename Type, size_t RawSize, size_t NBids, typename MetaInfoType = void>
185  : public block_w_bids<Type, ((RawSize - sizeof(BID<RawSize>)* NBids - sizeof(MetaInfoType)) / sizeof(Type)), RawSize, NBids>
186 {
187 public:
188  //! Type of per block information element.
189  using info_type = MetaInfoType;
190 
191  //! Per block information element.
193 
195  {
196  TLX_LOGC(debug_typed_block)
197  << "[" << static_cast<void*>(this) << "] block_w_info is constructed";
198  }
199 };
200 
201 template <typename Type, size_t RawSize, size_t NBids>
202 class block_w_info<Type, RawSize, NBids, void>
203  : public block_w_bids<Type, ((RawSize - sizeof(BID<RawSize>)* NBids) / sizeof(Type)), RawSize, NBids>
204 {
205 public:
206  using info_type = void;
207 
209  {
210  TLX_LOGC(debug_typed_block)
211  << "[" << static_cast<void*>(this) << "] block_w_info<> is constructed";
212  }
213 };
214 
215 //! Contains per block filler for \c foxxll::typed_block , not intended for direct use.
216 template <typename BaseType, size_t FillSize = 0>
217 class add_filler : public BaseType
218 {
219 private:
220  //! Per block filler element.
222 
223 public:
225  {
226  TLX_LOGC(debug_typed_block)
227  << "[" << static_cast<void*>(this) << "] add_filler is constructed";
228  }
229 };
230 
231 template <typename BaseType>
232 class add_filler<BaseType, 0>
233  : public BaseType
234 {
235 public:
237  {
238  TLX_LOGC(debug_typed_block)
239  << "[" << static_cast<void*>(this) << "] add_filler<> is constructed";
240  }
241 };
242 
243 //! Helper to compute the size of the filler , not intended for direct use.
244 template <typename Type, size_t RawSize>
245 class expand_struct : public add_filler<Type, RawSize - sizeof(Type)>
246 { };
247 
248 //! \}
249 
250 } // namespace mng_local
251 
252 //! Block containing elements of fixed length.
253 //!
254 //! \tparam RawSize size of block in bytes
255 //! \tparam Type type of block's records
256 //! \tparam NRef number of block references (BIDs) that can be stored in the block (default is 0)
257 //! \tparam MetaInfoType type of per block information (default is no information - void)
258 //!
259 //! The data array of type Type is contained in the parent class \c foxxll::element_block, see related information there.
260 //! The BID array of references is contained in the parent class \c foxxll::block_w_bids, see related information there.
261 //! The "per block information" is contained in the parent class \c foxxll::block_w_info, see related information there.
262 //! \warning If \c RawSize > 2MB object(s) of this type can not be allocated on the stack (as a
263 //! function variable for example), because Linux POSIX library limits the stack size for the
264 //! main thread to (2MB - system page size)
265 template <size_t RawSize, typename Type, size_t NRef = 0, typename MetaInfoType = void>
267  : public mng_local::expand_struct<mng_local::block_w_info<Type, RawSize, NRef, MetaInfoType>, RawSize>
268 {
270 
271  constexpr static bool debug_block_life_cycle = false;
272 
273 public:
274  using value_type = Type;
276  using const_reference = const value_type &;
277  using pointer = value_type *;
278  using iterator = pointer;
279  using const_pointer = const value_type *;
281 
282  static constexpr size_t raw_size = RawSize; //!< size of block in bytes
283  static constexpr size_t size = Base::size; //!< number of elements in block
284  static constexpr bool 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
285 
287 
289  {
290  static_assert(
291  sizeof(typed_block) == raw_size,
292  "sizeof(typed_block) == raw_size"
293  );
294  TLX_LOGC(debug_typed_block)
295  << "[" << static_cast<void*>(this) << "] typed_block is constructed";
296 #if 0
297  assert(((long)this) % BlockAlignment == 0);
298 #endif
299  }
300 
301  /*!
302  * Writes block to the disk(s).
303  * \param bid block identifier, points the file(disk) and position
304  * \param on_complete completion handler
305  * \return \c pointer_ptr object to track status I/O operation after the call
306  */
308  completion_handler on_complete = completion_handler())
309  {
310  TLX_LOGC(debug_block_life_cycle)
311  << "BLC:write " << bid;
312  return bid.storage->awrite(this, bid.offset, raw_size, on_complete);
313  }
314 
315  /*!
316  * Reads block from the disk(s).
317  * \param bid block identifier, points the file(disk) and position
318  * \param on_complete completion handler
319  * \return \c pointer_ptr object to track status I/O operation after the call
320  */
322  completion_handler on_complete = completion_handler())
323  {
324  TLX_LOGC(debug_block_life_cycle)
325  << "BLC:read " << bid;
326  return bid.storage->aread(this, bid.offset, raw_size, on_complete);
327  }
328 
329  /*!
330  * Writes block to the disk(s).
331  * \param bid block identifier, points the file(disk) and position
332  * \param on_complete completion handler
333  * \return \c pointer_ptr object to track status I/O operation after the call
334  */
336  completion_handler on_complete = completion_handler())
337  {
338  TLX_LOGC(debug_block_life_cycle)
339  << "BLC:write " << bid;
340  assert(bid.size >= raw_size);
341  return bid.storage->awrite(this, bid.offset, raw_size, on_complete);
342  }
343 
344  /*!
345  * Reads block from the disk(s).
346  * \param bid block identifier, points the file(disk) and position
347  * \param on_complete completion handler
348  * \return \c pointer_ptr object to track status I/O operation after the call
349  */
350  request_ptr read(const BID<0>& bid,
351  completion_handler on_complete = completion_handler())
352  {
353  TLX_LOGC(debug_block_life_cycle)
354  << "BLC:read " << bid;
355  assert(bid.size >= raw_size);
356  return bid.storage->aread(this, bid.offset, raw_size, on_complete);
357  }
358 
359  static void* operator new (size_t bytes)
360  {
361  size_t meta_info_size = bytes % raw_size;
362  TLX_LOGC(debug_typed_block)
363  << "typed::block operator new[]: bytes=" << bytes
364  << ", meta_info_size=" << meta_info_size;
365 
366  void* result = aligned_alloc<BlockAlignment>(
367  bytes - meta_info_size, meta_info_size
368  );
369 
370 #if FOXXLL_WITH_VALGRIND
371  memset(result, 0, bytes);
372 #endif
373  return result;
374  }
375 
376  static void* operator new[] (size_t bytes)
377  {
378  size_t meta_info_size = bytes % raw_size;
379  TLX_LOGC(debug_typed_block)
380  << "typed::block operator new[]: bytes=" << bytes
381  << ", meta_info_size=" << meta_info_size;
382 
383  void* result = aligned_alloc<BlockAlignment>(
384  bytes - meta_info_size, meta_info_size
385  );
386 
387 #if FOXXLL_WITH_VALGRIND
388  memset(result, 0, bytes);
389 #endif
390  return result;
391  }
392 
393  static void* operator new (size_t /*bytes*/, void* ptr) // construct object in existing memory
394  {
395  return ptr;
396  }
397 
398  static void operator delete (void* ptr)
399  {
400  aligned_dealloc<BlockAlignment>(ptr);
401  }
402 
403  static void operator delete[] (void* ptr)
404  {
405  aligned_dealloc<BlockAlignment>(ptr);
406  }
407 
408  static void operator delete (void*, void*)
409  { }
410 
411 #if 1
412  // STRANGE: implementing destructor makes g++ allocate
413  // additional 4 bytes in the beginning of every array
414  // of this type !? makes aligning to 4K boundaries difficult
415  //
416  // http://www.cc.gatech.edu/grads/j/Seung.Won.Jun/tips/pl/node4.html :
417  // "One interesting thing is the array allocator requires more memory
418  // than the array size multiplied by the size of an element, by a
419  // difference of delta for metadata a compiler needs. It happens to
420  // be 8 bytes long in g++."
422  {
423  TLX_LOGC(debug_typed_block)
424  << "[" << static_cast<void*>(this) << "] typed_block is destructed";
425  }
426 #endif
427 };
428 
429 //! \}
430 
431 } // namespace foxxll
432 
433 #endif // !FOXXLL_MNG_TYPED_BLOCK_HEADER
434 
435 /**************************************************************************/
value_type & reference
external_size_type offset
offset within the file of the block (uint64_t)
Definition: bid.hpp:118
Helper to compute the size of the filler , not intended for direct use.
const value_type * const_pointer
iterator end()
Returns iterator pointing to the end element.
Type
VFS object type.
Definition: file_io.hpp:52
Specialization of block identifier class (BID) for variable size block size.
Definition: bid.hpp:112
virtual request_ptr awrite(void *buffer, offset_type pos, size_type bytes, const completion_handler &on_complete=completion_handler())=0
external_size_type offset
offset within the file of the block (uint64_t)
Definition: bid.hpp:50
const_pointer const_iterator
MetaInfoType info_type
Type of per block information element.
iterator begin()
Returns iterator pointing to the first element.
virtual request_ptr aread(void *buffer, offset_type pos, size_type bytes, const completion_handler &on_complete=completion_handler())=0
const_iterator end() const
Returns const_iterator pointing to the end element.
constexpr bool debug_typed_block
Definition: typed_block.hpp:31
constexpr size_t BlockAlignment
Definition: request.hpp:34
tlx::delegate< void(request *r, bool success)> completion_handler
completion handler
Definition: request.hpp:46
Contains per block information for foxxll::typed_block , not intended for direct use.
const_iterator begin() const
Returns const_iterator pointing to the first element.
const_iterator cbegin() const
Returns const_iterator pointing to the first element.
request_ptr read(const BID< 0 > &bid, completion_handler on_complete=completion_handler())
Reads block from the disk(s).
Contains per block filler for foxxll::typed_block , not intended for direct use.
FOXXLL library namespace
#define TLX_LOGC(cond)
Explicitly specify the condition for logging.
Definition: core.hpp:137
file * storage
pointer to the file of the block
Definition: bid.hpp:116
High-performance smart pointer used as a wrapping reference counting pointer.
static const size_t bytes
number of bytes in uint_pair
Definition: uint_types.hpp:75
Contains BID references for foxxll::typed_block , not intended for direct use.
const value_type & const_reference
request_ptr write(const BID< 0 > &bid, completion_handler on_complete=completion_handler())
Writes block to the disk(s).
filler_struct< FillSize > filler
Per block filler element.
request_ptr write(const bid_type &bid, completion_handler on_complete=completion_handler())
Writes block to the disk(s).
value_type * pointer
size_t size
size of the block in bytes
Definition: bid.hpp:120
file * storage
pointer to the file of the block
Definition: bid.hpp:48
Contains data elements for foxxll::typed_block , not intended for direct use.
Definition: typed_block.hpp:74
request_ptr read(const bid_type &bid, completion_handler on_complete=completion_handler())
Reads block from the disk(s).
info_type info
Per block information element.
const_iterator cend() const
Returns const_iterator pointing to the end element.