You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
			
				
					49 lines
				
				3.0 KiB
			
		
		
			
		
	
	
					49 lines
				
				3.0 KiB
			| 
								 
											6 months ago
										 
									 | 
							
								#pragma once
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								namespace detail::refcount_hive
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								// The element as allocated in memory needs to be at-least 2*skipfield_type width in order to support free list indexes in
							 | 
						||
| 
								 | 
							
								// erased element memory space, so: make the size of this struct the larger of alignof(T), sizeof(T) or 2*skipfield_type
							 | 
						||
| 
								 | 
							
								// (the latter is only relevant for type char/uchar), and make the alignment alignof(T). This type is used mainly for
							 | 
						||
| 
								 | 
							
								// correct pointer arithmetic while iterating over elements in memory.
							 | 
						||
| 
								 | 
							
								template <typename element_type, typename skipfield_type, typename refcount_type>
							 | 
						||
| 
								 | 
							
								struct alignas(alignof(element_type)) aligned_element_struct {
							 | 
						||
| 
								 | 
							
								    // Using char as sizeof is always guaranteed to be 1 byte regardless of the number of bits in a byte on given computer,
							 | 
						||
| 
								 | 
							
								    // whereas for example, uint8_t would fail on machines where there are more than 8 bits in a byte eg. Texas Instruments
							 | 
						||
| 
								 | 
							
								    // C54x DSPs.
							 | 
						||
| 
								 | 
							
								    char
							 | 
						||
| 
								 | 
							
								        data[(sizeof(element_type) < (sizeof(skipfield_type) * 2))
							 | 
						||
| 
								 | 
							
								                 ? ((sizeof(skipfield_type) * 2) < alignof(element_type) ? alignof(element_type) : (sizeof(skipfield_type) * 2))
							 | 
						||
| 
								 | 
							
								                 : ((sizeof(element_type) < alignof(element_type)) ? alignof(element_type) : sizeof(element_type))];
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// We combine the allocation of elements and skipfield into one allocation to save performance. This memory must be
							 | 
						||
| 
								 | 
							
								// allocated as an aligned type with the same alignment as T in order for the elements to align with memory boundaries
							 | 
						||
| 
								 | 
							
								// correctly (which won't happen if we allocate as char or uint_8). But the larger the sizeof in the type we use for
							 | 
						||
| 
								 | 
							
								// allocation, the greater the chance of creating a lot of unused memory in the skipfield portion of the allocated block. So
							 | 
						||
| 
								 | 
							
								// we create a type that is sizeof(alignof(T)), as in most cases alignof(T) < sizeof(T). If alignof(t) >= sizeof(t) this
							 | 
						||
| 
								 | 
							
								// makes no difference.
							 | 
						||
| 
								 | 
							
								template <typename element_type>
							 | 
						||
| 
								 | 
							
								struct alignas(alignof(element_type)) aligned_allocation_struct {
							 | 
						||
| 
								 | 
							
								    char data[alignof(element_type)];
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// Calculate the capacity of a group's elements+skipfield memory block when expressed in multiples of the value_type's
							 | 
						||
| 
								 | 
							
								// alignment (rounding up).
							 | 
						||
| 
								 | 
							
								template <typename element_type, typename skipfield_type, typename refcount_type>
							 | 
						||
| 
								 | 
							
								static size_t get_aligned_block_capacity(const skipfield_type elements_per_group)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    using aligned_element_struct    = aligned_element_struct<element_type, skipfield_type, refcount_type>;
							 | 
						||
| 
								 | 
							
								    using aligned_allocation_struct = aligned_allocation_struct<element_type>;
							 | 
						||
| 
								 | 
							
								    return ((elements_per_group * (sizeof(aligned_element_struct) + sizeof(skipfield_type))) + sizeof(skipfield_type)
							 | 
						||
| 
								 | 
							
								            + sizeof(aligned_allocation_struct) - 1)
							 | 
						||
| 
								 | 
							
								           / sizeof(aligned_allocation_struct);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// To enable conversion when allocator supplies non-raw pointers:
							 | 
						||
| 
								 | 
							
								template <class destination_pointer_type, class source_pointer_type>
							 | 
						||
| 
								 | 
							
								static constexpr destination_pointer_type pointer_cast(const source_pointer_type source_pointer) noexcept
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    return destination_pointer_type(&*source_pointer);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								} // namespace detail::refcount_hive
							 |