1 /** @file 2 3 Extendible 4 5 @section license License 6 7 Licensed to the Apache Software Foundation (ASF) under one 8 or more contributor license agreements. See the NOTICE file 9 distributed with this work for additional information 10 regarding copyright ownership. The ASF licenses this file 11 to you under the Apache License, Version 2.0 (the 12 "License"); you may not use this file except in compliance 13 with the License. You may obtain a copy of the License at 14 15 http://www.apache.org/licenses/LICENSE-2.0 16 17 Unless required by applicable law or agreed to in writing, software 18 distributed under the License is distributed on an "AS IS" BASIS, 19 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 20 See the License for the specific language governing permissions and 21 limitations under the License. 22 23 @section details Details 24 25 //////////////////////////////////////////// 26 Implements: 27 * Extendible<Derived_t> 28 * Schema 29 * fieldAdd 30 * fieldFind 31 */ 32 33 #include "tscore/Extendible.h" 34 35 namespace ext 36 { 37 namespace details 38 { 39 //////////////////////////////////////////////////// 40 // Schema Methods 41 ~Schema()42 Schema::~Schema() {} 43 44 void updateMemOffsets()45 Schema::updateMemOffsets() 46 { 47 ink_release_assert(cnt_constructed == cnt_destructed); 48 49 uint32_t acc_offset = 0; 50 alloc_align = 1; 51 52 for (auto &pair_fld : fields) { 53 alloc_align = std::max(alloc_align, pair_fld.second.align); 54 } 55 56 // allocate fields from largest to smallest alignment 57 uint8_t processing_align = alloc_align; 58 while (processing_align > 0) { 59 uint8_t next_align = 0; 60 for (auto &pair_fld : fields) { 61 auto &fld = pair_fld.second; 62 if (fld.align == processing_align) { 63 fld.field_offset = acc_offset; 64 acc_offset += fld.size; 65 } else if (fld.align < processing_align) { 66 next_align = std::max(next_align, fld.align); 67 } 68 } 69 processing_align = next_align; 70 } 71 72 // align '0' are packed bit allocations. 73 uint32_t acc_bit_offset = 0; 74 for (auto &pair_fld : fields) { 75 auto &fld = pair_fld.second; 76 if (fld.align == 0) { 77 fld.field_offset = acc_offset + acc_bit_offset / 8; 78 fld.mask = 1 << (acc_bit_offset % 8); 79 ++acc_bit_offset; 80 } 81 } 82 83 alloc_size = acc_offset + (acc_bit_offset + 7) / 8; 84 } 85 86 bool reset()87 Schema::reset() 88 { 89 if (cnt_constructed > cnt_destructed) { 90 // free instances before calling this so we don't leak memory 91 return false; 92 } 93 fields.clear(); 94 updateMemOffsets(); 95 return true; 96 } 97 98 void callConstructor(uintptr_t ext_loc)99 Schema::callConstructor(uintptr_t ext_loc) 100 { 101 ink_assert(ext_loc); 102 ++cnt_fld_constructed; // don't allow schema modification 103 ink_assert(cnt_fld_constructed <= cnt_constructed); 104 105 // init all extendible memory to 0, in case constructors don't 106 memset(reinterpret_cast<void *>(ext_loc), 0, alloc_size); 107 108 for (auto const &elm : fields) { 109 if (elm.second.constructor) { 110 elm.second.constructor(FieldPtr(ext_loc + elm.second.field_offset)); 111 } 112 } 113 } 114 115 void callDestructor(uintptr_t ext_loc)116 Schema::callDestructor(uintptr_t ext_loc) 117 { 118 ink_assert(ext_loc); 119 for (auto const &elm : fields) { 120 if (elm.second.destructor) { 121 elm.second.destructor(FieldPtr(ext_loc + elm.second.field_offset)); 122 } 123 } 124 } 125 126 size_t fullSize(const size_t base_size) const127 Schema::fullSize(const size_t base_size) const 128 { 129 ink_assert(base_size); 130 return ROUNDUP(base_size, alloc_align) + alloc_size; 131 } 132 133 bool no_instances() const134 Schema::no_instances() const 135 { 136 return cnt_constructed == cnt_destructed; 137 } 138 } // namespace details 139 140 } // namespace ext 141