/* ----------------------------------------------------------------------------- Copyright 2019-2021 Kevin P. Barry Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. ----------------------------------------------------------------------------- */ // Author: Kevin P. Barry [ta0kira@gmail.com] #ifndef INTERNAL_HPP_ #define INTERNAL_HPP_ #include #include #include "category-source.hpp" #include "cycle-check.hpp" #define COLLECTION_ID(vp) (int) 1000000009 * (long) (vp) template class InstanceCache { public: using Creator = std::function(typename Params

::Type)>; InstanceCache(const Creator& create) : create_(create) {} S GetOrCreate(typename Params

::Type params) { while (lock_.test_and_set(std::memory_order_acquire)); auto& cached = cache_[GetKeyFromParams

(params)]; S type = cached; if (!type) { cached = type = create_(params); } lock_.clear(std::memory_order_release); return type; } private: const Creator create_; std::atomic_flag lock_ = ATOMIC_FLAG_INIT; std::map::Type, S> cache_; }; template struct DispatchTable { constexpr DispatchTable() : key(), table(nullptr), size(0) {} template DispatchTable(CollectionType k, const F(&t)[S]) : key(k), table(t), size(S) {} inline bool operator < (const DispatchTable& other) const { return key < other.key; } CollectionType key; const F* table; int size; }; template struct DispatchSingle { constexpr DispatchSingle() : key(nullptr), value() {} DispatchSingle(const void* k, const F v) : key(k), value(v) {} inline bool operator < (const DispatchSingle& other) const { return key < other.key; } const void* key; F value; }; struct StaticSort { template StaticSort(T(&table)[S]) { std::sort(table, table+S); } }; template struct LoopLimit {}; template struct LoopLimit> { // See function-calls.0rt for tests. static constexpr int max = 15; }; template struct LoopLimit> { // See function-calls.0rt for tests. static constexpr int max = 15; }; template struct DispatchChoice {}; template struct DispatchChoice { template static const T* Select(K key, T* table) { return nullptr; } }; template struct DispatchChoice { template static const T* Select(K key, T* table) { if (table->key == key) { return table; } return DispatchChoice::Select(key, table+1); } }; template struct DispatchChoice { template static const T* Select(K key, T* table) { int i = 0, j = S, k; while ((k = (i+j)/2) > i) { if (table[k].key < key) { i = k; } else if (table[k].key > key) { j = k; } else { return &table[k]; } } if (table[k].key == key) { return &table[k]; } else { return nullptr; } } }; template const T* DispatchSelect(K key, T(&table)[S]) { return DispatchChoice<(S <= LoopLimit::max), T, S>::Select(key, table); } #endif // INTERNAL_HPP_