| /* |
| * Copyright (C) 2018 The Android Open Source Project |
| * |
| * 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. |
| */ |
| |
| #ifndef C2UTILS_INTERFACE_HELPER_H_ |
| #define C2UTILS_INTERFACE_HELPER_H_ |
| |
| #include <C2Component.h> |
| #include <util/C2InterfaceUtils.h> |
| |
| #include <map> |
| #include <mutex> |
| #include <vector> |
| |
| #include <stddef.h> |
| |
| /** |
| * Interface Helper |
| */ |
| using C2R = C2SettingResultsBuilder; |
| |
| template<typename T, bool E=std::is_enum<T>::value> |
| struct _c2_reduce_enum_to_underlying_type { |
| typedef T type; |
| }; |
| |
| template<typename T> |
| struct _c2_reduce_enum_to_underlying_type<T, true> { |
| typedef typename std::underlying_type<T>::type type; |
| }; |
| |
| /** |
| * Helper class to implement parameter reflectors. This class is dynamic and is designed to be |
| * shared by multiple interfaces. This allows interfaces to add structure descriptors as needed. |
| */ |
| class C2ReflectorHelper : public C2ParamReflector { |
| public: |
| C2ReflectorHelper() = default; |
| virtual ~C2ReflectorHelper() = default; |
| virtual std::unique_ptr<C2StructDescriptor> describe( |
| C2Param::CoreIndex paramIndex) const override; |
| |
| /** |
| * Adds support for describing the given parameters. |
| * |
| * \param Params types of codec 2.0 structs (or parameters) to describe |
| */ |
| template<typename... Params> |
| C2_INLINE void addStructDescriptors() { |
| std::vector<C2StructDescriptor> structs; |
| addStructDescriptors(structs, (_Tuple<Params...> *)nullptr); |
| } |
| |
| /** |
| * Adds support for describing a specific struct. |
| * |
| * \param strukt descriptor for the struct that will be moved out. |
| */ |
| void addStructDescriptor(C2StructDescriptor &&strukt); |
| |
| private: |
| template<typename... Params> |
| class C2_HIDE _Tuple { }; |
| |
| /** |
| * Adds support for describing the given descriptors. |
| * |
| * \param structs List of structure descriptors to add support for |
| */ |
| void addStructDescriptors( |
| std::vector<C2StructDescriptor> &structs, _Tuple<> *); |
| |
| /** |
| * Utility method that adds support for describing the given descriptors in a recursive manner |
| * one structure at a time using a list of structure descriptors temporary. |
| * |
| * \param T the type of codec 2.0 struct to describe |
| * \param Params rest of the structs |
| * \param structs Temporary list of structure descriptors used to optimize the operation. |
| */ |
| template<typename T, typename... Params> |
| C2_INLINE void addStructDescriptors( |
| std::vector<C2StructDescriptor> &structs, _Tuple<T, Params...> *) { |
| structs.emplace_back((T*)nullptr); |
| addStructDescriptors(structs, (_Tuple<Params...> *)nullptr); |
| } |
| |
| mutable std::mutex _mMutex; |
| std::map<C2Param::CoreIndex, const C2StructDescriptor> _mStructs; ///< descriptors |
| }; |
| |
| /** |
| * Utility class that implements the codec 2.0 interface API-s for some parameters. |
| * |
| * This class must be subclassed. |
| */ |
| class C2InterfaceHelper { |
| public: |
| /** |
| * Returns the base offset of a field at |offset| that could be part of an array or part of a |
| * sub-structure. |
| * |
| * This method does not do field size verification, e.g. if offset if obtained from a structure, |
| * it will not stop at the structure boundary - this is okay, as we just want the base offset |
| * here, which is the same. |
| */ |
| static |
| size_t GetBaseOffset(const std::shared_ptr<C2ParamReflector> &reflector, |
| C2Param::CoreIndex index, size_t offset); |
| |
| /** |
| * The interface helper class uses references to std::shared_ptr<T> config parameters. |
| * Internally, these need to be generalized to std::shared_ptr<C2Param> refs, but the cast is |
| * not allowed (as these are references). As such, this class never returns pointer to the |
| * shared_ptrs. |
| */ |
| struct ParamRef { |
| template<typename T, typename enable= |
| typename std::enable_if<std::is_convertible<T, C2Param>::value>::type> |
| inline C2_HIDE ParamRef(std::shared_ptr<T> ¶m) |
| : _mRef(reinterpret_cast<std::shared_ptr<C2Param>*>(¶m)) { } |
| |
| // used by comparison operator for containers |
| operator std::shared_ptr<C2Param> *() const { return _mRef; } |
| |
| /** |
| * Returns a shared pointer to the parameter. |
| */ |
| std::shared_ptr<C2Param> get() const { return *_mRef; } |
| |
| private: |
| std::shared_ptr<C2Param> *_mRef; |
| }; |
| |
| /** |
| * Field helper. |
| * |
| * Contains additional information for the field: possible values, and currently supported |
| * values. |
| */ |
| class FieldHelper { |
| public: |
| /** |
| * Creates helper for a field with given possible values. |
| * |
| * \param param parameter reference. The parameter does not have to be initialized at this |
| * point. |
| * \param field field identifier |
| * \param values possible values for the field |
| */ |
| FieldHelper(const ParamRef ¶m, const _C2FieldId &field, |
| std::unique_ptr<C2FieldSupportedValues> &&values); |
| |
| /** |
| * Creates a param-field identifier for this field. This method is called after the |
| * underlying parameter has been initialized. |
| * |
| * \aram index |
| * |
| * @return C2ParamField |
| */ |
| C2ParamField makeParamField(C2Param::Index index) const; |
| |
| /** |
| * Sets the currently supported values for this field. |
| * |
| * \param values currently supported values that will be moved out |
| */ |
| void setSupportedValues(std::unique_ptr<C2FieldSupportedValues> &&values); |
| |
| /** |
| * Gets the currently supported values for this field. This defaults to the possible values |
| * if currently supported values were never set. |
| */ |
| const C2FieldSupportedValues *getSupportedValues() const; |
| |
| /** |
| * Gets the possible values for this field. |
| */ |
| const C2FieldSupportedValues *getPossibleValues() const; |
| |
| protected: |
| // TODO: move to impl for safety |
| ParamRef mParam; |
| _C2FieldId mFieldId; |
| std::unique_ptr<C2FieldSupportedValues> mPossible; |
| std::unique_ptr<C2FieldSupportedValues> mSupported; ///< if different from possible |
| }; |
| |
| template<typename T> |
| struct C2_HIDE Param; |
| class ParamHelper; |
| |
| /** |
| * Factory is an interface to get the parameter helpers from a std::shared_ptr<T> &. |
| */ |
| class Factory { |
| // \todo this may be already in ParamHelper |
| virtual std::shared_ptr<C2ParamReflector> getReflector() const = 0; |
| |
| virtual std::shared_ptr<ParamHelper> getParamHelper(const ParamRef ¶m) const = 0; |
| |
| public: |
| virtual ~Factory() = default; |
| |
| template<typename T> |
| Param<T> get(std::shared_ptr<T> ¶m, std::shared_ptr<T> altValue = nullptr) const { |
| return Param<T>(getParamHelper(ParamRef(param)), |
| altValue == nullptr ? param : altValue, |
| getReflector()); |
| } |
| }; |
| |
| /** |
| * Typed field helper. |
| */ |
| template<typename T> |
| struct Field { |
| /** |
| * Constructor. |
| * |
| * \param helper helper for this field |
| * \param index parameter index (this is needed as it is not available during parameter |
| * construction) \todo remove |
| */ |
| Field(std::shared_ptr<FieldHelper> helper, C2Param::Index index); |
| |
| bool supportsAtAll(T value) const { |
| return C2FieldSupportedValuesHelper<T>(*_mHelper->getPossibleValues()).supports(value); |
| } |
| |
| bool supportsNow(T value) const { |
| return C2FieldSupportedValuesHelper<T>(*_mHelper->getSupportedValues()).supports(value); |
| } |
| |
| /** |
| * Creates a conflict resolution suggestion builder for this field. |
| */ |
| C2ParamFieldValuesBuilder<T> shouldBe() const; |
| |
| /** |
| * Creates a currently supported values builder for this field. This is only supported |
| * for non-const fields to disallow setting supported values for dependencies. |
| */ |
| C2ParamFieldValuesBuilder<T> mustBe(); |
| |
| operator C2ParamField() const { |
| return _mField; |
| } |
| |
| // TODO |
| C2R validatePossible(const T &value __unused) const { |
| /// TODO |
| return C2R::Ok(); |
| } |
| |
| private: |
| std::shared_ptr<FieldHelper> _mHelper; |
| C2ParamField _mField; |
| }; |
| |
| class ParamHelper { |
| public: |
| ParamHelper(ParamRef param, C2StringLiteral name, C2StructDescriptor &&); |
| ParamHelper(ParamHelper &&); |
| ~ParamHelper(); |
| |
| /** |
| * Finds a field descriptor. |
| */ |
| std::shared_ptr<FieldHelper> findField(size_t baseOffs, size_t baseSize) const; |
| |
| /// returns the parameter ref for this parameter |
| const ParamRef ref() const; |
| |
| /// returns the current value of this parameter as modifiable. The constness of this |
| /// object determines the constness of the returned value. |
| std::shared_ptr<C2Param> value(); |
| |
| /// returns the current value of this parameter as const |
| std::shared_ptr<const C2Param> value() const; |
| |
| /** |
| * Performs a configuration change request for this parameter. |
| * |
| * \param value the value that is being assigned to this parameter. |
| * This could be pointing to the current value of the |
| * parameter. This must not change. |
| * \param mayBlock whether blocking is allowed |
| * \param endValue the resulting value |
| * \param factory parameter factory (to access dependencies) |
| * \param failures vector of failures to append any failures from this |
| * operation |
| * |
| * \retval C2_OK configuration was successful |
| * \retval C2_BAD_VALUE value is incorrect (TBD) |
| * \retval C2_NO_MEMORY not enough memory to perform the assignment |
| * \retval C2_TIMED_OUT configuration timed out |
| * \retval C2_BLOCKING configuration requires blocking to be allowed |
| * \retval C2_CORRUPTED interface is corrupted |
| */ |
| c2_status_t trySet( |
| const C2Param *value, bool mayBlock, |
| bool *changed, |
| Factory &factory, |
| std::vector<std::unique_ptr<C2SettingResult>>* const failures); |
| |
| /// returns parameter indices that depend on this parameter |
| const std::vector<C2Param::Index> getDownDependencies() const; |
| |
| /// adds a dependent parameter |
| void addDownDependency(C2Param::Index index); |
| |
| /// returns that parameter refs for parameters that depend on this |
| const std::vector<ParamRef> getDependenciesAsRefs() const; |
| |
| /// returns and moves out stored struct descriptor |
| C2StructDescriptor retrieveStructDescriptor(); |
| |
| /// returns the name of this parameter |
| C2String name() const; |
| |
| /// returns the index of this parameter |
| C2Param::Index index() const; |
| |
| /// returns the parameter descriptor |
| std::shared_ptr<const C2ParamDescriptor> getDescriptor() const; |
| |
| /** |
| * Validates param helper. |
| * |
| * For now, this fills field info for const params. |
| * |
| * \retval C2_CORRUPTED the parameter cannot be added as such |
| */ |
| c2_status_t validate(const std::shared_ptr<C2ParamReflector> &reflector); |
| |
| protected: |
| typedef C2ParamDescriptor::attrib_t attrib_t; |
| attrib_t& attrib(); |
| |
| /// sets the default value of this parameter |
| void setDefaultValue(std::shared_ptr<C2Param> default_); |
| |
| /// sets the setter method |
| void setSetter(std::function<C2R(const C2Param *, bool, bool *, Factory &)> setter); |
| |
| /// sets the getter method |
| void setGetter(std::function<std::shared_ptr<C2Param>(bool)> getter); |
| |
| /// sets the dependencies |
| void setDependencies(std::vector<C2Param::Index> indices, std::vector<ParamRef> refs); |
| |
| /// sets the fields and their supported values |
| void setFields(std::vector<C2ParamFieldValues> &&fields); |
| |
| /// build this into a final ParamHelper object |
| std::shared_ptr<ParamHelper> build(); |
| |
| class Impl; |
| std::unique_ptr<Impl> mImpl; |
| }; |
| |
| /** |
| * Typed parameter helper. This provides access to members as well as field helpers. |
| */ |
| template<typename T> |
| struct C2_HIDE Param { |
| Param( |
| std::shared_ptr<ParamHelper> helper, std::shared_ptr<T> ¶m, |
| std::shared_ptr<C2ParamReflector> reflector) |
| : v(*param.get()), |
| _mTypedParam(param), |
| _mHelper(helper), |
| _mReflector(reflector) { } |
| |
| template<typename S> |
| using FieldType = Field< |
| typename _c2_reduce_enum_to_underlying_type< |
| typename std::remove_const< |
| typename std::remove_extent<S>::type>::type>::type>; |
| |
| template<typename S> |
| FieldType<S> F(S &field) { |
| size_t offs = (uintptr_t)&field - (uintptr_t)&get(); |
| // this must fall either within sizeof(T) + FLEX_SIZE or param->size() |
| // size_t size = sizeof(field); |
| // mParam may be null |
| size_t baseSize = sizeof(typename std::remove_extent<S>::type); |
| size_t baseOffs = GetBaseOffset( |
| _mReflector, T::CORE_INDEX, offs - sizeof(C2Param)); |
| if (~baseOffs == 0) { |
| // C2_LOG(FATAL) << "unknown field at offset " << offs << " size " << sizeof(S) |
| // << " base-size " << baseSize; |
| // __builtin_trap(); |
| } else { |
| baseOffs += sizeof(C2Param); |
| } |
| |
| std::shared_ptr<FieldHelper> helper = _mHelper->findField(baseOffs, baseSize); |
| return FieldType<S>(helper, _mTypedParam->index()); |
| } |
| |
| // const Param have const Fields; however, remove const from S |
| template<typename S> |
| const FieldType<S> F(S &field) const { |
| return const_cast<const FieldType<S>>(const_cast<Param *>(this)->F(field)); |
| } |
| |
| /// Returns a const ref value of this const param. |
| const T &get() const { |
| return *_mTypedParam.get(); |
| } |
| |
| /// Returns a modifiable ref value of this non-const param. |
| T &set() { |
| return *_mTypedParam.get(); |
| } |
| |
| /// Const-reference to the value.s |
| T const &v; |
| |
| private: |
| std::shared_ptr<T> _mTypedParam; |
| std::shared_ptr<ParamHelper> _mHelper; |
| std::shared_ptr<C2ParamReflector> _mReflector; |
| }; |
| |
| template<typename T> |
| using C2P = Param<T>; |
| |
| /** |
| * Templated move builder class for a parameter helper. |
| */ |
| template<typename T> |
| class C2_HIDE ParamBuilder : private ParamHelper { |
| public: |
| /** Construct the parameter builder from minimal info required. */ |
| ParamBuilder(std::shared_ptr<T> ¶m, C2StringLiteral name) |
| : ParamHelper(param, name, C2StructDescriptor((T*)nullptr)), |
| mTypedParam(¶m) { |
| attrib() = attrib_t::IS_PERSISTENT; |
| } |
| |
| /** Makes this parameter required. */ |
| inline ParamBuilder &required() { |
| attrib() |= attrib_t::IS_REQUIRED; |
| return *this; |
| } |
| |
| /** Makes this parameter transient (not persistent). */ |
| inline ParamBuilder &transient() { |
| attrib() &= ~attrib_t::IS_PERSISTENT; |
| return *this; |
| } |
| |
| /** Makes this parameter hidden (not exposed in JAVA API). */ |
| inline ParamBuilder &hidden() { |
| attrib() |= attrib_t::IS_HIDDEN; |
| return *this; |
| } |
| |
| /** Makes this parameter internal (not exposed to query/settings). */ |
| inline ParamBuilder &internal() { |
| attrib() |= attrib_t::IS_INTERNAL; |
| return *this; |
| } |
| |
| /** Adds default value. Must be added exactly once. */ |
| inline ParamBuilder &withDefault(std::shared_ptr<T> default_) { |
| // CHECK(!mDefaultValue); |
| // WARN_IF(!default_); // could be nullptr if OOM |
| // technically, this could be in the parent |
| *mTypedParam = std::shared_ptr<T>(T::From(C2Param::Copy(*default_).release())); |
| setDefaultValue(default_); |
| std::shared_ptr<T> *typedParam = mTypedParam; |
| setGetter([typedParam](bool) -> std::shared_ptr<C2Param> { |
| return std::static_pointer_cast<C2Param>(*typedParam); |
| }); |
| return *this; |
| } |
| |
| /** Adds default value. Must be added exactly once. */ |
| inline ParamBuilder &withDefault(T *default_) { |
| return withDefault(std::shared_ptr<T>(default_)); |
| } |
| |
| /** Adds all fields to this parameter with their possible values. */ |
| inline ParamBuilder &withFields(std::vector<C2ParamFieldValues> &&fields_) { |
| setFields(std::move(fields_)); |
| return *this; |
| } |
| |
| /** |
| * Adds a constant value (also as default). Must be added exactly once. |
| * |
| * Const parameters by definition have no dependencies. |
| */ |
| inline ParamBuilder &withConstValue(std::shared_ptr<T> default_) { |
| attrib() |= attrib_t::IS_CONST; |
| setSetter([default_]( |
| const C2Param *value, bool mayBlock __unused, bool *changed, Factory &) -> C2R { |
| *changed = false; |
| const T *typedValue = T::From(value); |
| if (typedValue == nullptr) { |
| return C2R::Corrupted(); // TODO BadValue/Invalid. This should not happen here. |
| } |
| if (*typedValue != *default_) { |
| return C2R::Corrupted(); // TODO ReadOnly(*default_); |
| } |
| *changed = false; |
| return C2R::Ok(); |
| }); |
| return withDefault(default_); |
| } |
| |
| /** Adds constant value (also as default). Must be added exactly once. */ |
| inline ParamBuilder &withConstValue(T *default_) { |
| return withConstValue(std::shared_ptr<T>(default_)); |
| } |
| |
| /** |
| * Use a strict setter. |
| * |
| * \param fn strict setter |
| * \param deps dependencies (references) |
| */ |
| template<typename ... Deps> |
| inline ParamBuilder &withSetter( |
| C2R (*fn)(bool, const C2P<T> &, C2P<T> &, const C2P<Deps> &...), |
| std::shared_ptr<Deps>& ... deps) { |
| attrib() |= attrib_t::IS_STRICT; |
| std::shared_ptr<T> *typedParam = mTypedParam; |
| setSetter([typedParam, fn, &deps...]( |
| const C2Param *value, bool mayBlock, bool *changed, Factory &factory) -> C2R { |
| *changed = false; |
| const T *typedValue = T::From(value); |
| if (typedValue == nullptr) { |
| return C2R::Corrupted(); // TODO BadValue/Invalid. This should not happen here. |
| } |
| // Do copy-on-change for parameters in this helper so change can be detected by |
| // a change of the pointer. Do this by working on a proposed value. |
| std::shared_ptr<T> proposedValue = |
| std::shared_ptr<T>(T::From(C2Param::Copy(*value).release())); |
| if (proposedValue == nullptr) { |
| return C2R::NoMemory(value->index()); |
| } |
| C2P<T> oldValue = factory.get(*typedParam); |
| // Get a parameter helper with value pointing to proposedValue |
| C2P<T> helper = factory.get(*typedParam, proposedValue); |
| C2R result = fn(mayBlock, oldValue, helper, factory.get(deps)...); |
| |
| // If value changed, copy result to current value |
| if (helper.get() != *typedParam->get()) { |
| *typedParam = proposedValue; |
| *changed = true; |
| } |
| return result; |
| }); |
| setDependencies(std::vector<C2Param::Index>{ deps->index()... }, |
| std::vector<ParamRef>{ ParamRef(deps)... }); |
| return *this; |
| } |
| |
| /** |
| * Use a non-strict setter. |
| * |
| * \param fn non-strict setter |
| * \param deps dependencies (references) |
| */ |
| template<typename ... Deps> |
| inline ParamBuilder &withSetter( |
| C2R (*fn)(bool, C2P<T> &, const C2P<Deps> &...), std::shared_ptr<Deps>& ... deps) { |
| std::shared_ptr<T> *typedParam = mTypedParam; |
| setSetter([typedParam, fn, &deps...]( |
| const C2Param *value, bool mayBlock, bool *changed, Factory &factory) -> C2R { |
| *changed = false; |
| const T *typedValue = T::From(value); |
| if (typedValue == nullptr) { |
| return C2R::Corrupted(); // TODO BadValue/Invalid. This should not happen here. |
| } |
| // Do copy-on-change for parameters in this helper so change can be detected by |
| // a change of the pointer. Do this by working on a proposed value. |
| std::shared_ptr<T> proposedValue = |
| std::shared_ptr<T>(T::From(C2Param::Copy(*value).release())); |
| if (proposedValue == nullptr) { |
| return C2R::NoMemory(value->index()); |
| } |
| // Get a parameter helper with value pointing to proposedValue |
| C2P<T> helper = factory.get(*typedParam, proposedValue); |
| C2R result = fn(mayBlock, helper, factory.get(deps)...); |
| |
| // If value changed, copy result to current value |
| if (helper.get() != *typedParam->get()) { |
| *typedParam = proposedValue; |
| *changed = true; |
| } |
| return result; |
| }); |
| setDependencies(std::vector<C2Param::Index>{ deps->index()... }, |
| std::vector<ParamRef>{ ParamRef(deps)... }); |
| return *this; |
| } |
| |
| /** |
| * Marks this a calculated (read-only) field. |
| * |
| * \param fn non-strict setter (calculator) |
| * \param deps dependencies (references) |
| */ |
| template<typename ... Deps> |
| inline ParamBuilder &calculatedAs( |
| C2R (*fn)(bool, C2P<T> &, const C2P<Deps> &...), std::shared_ptr<Deps>& ... deps) { |
| attrib() |= attrib_t::IS_READ_ONLY; |
| return withSetter(fn, std::forward<decltype(deps)>(deps)...); |
| } |
| |
| inline std::shared_ptr<ParamHelper> build() { |
| return ParamHelper::build(); |
| } |
| |
| protected: |
| std::shared_ptr<T> *mTypedParam; |
| }; |
| |
| template<typename T> |
| static ParamBuilder<T> DefineParam(std::shared_ptr<T> ¶m, C2StringLiteral name) { |
| return ParamBuilder<T>(param, name); |
| } |
| |
| public: |
| c2_status_t query( |
| const std::vector<C2Param*> &stackParams, |
| const std::vector<C2Param::Index> &heapParamIndices, |
| c2_blocking_t mayBlock, |
| std::vector<std::unique_ptr<C2Param>>* const heapParams) const; |
| |
| /** |
| * Helper implementing config calls as well as other configuration updates. |
| * |
| * This method is virtual, so implementations may provide wrappers around it (and perform |
| * actions just before and after a configuration). |
| * |
| * \param params |
| * \param mayBlock |
| * \param failures |
| * \param updateParams if true, the updated parameter values are copied back into the arguments |
| * passed in |params| |
| * \param changes pointed to a vector to receive settings with their values changed. If not |
| * null, settings with their values changed are added to this. |
| * \return result from config |
| */ |
| virtual c2_status_t config( |
| const std::vector<C2Param*> ¶ms, c2_blocking_t mayBlock, |
| std::vector<std::unique_ptr<C2SettingResult>>* const failures, |
| bool updateParams = true, |
| std::vector<std::shared_ptr<C2Param>> *changes = nullptr); |
| |
| c2_status_t querySupportedParams( |
| std::vector<std::shared_ptr<C2ParamDescriptor>> *const params) const; |
| |
| c2_status_t querySupportedValues( |
| std::vector<C2FieldSupportedValuesQuery> &fields, c2_blocking_t mayBlock) const; |
| |
| std::shared_ptr<C2ReflectorHelper> getReflector() { |
| return mReflector; |
| } |
| |
| typedef std::unique_lock<std::mutex> Lock; |
| |
| /** |
| * Locks the interface and returns a lock. This lock must be unlocked or released without |
| * calling any other blocking call. |
| */ |
| Lock lock() const; |
| |
| private: |
| void setInterfaceAddressBounds(uintptr_t start, uintptr_t end) { |
| // TODO: exclude this helper |
| (void)start; |
| (void)end; |
| } |
| |
| protected: |
| mutable std::mutex mMutex; |
| std::shared_ptr<C2ReflectorHelper> mReflector; |
| struct FactoryImpl; |
| std::shared_ptr<FactoryImpl> _mFactory; |
| |
| C2InterfaceHelper(std::shared_ptr<C2ReflectorHelper> reflector); |
| |
| /** |
| * Adds a parameter to this interface. |
| * \note This method CHECKs. |
| * |
| * \param param parameter to add. |
| */ |
| void addParameter(std::shared_ptr<ParamHelper> param); |
| |
| /** |
| * Returns the dependency index for a parameter. |
| * |
| * \param ix the index of the parameter |
| */ |
| size_t getDependencyIndex_l(C2Param::Index ix) const; |
| |
| virtual ~C2InterfaceHelper() = default; |
| |
| /** |
| * Sets subclass instance's address and size. |
| * |
| * \todo allow subclass to specify parameter address range directly (e.g. do not assume that |
| * they are local to the subclass instance) |
| * |
| * \param T type of the derived instance |
| * \param instance pointer to the derived instance |
| */ |
| template<typename T> |
| inline C2_HIDE void setDerivedInstance(T *instance) { |
| setInterfaceAddressBounds((uintptr_t)instance, (uintptr_t)(instance + 1)); |
| } |
| |
| C2_DO_NOT_COPY(C2InterfaceHelper); |
| }; |
| |
| /** |
| * Creates a C2ParamFieldValuesBuilder class for a field of a parameter |
| * |
| * \param spParam a configuration parameter in an interface class subclassed from C2InterfaceHelper. |
| * \param field a field of such parameter |
| */ |
| #define C2F(spParam, field) \ |
| C2ParamFieldValuesBuilder< \ |
| typename _c2_reduce_enum_to_underlying_type< \ |
| typename std::remove_reference< \ |
| typename std::remove_extent< \ |
| decltype(spParam->field)>::type>::type>::type>( \ |
| C2ParamField(spParam.get(), &spParam->field)) |
| |
| #endif // C2UTILS_INTERFACE_HELPER_H_ |