1 /*========================== begin_copyright_notice ============================ 2 3 Copyright (C) 2017-2021 Intel Corporation 4 5 SPDX-License-Identifier: MIT 6 7 ============================= end_copyright_notice ===========================*/ 8 9 #pragma once 10 11 #include <array> 12 13 #include "cif/common/cif.h" 14 #include "cif/export/interface_creator.h" 15 16 namespace CIF{ 17 18 template <template <Version_t> class Interface> 19 struct Multiversion 20 { 21 using ImplT = typename Interface<CIF::BaseVersion>::Impl; 22 using BaseInterfaceT = Interface<CIF::BaseVersion>; 23 MultiversionMultiversion24 Multiversion(){ 25 this->impl = nullptr; 26 std::fill(versions.begin(), versions.end(), nullptr); 27 } 28 29 template<typename ArgT, typename ... ArgsT> MultiversionMultiversion30 Multiversion(ArgT && arg, ArgsT && ... args) 31 : Multiversion(){ 32 impl = new ImplT(std::forward<ArgT>(arg), std::forward<ArgsT>(args)...); 33 impl->retain(nullptr); 34 } 35 MultiversionMultiversion36 Multiversion(ImplT *impl) 37 : Multiversion(){ 38 this->impl = impl; 39 this->impl->retain(nullptr); 40 } 41 42 template<typename ... ArgsT> CreateImplMultiversion43 void CreateImpl(ArgsT && ... args){ 44 // release interface tied-up to previous impl (if any) 45 for(BaseInterfaceT *&iVer : versions){ 46 if(iVer == nullptr){ 47 continue; 48 } 49 iVer->Release(); 50 iVer = nullptr; 51 } 52 53 if(this->impl != nullptr){ 54 this->impl->Release(nullptr); 55 } 56 this->impl = new ImplT(std::forward<ArgsT>(args)...); 57 this->impl->Retain(nullptr); 58 } 59 ~MultiversionMultiversion60 ~Multiversion(){ 61 for(BaseInterfaceT * iVer : versions){ 62 if(iVer == nullptr){ 63 continue; 64 } 65 iVer->Release(); 66 } 67 68 if(this->impl != nullptr){ 69 impl->Release(nullptr); 70 } 71 } 72 73 Multiversion(const Multiversion &) = delete; 74 Multiversion &operator=(const Multiversion &) = delete; 75 Multiversion(Multiversion &&) = delete; 76 Multiversion *operator=(Multiversion &&) = delete; 77 78 ImplT *operator->() { return impl; } 79 80 ImplT *operator->() const { return impl; } 81 GetImplMultiversion82 ImplT *GetImpl(){ 83 return impl; 84 } 85 GetImplMultiversion86 const ImplT *GetImpl() const { 87 return impl; 88 } 89 GetVersionMultiversion90 const BaseInterfaceT *GetVersion(Version_t v) const { 91 constexpr Version_t oldestSupportedVersion = Interface<CIF::TraitsSpecialVersion>::GetOldestSupportedVersion(); 92 constexpr Version_t latestSupportedVersion = Interface<CIF::TraitsSpecialVersion>::GetLatestSupportedVersion(); 93 94 if((v < oldestSupportedVersion) || (v > latestSupportedVersion)){ 95 return nullptr; 96 } 97 98 size_t idx = static_cast<size_t>(v - oldestSupportedVersion); 99 BaseInterfaceT *curr = versions[idx]; 100 if(curr != nullptr){ 101 return curr; 102 } 103 versions[idx] = InterfaceCreator<Interface>::CreateInterfaceVer(v, impl); 104 return versions[idx]; 105 } 106 GetVersionMultiversion107 BaseInterfaceT *GetVersion(Version_t v) { 108 return const_cast<BaseInterfaceT*>(const_cast<const Multiversion<Interface>*>(this)->GetVersion(v)); 109 } 110 protected: 111 mutable std::array<BaseInterfaceT*, Interface<CIF::TraitsSpecialVersion>::GetNumSupportedVersions()> versions = {}; 112 ImplT *impl = nullptr; 113 bool ownsImpl = false; 114 }; 115 116 } 117