c++ 防止在硬件资源耗尽时创建对象

neekobn8  于 2023-05-02  发布在  其他
关注(0)|答案(2)|浏览(106)

在嵌入式项目中工作时,您经常为硬件资源(如UART(或串行端口))编写驱动程序。一个微控制器可以有多个不同的硬件UART示例(有时也有专门的,比如USARTS)。
我正在寻找一种模式,允许创建驱动程序的多个示例,以便您可以使用不同的硬件外围设备,同时保证只有一个对象“连接”或“代表”物理设备。
以UART1、UART2、UART3、USART4和USART5为例,是否有方法允许:

auto uart1 = UartDriver(UART1, ...);
auto uart2 = UartDriver(UART2, ...);
auto usart4= UsartDriver(USART4, ...);
// later in the code
auto another_instance = UartDriver(UART1, ...); // should not compile

由于资源有限,我无法使用异常。

jfgube3f

jfgube3f1#

除非所有对象都是静态示例化的,否则阻止编译在运行时示例化对象的代码可能是不可能的,即使这样,我也怀疑任何解决方案的实用性。
然而,资源使用的运行时检查是直接的。例如,在outline中:

class UsartDriver
{
    public :
        UsartDriver( int usart ) : m_usart(usart)
        {
            assert( !m_resource_in_use[m_usart] ) ;
            m_resource_in_use[m_usart] = true ;
            ...
        }

        ~UsartDriver()
        {
            m_resource_in_use[m_usart] = false ;
        }

        ...

    private :
        static bool m_resource_in_use[MAX_USART] ;
        int m_usart ;    
} ;

bool UsartDriver::m_resource_in_use[MAX_USART] ;
t9aqgxwy

t9aqgxwy2#

虽然我不太愿意建议将此作为解决问题的方法,但有一种方法可以构建一个值元组,使所有设备都具有不同的类型,并进行编译时检查。它使用了C++ 11的特性:

#include <type_traits>
#include <tuple>

首先,我定义了一个递归可变参数模板,它使用std::is_same检查参数包中的第一个类型是否与所有其他类型不同:

// base case: true
template<typename... Types>
struct head_distinct {
    static const bool v = true;
};

// general case, T != O and the property holds recursively 
// for T and the remaining types
template<typename T , typename O, typename... Others>
struct head_distinct<T, O, Others...> {
    static const bool v =
       !std::is_same<T, O>::value
    && head_distinct<T, Others...>::v;
};

一旦你有了这个,你就可以有一个alldiffs predicate trait,它确保所有类型对都是不同的(算法是二次的,但在编译时):

// base case: true
template<typename... Types>
struct alldiffs {
    static const bool v = true;
};

// general case: T is distinct from all other Types
// and recursively, alldiffs(Types)
template<typename T, typename... Types>
struct alldiffs<T, Types...> {
    static const bool v = head_distinct<T, Types...>::v 
        && alldiffs<Types...>::v;
};

最后,你可以实现一个基本上是元组的数据结构,但是使用static_assert,所有类型都是不同的:

template<typename ... T>
struct Blob {
    Blob(T&&... args) : tuple(std::forward(...args)) {
        static_assert(alldiffs<T...>::v, 
        "all types must be different");
    };
    std::tuple<T...> tuple;
};

例如:

class A{};
struct B{};

int main()
{
    Blob<A,B> ok({},{}); // compiles
    Blob<A,A> ko({},{}); // does not compile
}
<source>: In constructor 'Blob<T>::Blob(T&& ...)':
<source>:29:44: error: expected primary-expression before '...' token
   29 |     Blob(T&&... args) : tuple(std::forward(...args)) {
      |                                            ^~~
<source>: In instantiation of 'Blob<T>::Blob(T&& ...) [with T = {A, A}]':
<source>:42:23:   required from here
<source>:30:39: error: static assertion failed: all types must be different
   30 |         static_assert(alldiffs<T...>::v,
      |                                       ^
<source>:30:39: note: 'alldiffs<A, A>::v' evaluates to false
Compiler returned: 1

相关问题