Git Product home page Git Product logo

act-common-mc-common's Introduction

act-common - /mc/common

Является частью проекта act-common.

Проект содержит:

  • /include - общие включаемые файлы
  • /test - тесты к ним
  • /main.cpp - точка запуска тестов

API

API Header Exports
Definitions common.h byte, sbyte, bool, true, false
Utility common.h INT_MAX, INT_MAX, ABS(), ulog2(), safe_add()
Utility lock_guard.h lock_guard<>
Utility array.h array<>, array_size<>()
IO API iobuf.h iobuf<>, iobuf_read<>(), iobuf_write<>()
USART API usart.h interrupt handlers, usart_ibuf, usart_obuf

lock_guard<>

Класс помогает в элегантном создании критической секции. Переменные, к которым производится доступ как из основного потока, так и из прерываний, должны быть защищены блокировкой (запрет прерываний) для предотвращения параллельных операций над данными. lock_guard<> делает это в одну строчку.

// ... some code
{
    lock_guard < true > guard;
    // вход в критическую секцию с созданием `guard`
    
    shared_variable++; // внутри критической секции, прерывания запрещены
    
    // выход их критической секции с разрушением `guard`
}
// ... some other code

В зависимости от значения параметра шаблона (true или false) класс будет либо запоминать значение флага прерываний при входе в критическую секцию и восстанавливать по выходе, либо всегда разрешать прерывания по выходе.

array<>

Класс несколько аналогичен std::array<> в назначении -- инкапсулирует статический массив известного во время компиляции размера. Размер такого массива может быть получен функцией array_size<>(), которая при должном уровне оптимизаций транслируется в числовую константу времени компиляции (а не переменную времени выполнения), что, безусловно, ускоряет некоторые вычисления.

typedef array
<
    byte /* тип размера массива / индекса массива */,
    103u /* размер массива                        */,
    byte /* тип содержимого массива               */
>
my_array_of_103_elements;

my_array_of_103_elements arr;
arr[0] = (byte) 1u;
arr[1] = (byte) 46u;
// ...

// эквивалентно

array < byte, 103u, byte> arr;
arr[0] = (byte) 1u;
arr[1] = (byte) 46u;
// ...

byte arr_size = array_size(arr);
// эквивалентно
byte arr_size = 103u;

size_aware_pointer<>

В некотором смысле подобен array<> с тем исключением, что класс сам не определяет/создает (статический / динамический) массив и не знает его размер во время компиляции, а лишь хранит указатель на массив и его размер.

Функция array_size<>() перегружена и для этого типа.

typedef size_aware_pointer
<
    byte /* тип размера массива / индекса массива */,
    byte /* тип содержимого массива               */
>
my_array_of_any_elements;

byte data[103];
my_array_of_any_elements arr(data, 103u);
arr[0] = (byte) 1u;
arr[1] = (byte) 46u;
// ...

// эквивалентно

byte data[103];
size_aware_pointer < byte, byte > arr(data, 103u);
arr[0] = (byte) 1u;
arr[1] = (byte) 46u;
// ...

byte arr_size = array_size(arr);
// эквивалентно
byte arr_size = arr.capacity;

iobuf API

iobuf<>, в отличие от array<> и size_aware_pointer<>, имеет дополнительные поля для использования внутри iobuf api. Сам класс является наследником некоторого типа T (шаблонный параметр), которым может быть как array<>, size_aware_pointer<>, так и любой определенный пользователем тип, удовлетворяющий некоторым ограничениям (см. array_base<>).

iobuf_api предоставляет обобщенный интерфейс для работы с кольцевыми буферами. Имеет две основные функции:

  • iobuf_read<>() -- читает данные из iobuf<> и записывает их в переданных массив
  • iobuf_write<>() -- пишет данные из массива в переданных iobuf<>
iobuf < array < byte, 30u, byte > > obuf;

byte data[3] = { 1u, 3u, 5u };

byte w /* сколько было записано */
      = iobuf_write
        <
            sp_process_any, /* записать столько, сколько возможно    */
            lp_use_lock     /* защитить указатели буфера блокировкой */
        >
        (
            obuf,   /* куда записать         */
            data,   /* что записать          */
            3u      /* сколько байт записать */
        );

// эквивалентно

byte w = iobuf_write_any(obuf, data, 3u);

// внутри прерывания

byte b;

byte success /* сколько было прочитано */
      = iobuf_read
        <
            lp_adopt_lock   /* использовать существующую блокировку прерываний */
        >
        (
            b,      /* куда записать    */
            obuf    /* откуда прочитать */
        );
if (!success /* байт не был прочитан */)
{
    // ...
}

success_policy определяет две константы: sp_process_any и sp_process_full. Про первую уже было сказано. В случае, если размер буфера не позволяет записать указанное количество байт, будет записано столько, сколько можно. При этом число записанных байтов будет возвращено. Вторая запрещает продолжение операции в случае, если в буфере не хватает места, возвращая всегда либо 0 (запрет), либо указанное количество байт (успех).

lock_policy определяет политику применения блокировки. Внутри прерывания блокировка автоматически получена засчет свойства этих самых прерываний, поэтому не нужно применять ручной блокировки. Это не запрещается, однако это менее оптимально.

Следует отметить, что механизм шаблонов влечет колоссальное разрастание размера кода в силу того, что на каждый новый шаблонный параметр генерируется новая функция. Так, в приведенном примере будет сгенерировано две функции: iobuf_write<sp_process_any, lp_use_lock, array <byte, 30u, byte> > и iobuf_read<lp_adopt_lock, array <byte, 30u, byte> >. Первая функция занимает ~150 байт, вторая -- ~50 байт. В случае применения в коде функции iobuf_write с параметром sp_process_full к тому же буферу будет сгенерирована еще одна функция iobuf_write<sp_process_full, lp_use_lock, array<byte, 30u, byte> > на 150 байт. При применении функции к буферу другого размера / другого типа будет создана еще одна функция на 150 байт. И т.д. Поэтому нецелесообразно использовать эти функции с множеством разных шаблонных параметров (array <byte, 30u, byte> и array <byte, 60u, byte> -- разные типы, для них будут сгенерированы дополнительные варианты фунций API). При необходимости иметь возможность взаимодействовать с буферами разного размера и типа следует отойти от использования array<> и перейти к size_aware_pointer<>.

USART API

API определяет два буфера: usart_ibuf (входной) и usart_obuf (выходной). Пользователь должен писать данные в выходной и читать данные из входного.

Кроме буферов генерируются обработчики прерываний, использующие два указанных буфера для реализации процесса приема-передачи данных.

Для представления об определенных макросах следует заглянуть в исходники.

Тестирование

Функция main() файла main.cpp является точкой входа. Там размещаются вызовы функций-тестеров соответствующих API.

Функции-тестеры содержатся в заголовочных файлах директории /test, файлы которой имеют постфикс _test.

К сожалению, тестирование не может быть автоматизировано, потому вводятся правила юнит-тестирования.

Каждый файл с постфиксом _test рассматривается как индивидуальный набор юнит-тестов. В нем размещается массив bool[N], где N -- максимальное количество проверяемых в файле условий. Возможно также наличие массива const char * [N] или const char * [M], где M -- количество независимых юнит-тестов, однако в большинстве случаев это излишне, требует много памяти, которой и так слишком мало, а также дополнительной работы руками. По окончании теста все N элементов массива должны быть заполнены единицами (true). В случае, если в каком-либо элементе появляется ноль (false) -- какое-то условие провалено. Поэтому ставится точка останова в конец метода main и в наблюдениях проверяется наличие нулей во всех таких массивах. При наличии нулей определяется проваленное условие и начинается обычный анализ кода теста и тестируемого кода.

Пример

// main.cpp

#include "test/foo_test.h"
#include "test/bar_test.h"

void main()
{
    foo_test();
    bar_test();
}
// test/foo_test.h

#include <act-common/foo.h>

bool foo_test_results[64];

void foo_test_case_1(byte & i)
{
    foo f;
    
    // ----- 1 2 3
    
    foo_test_results[i++] = f.bar(0);
    foo_test_results[i++] = !f.bar(1);
    foo_test_results[i++] = (f.bar(2) == 4);
    
    // ----- 4 5
    
    foo.n = 34;
    
    foo_test_results[i++] = (f.bar(0) == 89);
    foo_test_results[i++] = (f.n == 34);
}

// ...

void foo_test()
{
    byte i = 1; // для удобства нумеруем с 1
    foo_test_case_1(i); // i = 1
    foo_test_case_2(i); // i = 6
    foo_test_case_3(i); // i = 14
    // i = 21 -> foo_test_results должен содержать 20 единиц
    //           не считая нулевой элемент 0
    // <breakpoint>
}

act-common-mc-common's People

Contributors

kalaider avatar

Stargazers

 avatar

Watchers

 avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.