1.New macros for obtaining the number of variable parameters, adaptive parameter concatenation macros, and separated concatenation macros have been added (in preparation for the device tree).
298 lines
7.9 KiB
C
298 lines
7.9 KiB
C
/**
|
|
* @copyright (c) 2024-2025, MacRsh
|
|
*
|
|
* @license SPDX-License-Identifier: Apache-2.0
|
|
*
|
|
* @date 2024-09-06 MacRsh First version
|
|
*/
|
|
|
|
#ifndef __MR_WORKQUEUE_H__
|
|
#define __MR_WORKQUEUE_H__
|
|
|
|
#include <mr_config.h>
|
|
#if defined(MR_USE_WORKQUEUE)
|
|
#include <mr-X/mr_timer.h>
|
|
#endif /* defined(MR_USE_WORKQUEUE) */
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif /* __cplusplus */
|
|
|
|
/**
|
|
* @addtogroup Workqueue
|
|
* @{
|
|
*/
|
|
|
|
#if defined(MR_USE_WORKQUEUE)
|
|
#if defined(MR_USE_WORKQUEUE_HOOK)
|
|
struct mr_workqueue;
|
|
|
|
/* Workqueue hook type */
|
|
typedef struct mr_workqueue_hook {
|
|
void (*suspend)(struct mr_workqueue *queue, void *param);
|
|
void (*wakeup)(struct mr_workqueue *queue, void *param);
|
|
void *param;
|
|
} mr_workqueue_hook_t;
|
|
#endif /* defined(MR_USE_WORKQUEUE_HOOK) */
|
|
|
|
/* Workqueue type */
|
|
MR_CLAZZ_EXPORT(workqueue);
|
|
typedef struct mr_workqueue {
|
|
mr_object_t parent;
|
|
mr_atomic_t depth;
|
|
mr_atomic_t dying;
|
|
mr_timer_t timer;
|
|
mr_list_t tlist;
|
|
mr_list_t list;
|
|
#if defined(MR_USE_WORKQUEUE_HOOK)
|
|
const mr_workqueue_hook_t *hook;
|
|
#endif /* defined(MR_USE_WORKQUEUE_HOOK) */
|
|
} mr_workqueue_t;
|
|
|
|
/* Work type */
|
|
MR_CLAZZ_EXPORT(work);
|
|
typedef struct mr_work {
|
|
mr_object_t parent;
|
|
mr_list_t list;
|
|
mr_ptr_t queue;
|
|
mr_tick_t tick;
|
|
mr_ptr_t entry;
|
|
mr_ptr_t param;
|
|
} mr_work_t;
|
|
|
|
/* Work entry type */
|
|
typedef void(mr_work_entry_t)(struct mr_work *work, void *param);
|
|
|
|
/**
|
|
* @brief This macro function initializes a workqueue.
|
|
*
|
|
* @param _queue The workqueue.
|
|
*/
|
|
#define MR_WORKQUEUE_INIT(_queue) \
|
|
{.parent = MR_OBJECT_INIT(MR_CLAZZ_FIND(workqueue)), \
|
|
.depth = MR_ATOMIC_INIT(0), \
|
|
.dying = MR_ATOMIC_INIT(MR_FALSE), \
|
|
.tlist = MR_LIST_INIT(&(_queue)->tlist), \
|
|
.list = MR_LIST_INIT(&(_queue)->list)}
|
|
|
|
/**
|
|
* @brief This function initializes a workqueue.
|
|
*
|
|
* @param queue The workqueue.
|
|
* @return 0 on success, a negative error code on failure.
|
|
*/
|
|
mr_err_t mr_workqueue_init(mr_workqueue_t *queue);
|
|
|
|
/**
|
|
* @brief This function creates a workqueue.
|
|
*
|
|
* @return The workqueue on success, MR_NULL on failure.
|
|
*/
|
|
mr_workqueue_t *mr_workqueue_create(void);
|
|
|
|
/**
|
|
* @brief This function deletes a workqueue.
|
|
*
|
|
* @param queue The workqueue.
|
|
* @return 0 on success, a negative error code on failure.
|
|
*/
|
|
mr_err_t mr_workqueue_del(mr_workqueue_t *queue);
|
|
|
|
/**
|
|
* @brief This function executes a workqueue.
|
|
*
|
|
* @param queue The workqueue.
|
|
* @return 0 on success, a negative error code on failure.
|
|
*/
|
|
mr_err_t mr_workqueue_execute(mr_workqueue_t *queue);
|
|
|
|
/**
|
|
* @brief This function adds a work to a workqueue.
|
|
*
|
|
* @param queue The workqueue.
|
|
* @param work The work.
|
|
* @return 0 on success, a negative error code on failure.
|
|
*/
|
|
mr_err_t mr_workqueue_work(mr_workqueue_t *queue, mr_work_t *work);
|
|
|
|
/**
|
|
* @brief This function adds a delayed work to a workqueue.
|
|
*
|
|
* @param queue The workqueue.
|
|
* @param work The work.
|
|
* @param tick The delay tick.
|
|
* @return 0 on success, a negative error code on failure.
|
|
*/
|
|
mr_err_t mr_workqueue_delayed_work(mr_workqueue_t *queue, mr_work_t *work,
|
|
mr_tick_t tick);
|
|
|
|
#if defined(MR_USE_WORKQUEUE_HOOK)
|
|
/**
|
|
* @brief This function sets a workqueue hook.
|
|
*
|
|
* @param queue The workqueue.
|
|
* @param hook The workqueue hook.
|
|
* @return 0 on success, a negative error code on failure.
|
|
*
|
|
* @note Recommend to use a semaphore with an initial value of 0 as the hook.
|
|
*/
|
|
MR_INLINE mr_err_t mr_workqueue_hook_set(mr_workqueue_t *queue,
|
|
const mr_workqueue_hook_t *hook) {
|
|
/* Check parameter */
|
|
MR_ASSERT((queue != MR_NULL) && MR_OBJECT_IS_INITED(queue));
|
|
MR_ASSERT(MR_OBJECT_CLAZZ_IS(queue, workqueue));
|
|
MR_ASSERT(hook != MR_NULL);
|
|
|
|
/* Set workqueue hook */
|
|
queue->hook = hook;
|
|
return 0;
|
|
}
|
|
#endif /* defined(MR_USE_WORKQUEUE_HOOK) */
|
|
|
|
/**
|
|
* @brief This function gets a workqueue.
|
|
*
|
|
* @param queue The workqueue.
|
|
* @return The workqueue on success, MR_NULL on failure.
|
|
*/
|
|
MR_INLINE mr_workqueue_t *mr_workqueue_get(mr_workqueue_t *queue) {
|
|
/* Get workqueue reference */
|
|
return (mr_workqueue_t *)mr_object_get((mr_object_t *)queue);
|
|
}
|
|
|
|
/**
|
|
* @brief This function puts a workqueue.
|
|
*
|
|
* @param queue The workqueue.
|
|
* @return MR_TRUE on end of life cycle, MR_FALSE otherwise.
|
|
*/
|
|
MR_INLINE mr_bool_t mr_workqueue_put(mr_workqueue_t *queue) {
|
|
/* Put workqueue reference */
|
|
return mr_object_put((mr_object_t *)queue);
|
|
}
|
|
|
|
/**
|
|
* @brief This macro function initializes a work.
|
|
*
|
|
* @param _work The work.
|
|
* @param _entry The work entry.
|
|
* @param _param The entry parameter.
|
|
*/
|
|
#define MR_WORK_INIT(_work, _entry, _param) \
|
|
{.parent = MR_OBJECT_INIT(MR_CLAZZ_FIND(work)), \
|
|
.list = MR_LIST_INIT(&(_work)->list), \
|
|
.queue = MR_NULL, \
|
|
.tick = 0, \
|
|
.entry = (_entry), \
|
|
.param = (_param)}
|
|
|
|
/**
|
|
* @brief This function initializes a work.
|
|
*
|
|
* @param work The work.
|
|
* @param entry The work entry.
|
|
* @param param The entry parameter.
|
|
* @return 0 on success, a negative error code on failure.
|
|
*/
|
|
mr_err_t mr_work_init(mr_work_t *work, mr_work_entry_t *entry, void *param);
|
|
|
|
/**
|
|
* @brief This function creates a work.
|
|
*
|
|
* @param entry The work entry.
|
|
* @param param The entry parameter.
|
|
* @return The work on success, MR_NULL on failure.
|
|
*/
|
|
mr_work_t *mr_work_create(mr_work_entry_t *entry, void *param);
|
|
|
|
/**
|
|
* @brief This function deletes a work.
|
|
*
|
|
* @param work The work.
|
|
* @return 0 on success, a negative error code on failure.
|
|
*/
|
|
mr_err_t mr_work_del(mr_work_t *work);
|
|
|
|
/**
|
|
* @brief This macro function checks if a work is running.
|
|
*
|
|
* @param _work The work.
|
|
* @return MR_TRUE if the work is running, MR_FALSE otherwise.
|
|
*/
|
|
#define MR_WORK_IS_RUNNING(_work) (!mr_list_is_empty(&(_work)->list))
|
|
|
|
/**
|
|
* @brief This function schedules a work.
|
|
*
|
|
* @param work The work.
|
|
* @return 0 on success, a negative error code on failure.
|
|
*/
|
|
mr_err_t mr_work_schedule(mr_work_t *work);
|
|
|
|
/**
|
|
* @brief This function schedules a delayed work.
|
|
*
|
|
* @param work The work.
|
|
* @param tick The delay tick.
|
|
* @return 0 on success, a negative error code on failure.
|
|
*/
|
|
mr_err_t mr_work_delayed_schedule(mr_work_t *work, mr_tick_t tick);
|
|
|
|
/**
|
|
* @brief This function cancels a work.
|
|
*
|
|
* @param work The work.
|
|
* @return 0 on success, a negative error code on failure.
|
|
*/
|
|
mr_err_t mr_work_cancel(mr_work_t *work);
|
|
|
|
/**
|
|
* @brief This function binds a work to a workqueue.
|
|
*
|
|
* @param work The work.
|
|
* @param queue The workqueue.
|
|
* @return 0 on success, a negative error code on failure.
|
|
*/
|
|
MR_INLINE mr_err_t mr_work_bind(mr_work_t *work, mr_workqueue_t *queue) {
|
|
/* Check parameter */
|
|
MR_ASSERT((work != MR_NULL) && MR_OBJECT_IS_INITED(work));
|
|
MR_ASSERT(MR_OBJECT_CLAZZ_IS(work, work));
|
|
MR_ASSERT((queue != MR_NULL) && MR_OBJECT_IS_INITED(queue));
|
|
MR_ASSERT(MR_OBJECT_CLAZZ_IS(queue, workqueue));
|
|
|
|
/* Set workqueue */
|
|
work->queue = queue;
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* @brief This function gets a work.
|
|
*
|
|
* @param work The work.
|
|
* @return The work on success, MR_NULL on failure.
|
|
*/
|
|
MR_INLINE mr_work_t *mr_work_get(mr_work_t *work) {
|
|
/* Get work reference */
|
|
return (mr_work_t *)mr_object_get((mr_object_t *)work);
|
|
}
|
|
|
|
/**
|
|
* @brief This function puts a work.
|
|
*
|
|
* @param work The work.
|
|
* @return MR_TRUE on end of life cycle, MR_FALSE otherwise.
|
|
*/
|
|
MR_INLINE mr_bool_t mr_work_put(mr_work_t *work) {
|
|
/* Put work reference */
|
|
return mr_object_put((mr_object_t *)work);
|
|
}
|
|
#endif /* defined(MR_USE_WORKQUEUE) */
|
|
|
|
/** @} */
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif /* __cplusplus */
|
|
|
|
#endif /* __MR_WORKQUEUE_H__ */
|