工作队列

更新时间:2023-12-19 08:36:58下载pdf

本文介绍工作队列服务。

基本概念

针对一些需要缓存并依赖一些处理函数实现处理的相关事件场景,TuyaOS 提供了一套标准的、基于回调函数的数据队列异步处理服务。当涂鸦的应用中有大量事件需要缓存并执行,便可以利用这套工作队列服务完成相关的应用开发。

功能描述

实现任务立即触发、延迟触发和周期性触发执行。

工作原理/实现方案

工作队列初始化

WORKQ_SYSTEM
WORKQ_HIGHTPRI
工作队列初始化
创建线程 wq_system 并且
优先级 THREAD_PRIO_2
创建线程 wq_highpri 并且
优先级 THREAD_PRIO_1
创建队列
创建队列
初始化完成

工作任务处理

workq_initworkq_threadworkq_schedule资源初始化tal_semaphore_wait(信号量挂起)tuya_queue_input(链表成员创建入链,并发送信号量)work_item.cb(接收到信号量读取链表执行回调)workq_initworkq_threadworkq_schedule

开发指导

运行环境

  • 开发框架

    Wi-Fi 开发框架的通用功能

  • 关联组件

    tal_system_service

  • App 版本

    无特殊要求

  • 其他

    无特殊要求

使用方法

对任务响应优先级较高的使用 WORKQ_HIGHTPRI,响应要求一般的使用 WORKQ_SYSTEM 入队,延迟执行任务使用,请参考 使用示例

类型定义

/**
 * @brief TuyaOS provides you with two workqueue services for convenience.
 */
typedef enum {
    /**
     * low priority workqueue (block operations are allowed)
     */
    WORKQ_SYSTEM,
    /**
     * high priority workqueue (block operations are not allowed)
     */
    WORKQ_HIGHTPRI
}WORKQ_SERVICE_E;

/**
 * @brief delayed work entry definition
 */
typedef struct {
    DELAYED_WORK_HANDLE *delayed_work; // delayed work handle
    WORKQUEUE_CB delayed_work_cb;      // delayed work callback
}DELAYED_WORK_ENTRY_S;

typedef VOID_T* WORKQUEUE_HANDLE;
typedef VOID_T* DELAYED_WORK_HANDLE;

回调函数

typedef VOID_T (*WORKQUEUE_CB)(VOID_T *data);

API 说明

工作队列初始化

/**
 * @brief init ty work queue service
 *
 * @return OPRT_OK on success. Others on error, please refer to tuya_error_code.h
 */
OPERATE_RET tal_workq_init(VOID_T);

获取工作队列句柄

/**
 * @brief get handle of workqueue service
 *
 * @param[in] service the workqueue service
 *
 * @return WORKQUEUE_HANDLE handle of workqueue service
 */
WORKQUEUE_HANDLE tal_workq_get_handle(WORKQ_SERVICE_E service);

工作任务入队

/**
 * @brief add work to work queue
 *
 * @param[in] service the workqueue service
 * @param[in] cb, call back of work
 * @param[in] data, parameter of call back
 *
 * @return OPRT_OK on success. Others on error, please refer to tuya_error_code.h
 */
OPERATE_RET tal_workq_schedule(WORKQ_SERVICE_E service, WORKQUEUE_CB cb, VOID_T *data);

工作任务入队,即时任务将首先出队

/**
 * @brief put work task in workqueue, instant tasks will be dequeued first
 *
 * @param[in] service the workqueue service
 * @param[in] cb the work callback
 * @param[in] data the work data
 *
 * @return OPRT_OK on success. Others on error, please refer to tuya_error_code.h
 */
OPERATE_RET tal_workq_schedule_instant(WORKQ_SERVICE_E service, WORKQUEUE_CB cb, VOID_T *data);

取消工作队列中的任务

/**
 * @brief cancel work task in workqueue
 *
 * @param[in] service the workqueue service
 * @param[in] cb the work callback
 * @param[in] data the work data
 *
 * @return OPRT_OK on success. Others on error, please refer to tuya_error_code.h
 */
OPERATE_RET tal_workq_cancel(WORKQ_SERVICE_E service, WORKQUEUE_CB cb, VOID_T *data);

获取工作队列任务数量

/**
 * @brief get current work number in work queue
 *
 * @param[in] service the workqueue service
 *
 * @note This API is used for get the current work number in work queue
 *
 * @return current work number in the work queue
 */
UINT16_T tal_workq_get_num(WORKQ_SERVICE_E service);

转储工作队列中的所有任务

/**
 * @brief dump all work in work queue.
 *
 * @param[in] service the workqueue service
 */
VOID_T tal_workq_dump(WORKQ_SERVICE_E service);

初始化延迟工作队列

/**
 * @brief init delayed work task
 *
 * @param[in] service the workqueue service
 * @param[in] cb the work callback
 * @param[in] data the work data
 * @param[out] delayed_work handle of delayed work
 *
 * @return OPRT_OK on success. Others on error, please refer to tuya_error_code.h
 */
OPERATE_RET tal_workq_init_delayed(WORKQ_SERVICE_E service, WORKQUEUE_CB cb, VOID_T *data, DELAYED_WORK_HANDLE *delayed_work);

延迟工作任务启动

/**
 * @brief put work task in workqueue after delay
 *
 * @param[in] delayed_work handle of delayed work
 * @param[in] interval number of ms to wait or 0 for immediate execution
 * @param[in] type see @LOOP_TYPE
 *
 * @return OPRT_OK on success. Others on error, please refer to tuya_error_code.h
 */
OPERATE_RET tal_workq_start_delayed(DELAYED_WORK_HANDLE delayed_work,
    TIME_MS interval, LOOP_TYPE type);

停止延迟任务

/**
 * @brief stop delayed work
 *
 * @param[in] delayed_work handle of delayed work
 *
 * @return OPRT_OK on success. Others on error, please refer to tuya_error_code.h
 */
OPERATE_RET tal_workq_stop_delayed(DELAYED_WORK_HANDLE delayed_work);

延迟工作队列取消

/**
 * @brief cancel delay work
 *
 * @param[in] delayed_work handle of delayed work
 *
 * @return OPRT_OK on success. Others on error, please refer to tuya_error_code.h
 */
OPERATE_RET tal_workq_cancel_delayed(DELAYED_WORK_HANDLE delayed_work);

使用示例

//工作队列执行回调
VOID_T work_queue_cb(VOID_T *data)
{
    return;
}

STATIC VOID_T wq_demo(VOID_T)
{
    OPERATE_RET op_ret = OPRT_OK;
    WORKQUEUE_HANDLE wq_hand = NULL;

    //应用调用 tuya_iot_init_params 也会执行 tal_workq_init
    op_ret = tal_workq_init();
    if (OPRT_OK != op_ret) {
        return;
    }

    op_ret = tal_workq_schedule(WORKQ_HIGHTPRI, work_queue_cb, NULL);
    if (OPRT_OK != op_ret) {
        PR_ERR("bt work queue add fail:%d", op_ret);
        return;
    }

    return;
}

STATIC VOID_T wq_dalayed_demo(VOID_T)
{
    OPERATE_RET op_ret = OPRT_OK;
    DELAYED_WORK_HANDLE dl_wq_hand = NULL;

    op_ret = tal_workq_init_delayed(WORKQ_HIGHTPRI, work_queue_cb, NULL, &dl_wq_hand);
    if (OPRT_OK != op_ret) {
        PR_ERR("op_ret:%d", op_ret);
        return;
    }

    //延迟 1 秒后启动任务
    op_ret = tal_workq_start_delayed(dl_wq_hand, 1000, LOOP_ONCE);
    if (OPRT_OK != op_ret) {
        PR_ERR("op_ret:%d", op_ret);
        return;
    }
}

注意事项

队列处理尽量不要长时间阻塞,以免影响其它任务执行。

FAQ

队列任务个数最大多少?

队列任务每种类型个数最大 100 个。