feat(core): rename and restructure event handling and initialization

- Rename exint_init to exint_initialize
- Update event handling to use multiple threads
- Add epoch checking to DataQueue
- Modify config reading logic
- Update build scripts
- Refactor test cases
This commit is contained in:
ovizro 2024-12-14 14:39:28 +08:00
parent ccaa4908b5
commit 53a5fe6d50
18 changed files with 508 additions and 65 deletions

View File

@ -31,7 +31,7 @@ if (CMAKE_CROSSCOMPILING)
message(STATUS "CMAKE_SYSTEM_PROCESSOR: ${CMAKE_SYSTEM_PROCESSOR}")
endif()
include_directories(${CMAKE_SOURCE_DIR}/include)
include_directories(./include)
aux_source_directory(${CMAKE_SOURCE_DIR}/src SRC_LIST)
add_library(exint SHARED ${SRC_LIST})
@ -40,8 +40,9 @@ set_target_properties(exint_static PROPERTIES OUTPUT_NAME exint)
if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
target_compile_options(exint PRIVATE -Wno-nonnull -fvisibility=hidden)
target_compile_options(exint_static PRIVATE -Wno-nonnull -fvisibility=hidden)
endif()
link_libraries(pthread)
link_libraries(pthread util)
subdirs(tests)
add_subdirectory(tests)

View File

@ -29,7 +29,7 @@ cmake --build build -j6 --target test
以下接口由通讯模块公开可以在VOIX主程序中使用。
1. `void exint_init(const char* config_path, et_callback_t cb)`:模块初始化函数,此函数会读取配置文件,开启串口并启动模块所需的线程
1. `void exint_initialize(const char* config_path, et_callback_t cb)`:模块初始化函数,此函数会读取配置文件,开启串口并启动模块所需的线程
- `config_path`:配置文件路径
- `cb`:回调函数,用于进行指令响应和遥测数据请求
2. `void (*et_callback_t)(uint32_t type, size_t len, void* data)`:回调函数类型,内部数据为指针类型的数据包仅保证在回调函数中有效。

78
include/CCfgFileParser.h Executable file
View File

@ -0,0 +1,78 @@
#if !defined(AFX_CFGFILEPARSERGENERATOR_H__AAF8F913_7694_4A69_A05F_57A1A1887CA1__INCLUDED_)
#define AFX_CFGFILEPARSERGENERATOR_H__AAF8F913_7694_4A69_A05F_57A1A1887CA1__INCLUDED_
#include <stdlib.h>
#include <stdio.h>
#ifdef WIN32
#pragma warning(disable:4786)
#pragma warning(disable:4503)
#endif
#include <map>
#include <string>
class __attribute__((visibility("default"))) CCfgFileParser
{
public:
explicit CCfgFileParser(bool base64 = false,
char chSectionBMark = '[',
char chSectionEMark = ']',
char chRecordEMark = ';', //record end-mark
char chCommentMark = '#'
)
:m_base64(base64), m_chSectionBMark(chSectionBMark), m_chSectionEMark(chSectionEMark),
m_chRecordEMark(chRecordEMark), m_chCommentMark(chCommentMark), m_bShowError(false)
{
}
virtual ~CCfgFileParser() {}
typedef std::map<std::string, std::string> SECTION_CONTENT;
typedef std::map<std::string, SECTION_CONTENT > FILE_CONTENT;
private:
bool m_base64;
enum{
SYNTAX_ERROR = 0x100,
};
public:
bool m_bShowError;
const char* getErrorString(int err);
int parseFile(const char* lpszFilename);
int sections() const { return m_content.size(); }
FILE_CONTENT::const_iterator sectionBegin() const { return m_content.begin(); }
FILE_CONTENT::const_iterator sectionEnd() const { return m_content.end(); }
//return empty-string if no corresponding value presented.
bool getValue(const std::string& strSection, const std::string& strKey, const char *&Value) const;
bool getValue(const std::string& strKey, const char *&Value) const;
bool getIntValue(const std::string& strSection, const std::string& strKey, long &pValue) const;
bool getIntValue(const std::string& strKey, long &Value) const;
bool getDoubleValue(const std::string& strSection, const std::string& strKey, double &Value) const;
bool getDoubleValue(const std::string& strKey, double &Value) const;
void printContent();
protected:
bool extractSection(char* line, std::string& strSection);
bool extractKeyValue(char* line, std::pair<std::string, std::string>& pairKeyValue);
private:
FILE_CONTENT m_content;
char m_chSectionBMark;
char m_chSectionEMark;
char m_chRecordEMark;
char m_chCommentMark;
int m_error_line;
};
extern "C" __attribute__((visibility("default"))) CCfgFileParser* createParser();
extern "C" __attribute__((visibility("default"))) void deleteParser(CCfgFileParser* parser);
#endif // !defined(AFX_CFGFILEPARSERGENERATOR_H__AAF8F913_7694_4A69_A05F_57A1A1887CA1__INCLUDED_)

View File

@ -47,6 +47,8 @@ public:
}
};
typedef uint8_t queue_epoch_t;
template <typename T>
class DataQueue {
public:
@ -109,6 +111,18 @@ public:
return m_Queue.size();
}
queue_epoch_t GetEpoch() noexcept
{
std::lock_guard<std::mutex> lock(m_Mutex);
return m_CurrEpoch;
}
bool CheckEpoch(queue_epoch_t epoch) noexcept
{
std::lock_guard<std::mutex> lock(m_Mutex);
return m_CurrEpoch == epoch;
}
void Clear() noexcept
{
std::lock_guard<std::mutex> lock(m_Mutex);
@ -123,7 +137,7 @@ protected:
std::condition_variable m_Cond;
private:
uint8_t m_CurrEpoch;
queue_epoch_t m_CurrEpoch;
};
#endif

View File

@ -1,6 +1,7 @@
#ifndef _INCLUDE_EVENT_H_
#define _INCLUDE_EVENT_H_
#include <stdint.h>
#include <stddef.h>
#define CONCAT_(prefix, suffix) prefix##suffix
@ -23,8 +24,8 @@ typedef void (*event_callback)(const char*, size_t, void*, void*);
void exint_event(const char *event_name, size_t args_size, void *args);
int exint_event_register(const char *event_name, event_callback callback, void* user_data);
int exint_event_unregister(const char *event_name, event_callback callback, void* user_data);
void* exint_event_thread(void*);
void exint_event_thread_exit();
void exint_event_thread_start(uint8_t num);
void exint_event_thread_stop();
#ifdef __cplusplus
}

26
include/exint/handler.h Normal file
View File

@ -0,0 +1,26 @@
#ifndef _INCLUDE_EXINT_HANDLER_
#define _INCLUDE_EXINT_HANDLER_
#include <stdint.h>
#include "comframe.h"
#define ET_HDL_FLAG_DEFAULT 0
#define ET_HDL_FLAG_DISABLED 1
#define ET_HDL_FLAG_ASYNC 2
#define ET_HDL_FLAG_NOVERIFY 4
#ifdef __cplusplus
extern "C" {
#endif
struct EtHandlerDef {
uint16_t hd_type;
uint16_t hd_flags;
void (*hd_handler)(struct EtHandlerDef *handler, ComFrame* frame);
};
#ifdef __cplusplus
}
#endif
#endif

View File

@ -44,7 +44,7 @@ struct TelemetryRequestData {
typedef void (*et_callback_t)(uint32_t, size_t, void*);
EXTERN_INTERFACE_PUBLIC
int exint_init(const char* config_path, et_callback_t cb);
int exint_initialize(const char* config_path, et_callback_t cb);
EXTERN_INTERFACE_PUBLIC
void exint_send(uint32_t type, size_t len, void* data);
EXTERN_INTERFACE_PUBLIC

View File

@ -1,5 +1,9 @@
#!/bin/sh
mkdir -p dist
zip -r "dist/exint-build-$(date +%Y%m%d-%H%M%S).zip" bin/ lib/ config/\
NAME="dist/exint-build-$(date +%Y%m%d-%H%M%S).zip"
zip -r $NAME bin/ lib/ config/\
scripts/ README.md include/external_interface.h
echo "Created $NAME"

View File

@ -1,5 +1,9 @@
#!/bin/sh
mkdir -p dist
tar -czvf "dist/exint-$(date +%Y%m%d-%H%M%S).tar.gz" src/ include/ tests/ config/\
NAME="dist/exint-$(date +%Y%m%d-%H%M%S).tar.gz"
tar -czvf $NAME src/ include/ tests/ config/\
scripts/ toolchains/ README.md CMakeLists.txt mak .gitignore
echo "Created $NAME"

12
scripts/x3_mak Executable file
View File

@ -0,0 +1,12 @@
#!/bin/bash
SERVER="sunrise@192.168.50.58"
SDIST=$(./scripts/sdist.sh | tail -1 | sed "s/Created //")
scp -r ${SDIST} $SERVER:/tmp
ssh $SERVER << EOF
mkdir -p voix_exint && cd voix_exint
tar -xzf /tmp/$(basename ${SDIST})
./mak $@
rm -rf src/ include/ tests/ build/
EOF
rm -rf ./lib/x3/
scp -r $SERVER:voix_exint/lib/ ./lib/x3/

263
src/CCfgFileParser.cpp Executable file
View File

@ -0,0 +1,263 @@
//bb.cpp
#include <cstdio>
#include <cstring>
#include <fstream>
#include <cerrno>
#include <sstream>
#include <cstdlib>
#include <iostream>
#include "CCfgFileParser.h"
using namespace std;
static inline bool istab(int c) { return (c == '\t'); }
static inline char *strltrim(char *str) {
while (isspace(*str) || istab(*str)) {
++str;
}
return str;
}
static inline char *strrtrim(char *str) {
int len = strlen(str) - 1;
while (isspace(str[len]) || istab(str[len])) {
str[len--] = '\0';
}
return str;
}
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
int CCfgFileParser::parseFile(const char *lpszFilename) {
using std::string;
std::ifstream in1(lpszFilename);
if (!in1.is_open()) return errno;
char line[2048];
char *pline;
bool bInSection = false;
SECTION_CONTENT *pSC = NULL;
string strSection;
std::pair<string, string> pairKeyValue;
m_error_line = 0;
m_content.clear();
pSC = &m_content["default"];
bInSection = true;
string base64str("");
string mystr("");
while (!in1.eof()) {
in1.getline(line, sizeof(line));
if (line[strlen(line)] != '\n')
mystr += line + string("\n");
else
mystr += line;
}
in1.close();
stringstream in;
in.str(mystr);
while (!in.eof()) { /*if(base64str.size() > sizeof(line))
{
printf("error in config parser!\n");
return -1;
}
memcpy(line, base64str.c_str(), base64str.size());
*/
in.getline(line, sizeof(line));
pline = line;
++m_error_line;
pline = strltrim(pline);
if (pline[0] == '\0') continue; //white line, skip
if (pline[0] == m_chCommentMark) continue; //comment line, skip
if (bInSection) {
//is new-section begin?
if (pline[0] == m_chSectionBMark && extractSection(pline, strSection)) {
pSC = &m_content[strSection];
}
else if (extractKeyValue(pline, pairKeyValue)) {
//key-value pair
pSC->insert(pairKeyValue);
}
else {
//in.close();
return SYNTAX_ERROR;
}
}
else { //NOT in section
//is a valid section?
if (extractSection(pline, strSection)) {
pSC = &m_content[strSection];
bInSection = true;
}
else {
//in.close();
return SYNTAX_ERROR;
}
}
}
// in.close();
return 0;
}
bool CCfgFileParser::getValue(const std::string &strSection,
const std::string &strKey, const char * &Value) const {
FILE_CONTENT::const_iterator it;
if ((it = m_content.find(strSection)) != m_content.end()) {
SECTION_CONTENT::const_iterator p;
const SECTION_CONTENT &section = (*it).second;//m_content[strSection];
if ((p = section.find(strKey)) != section.end()) {
Value = ((*p).second).c_str();
return true;
}
}
if (m_bShowError)
fprintf(stderr, "***Error: fail to read [%s]:%s\n", strSection.c_str(), strKey.c_str());
return false;
}
bool CCfgFileParser::getValue(const std::string &strKey, const char * &pValue) const {
return getValue("default", strKey, pValue);
}
bool CCfgFileParser::getIntValue(const std::string &strSection,
const std::string& strKey, long& Value) const {
const char* pstr;
if (getValue(strSection, strKey, pstr) && strlen(pstr) > 0)
{
if (strlen(pstr) > 0)
{
Value = atol(pstr);
return true;
}
}
if (m_bShowError)
fprintf(stderr, "***Error: fail to read [%s]:%s\n", strSection.c_str(), strKey.c_str());
return false;
}
bool CCfgFileParser::getIntValue(const std::string &strKey, long &Value) const {
return getIntValue("default", strKey, Value);
}
bool CCfgFileParser::getDoubleValue(const std::string &strSection,
const std::string &strKey, double &Value) const {
const char *pstr;
if (getValue(strSection, strKey, pstr) && strlen(pstr) > 0)
{
Value = atof(pstr);
return true;
}
else
{
if (m_bShowError)
fprintf(stderr, "***Error: fail to read [%s]:%s\n", strSection.c_str(), strKey.c_str());
return false;
}
}
bool CCfgFileParser::getDoubleValue(const std::string &strKey, double &Value) const {
return getDoubleValue("default", strKey, Value);
}
/*
* Description: Extract section name
* Parameters: line[IN]---A string line to be parsed
* strSection[OUT]---Section name
*
* Return Value: if section name is in the line return true,or return false
*/
bool CCfgFileParser::extractSection(char *line, std::string &strSection) {
char *tmp;
if (line[0] == m_chSectionBMark) {
if ((tmp = strchr(++line, m_chSectionEMark)) != NULL) {
*tmp = '\0';
strSection = line;
return true;
}
}
return false;
}
/*
* Description: Parse a record line into a std:pair as key and value
* Parameters: line[IN]---A string to be parsed
* pairKeyValue[OUT]---Parsing result
*
* Return Value: If parse successfully return true,or return false
*/
bool CCfgFileParser::extractKeyValue(char *line,
std::pair<std::string, std::string> &pairKeyValue) {
char *tmp;
if ((tmp = strchr(line, m_chRecordEMark)) != NULL || (tmp = strchr(line, '\r')) != NULL ||
(tmp = strchr(line, '='))) {
if (*tmp == '=')
tmp = line + strlen(line); // tmp++;
*tmp = '\0'; //ignore content after ';'(the RecordEMark)
if ((tmp = strchr(line, '=')) != NULL) {
*tmp++ = '\0';
tmp = strltrim(tmp);
tmp = strrtrim(tmp);
line = strrtrim(line);
pairKeyValue.first = line;
pairKeyValue.second = tmp;
return true;
}
}
return false;
}
const char *CCfgFileParser::getErrorString(int err) {
static char buf[100];
if (err == SYNTAX_ERROR) {
sprintf(buf, "configuration file format is invalid at line %d", m_error_line);
return buf;
}
else {
return strerror(err);
}
}
void CCfgFileParser::printContent() {
using std::cout;
using std::endl;
FILE_CONTENT::const_iterator pf;
SECTION_CONTENT::const_iterator ps;
for (pf = m_content.begin(); pf != m_content.end(); ++pf) {
cout << "section:" << (*pf).first << endl;
const SECTION_CONTENT &sc = (*pf).second;
for (ps = sc.begin(); ps != sc.end(); ++ps) {
cout << '\t' << (*ps).first << "=" << (*ps).second << endl;
}
}
}
// 在库中定义一个工厂函数 createParser
extern "C" __attribute__((visibility("default"))) CCfgFileParser* createParser() {
return new CCfgFileParser(); // 在工厂函数中调用构造函数创建对象并返回指针
}
// 在库中定义一个销毁函数 deleteParser
extern "C" __attribute__((visibility("default"))) void deleteParser(CCfgFileParser* parser) {
// 在销毁函数中调用析构函数销毁对象
delete parser;
}

View File

@ -4,15 +4,19 @@
#include <tuple>
#include <memory>
#include <atomic>
#include <thread>
#include <assert.h>
#include <string.h>
#include "logging/logger.hpp"
#include "dataqueue.hpp"
#include "exint/event.h"
#include "exint/detail.h"
std::atomic_bool _is_event_thread_running { false };
DataQueue<std::tuple<const char*, event_callback, size_t, std::unique_ptr<uint8_t[]>, void*>> _event_queue;
using EventCallbackData = std::tuple<std::string, event_callback, size_t, std::unique_ptr<uint8_t[]>, void*>;
std::atomic_size_t _event_thread_count { 0 };
DataQueue<EventCallbackData> _event_queue;
static auto& logger = *logging::get_logger("exint::event");
static std::unordered_map<std::string, std::vector<std::pair<event_callback, void*>>>& get_event_map() {
static std::unordered_map<std::string, std::vector<std::pair<event_callback, void*>>> _events;
return _events;
@ -23,7 +27,7 @@ void exint_event(const char *event_name, size_t args_size, void *args) {
auto it = event_map.find(event_name);
if (it != event_map.end()) {
for (auto &pair : it->second) {
if (!_is_event_thread_running) {
if (!_event_thread_count.load()) {
pair.first(event_name, args_size, args, pair.second);
continue;
}
@ -70,31 +74,46 @@ int exint_event_unregister(const char *event_name, event_callback callback, void
}
void* exint_event_thread(void*) {
bool is_running = false;
if (!_is_event_thread_running.compare_exchange_strong(is_running, true)) {
return NULL;
}
const char* event_name;
std::string event_name;
event_callback callback;
size_t args_size;
std::unique_ptr<uint8_t[]> args;
void* user_data;
while (g_bKeepExintRuning) {
queue_epoch_t queue_epoch = _event_queue.GetEpoch();
_event_thread_count.fetch_add(1);
while (_event_queue.CheckEpoch(queue_epoch)) {
try {
std::tie(event_name, callback, args_size, args, user_data) = _event_queue.Pop();
} catch (const QueueException&) {
break;
}
callback(event_name, args_size, args.get(), user_data);
callback(event_name.c_str(), args_size, args.get(), user_data);
}
_is_event_thread_running.store(false);
_event_thread_count.fetch_sub(1);
return NULL;
}
void exint_event_thread_exit() {
bool is_running = true;
if (!_is_event_thread_running.compare_exchange_strong(is_running, false)) {
void exint_event_thread_start(uint8_t num) {
if (_event_thread_count.load()) {
logger.warn("event thread already started");
}
for (int i = 0; i < num; i++) {
std::thread([] { (void)exint_event_thread(NULL); }).detach();
}
while (_event_thread_count.load() != num) {
std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
logger.info("started %d event threads", num);
}
void exint_event_thread_stop() {
if (!_event_thread_count.load()) {
logger.warn("event thread already stopped");
return;
}
_event_queue.Clear();
while (_event_thread_count.load()) {
std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
logger.info("stopped event threads");
}

View File

@ -1,17 +1,18 @@
#include <pthread.h>
#include "logging/logger.hpp"
#include "comframe.h"
#include "CCfgFileParser.h"
#include "inicpp.hpp"
#include "exint/detail.h"
#include "exint/event.h"
static auto& logger = *logging::get_logger("exint");
static et_callback_t et_callback;
static pthread_t event_thread;
static pthread_t upperhost_thread;
static pthread_t telemetry_thread;
int g_iHostCom_tty_id;
int g_iTelemetry_Com_tty_id;
int g_iHostCom_tty_id = 0;
int g_iTelemetry_Com_tty_id = 0;
int g_iEnableAlarmCode = true;
bool g_bTelemetry_Open = true;
bool g_bKeepExintRuning = false;
@ -20,30 +21,53 @@ int g_iUseHostComForTelemetry = true;
uint8_t g_iAlarmCode[4] = {0xAA, 0xAA, 0xAA, 0xAA};
static int read_config(const char* config_path) {
inicpp::IniManager manager(config_path);
if (!manager.isSectionExists("System-Setting")) return -1;
auto system_setting = manager["System-Setting"];
auto host_com_path = system_setting["HostInfo_COM_Path"];
auto host_com_baudrate = system_setting.toInt("HostInfo_COM_Baud_Rate");
g_iHostCom_tty_id = get_com_tty_id(host_com_path.c_str(), host_com_baudrate);
g_iUseHostComForTelemetry = system_setting.toInt("Use_HostCOM_for_Telemetry");
CCfgFileParser config;
if (config.parseFile(config_path) < 0) {
logger.error("read config file %s failed", config_path);
return -1;
}
const char* host_com_path = NULL;
if (!config.getValue("System-Setting", "HostInfo_COM_Path", host_com_path)) {
logger.error("fail to read [System-Setting]:HostInfo_ExchangeMode from %s", config_path);
}
long host_com_baudrate = 115200;
if (!config.getIntValue("System-Setting", "HostInfo_COM_Baud_Rate", host_com_baudrate)) {
logger.error("fail to read [System-Setting]:HostInfo_COM_Baud_Rate from %s", config_path);
}
if (host_com_path != NULL)
g_iHostCom_tty_id = get_com_tty_id(host_com_path, host_com_baudrate);
g_bTelemetry_Open = system_setting.toInt("Telemetry_Open") == 1;
long use_host_com_for_telemetry = 1;
if (!config.getIntValue("System-Setting", "Use_HostCOM_for_Telemetry", use_host_com_for_telemetry)) {
logger.error("fail to read [System-Setting]:Use_HostCOM_for_Telemetry from %s", config_path);
}
g_iUseHostComForTelemetry = use_host_com_for_telemetry == 1;
long telemetry_open = 1;
if (!config.getIntValue("System-Setting", "Telemetry_Open", telemetry_open)) {
logger.error("fail to read [System-Setting]:Telemetry_Open from %s", config_path);
}
g_bTelemetry_Open = telemetry_open == 1;
if (g_bTelemetry_Open) {
auto telemetry_com_path = system_setting["Telemetry_COM_Path"];
auto telemetry_com_baudrate = system_setting.toInt("Telemetry_COM_Baud_Rate");
g_iTelemetry_Com_tty_id = get_com_tty_id(telemetry_com_path.c_str(), telemetry_com_baudrate);
const char* telemetry_com_path = NULL;
if (!config.getValue("System-Setting", "Telemetry_COM_Path", telemetry_com_path)) {
logger.error("fail to read [System-Setting]:Telemetry_COM_Path from %s", config_path);
}
long telemetry_com_baudrate = 115200;
if (!config.getIntValue("System-Setting", "Telemetry_COM_Baud_Rate", telemetry_com_baudrate)) {
logger.error("fail to read [System-Setting]:Telemetry_COM_Baud_Rate from %s", config_path);
}
if (telemetry_com_path != NULL)
g_iTelemetry_Com_tty_id = get_com_tty_id(telemetry_com_path, telemetry_com_baudrate);
}
return 0;
}
int exint_init(const char* config_path, et_callback_t cb) {
int exint_initialize(const char* config_path, et_callback_t cb) {
if (read_config(config_path)) return -1;
et_callback = cb;
g_bKeepExintRuning = true;
pthread_create(&event_thread, NULL, exint_event_thread, NULL);
exint_event_thread_start(1);
pthread_create(&upperhost_thread, NULL, upper_host_com_thread, NULL);
pthread_create(&telemetry_thread, NULL, telemetry_host_com_thread, NULL);
return 0;
@ -54,7 +78,7 @@ int exint_init_from_tty(int host_com_tty, int telemetry_com_tty, et_callback_t c
g_iHostCom_tty_id = host_com_tty;
g_iTelemetry_Com_tty_id = telemetry_com_tty;
g_bKeepExintRuning = true;
pthread_create(&event_thread, NULL, exint_event_thread, NULL);
exint_event_thread_start(1);
pthread_create(&upperhost_thread, NULL, upper_host_com_thread, NULL);
pthread_create(&telemetry_thread, NULL, telemetry_host_com_thread, NULL);
return 0;
@ -77,9 +101,9 @@ void exint_send(uint32_t type, size_t len, void* data) {
void exint_finialize() {
g_bKeepExintRuning = false;
pthread_cancel(event_thread);
pthread_cancel(upperhost_thread);
pthread_cancel(telemetry_thread);
exint_event_thread_stop();
}
void exint_handle_pack(uint32_t type, size_t len, void* data) {

1
src/handler/base.cpp Normal file
View File

@ -0,0 +1 @@
#include "exint/handler.h"

View File

@ -611,10 +611,10 @@ void send_command_upper_host(int length, void* payload) {
payload, length, true);
struct timeval tCurTime;
gettimeofday(&tCurTime, NULL);
uint64_t tCurTimeMs = tCurTime.tv_sec * 1000 + tCurTime.tv_usec / 1000;
uint64_t last_send_time;
while (need_resend) {
while (need_resend && g_bKeepExintRuning) {
gettimeofday(&tCurTime, NULL);
uint64_t tCurTimeMs = tCurTime.tv_sec * 1000 + tCurTime.tv_usec / 1000;
if (sendtime == 0) {
last_send_time = tCurTimeMs;
@ -678,3 +678,7 @@ void send_audio_upper_host(int length, void* payload) {
ON_EVENT(send_command) {
send_command_upper_host(args_size, args);
}
ON_EVENT(send_audio) {
send_audio_upper_host(args_size, args);
}

View File

@ -1,9 +1,5 @@
cmake_minimum_required(VERSION 3.15)
project(test)
set(TESTS_DIR .)
set(TEST_COMMON_SOURCE "${TESTS_DIR}/c_testcase.cpp")
file(GLOB_RECURSE TEST_FILES "${TESTS_DIR}/test_*.cpp")
foreach(TEST_FILE ${TEST_FILES})
@ -12,6 +8,9 @@ foreach(TEST_FILE ${TEST_FILES})
list(APPEND TEST_EXECUTABLES "${EXECUTABLE_OUTPUT_PATH}/${TEST_NAME}")
endforeach()
# message(STATUS "Test files: ${TEST_FILES}")
# message(STATUS "Test executables: ${TEST_EXECUTABLES}")
add_custom_target(test
COMMAND ${CMAKE_SOURCE_DIR}/scripts/unittest.py ${TEST_EXECUTABLES}
DEPENDS ${TEST_EXECUTABLES}

View File

@ -14,13 +14,11 @@ ON_EVENT(test) {
SETUP {
g_vec.clear();
g_bKeepExintRuning = true;
return 0;
}
TEARDOWN {
g_bKeepExintRuning = false;
exint_event_thread_exit();
exint_event_thread_stop();
return 0;
}
@ -38,15 +36,7 @@ TEST_CASE(test_event) {
}
TEST_CASE(test_event_thread) {
bool started = false;
std::thread t([&]() {
started = true;
exint_event_thread(NULL);
});
t.detach();
while (!started) {
std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
exint_event_thread_start(2);
int i = 2;
exint_event("test", sizeof(int), &i);
for (int i = 0; i < 10; i++) {
@ -60,5 +50,6 @@ TEST_CASE(test_event_thread) {
assert(false);
end:
exint_event_thread_stop();
END_TEST;
}

View File

@ -1,5 +1,7 @@
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR arm)
set(CMAKE_C_COMPILER arm-linux-gnueabihf-gcc-9)
set(CMAKE_CXX_COMPILER arm-linux-gnueabihf-g++-9)
set(CMAKE_C_COMPILER arm-none-linux-gnueabihf-gcc)
set(CMAKE_CXX_COMPILER arm-none-linux-gnueabihf-g++)
# set(CMAKE_CXX_FLAGS "-static ${CMAKE_CXX_FLAGS}")