mirror of
https://github.com/mudita/MuditaOS.git
synced 2026-01-17 18:37:53 -05:00
248 lines
8.1 KiB
C++
248 lines
8.1 KiB
C++
/****************************************************************************
|
|
*
|
|
* Copyright (c) 2017, Michael Becker (michael.f.becker@gmail.com)
|
|
*
|
|
* This file is part of the FreeRTOS Add-ons project.
|
|
*
|
|
* Source Code:
|
|
* https://github.com/michaelbecker/freertos-addons
|
|
*
|
|
* Project Page:
|
|
* http://michaelbecker.github.io/freertos-addons/
|
|
*
|
|
* On-line Documentation:
|
|
* http://michaelbecker.github.io/freertos-addons/docs/html/index.html
|
|
*
|
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
|
* copy of this software and associated documentation files
|
|
* (the "Software"), to deal in the Software without restriction, including
|
|
* without limitation the rights to use, copy, modify, merge, publish,
|
|
* distribute, sublicense, and/or sell copies of the Software, and to
|
|
* permit persons to whom the Software is furnished to do so,subject to the
|
|
* following conditions:
|
|
*
|
|
* + The above copyright notice and this permission notice shall be included
|
|
* in all copies or substantial portions of the Software.
|
|
* + Credit is appreciated, but not required, if you find this project
|
|
* useful enough to include in your application, product, device, etc.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
|
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
|
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
|
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
*
|
|
***************************************************************************/
|
|
|
|
|
|
#ifndef WORK_QUEUE_HPP_
|
|
#define WORK_QUEUE_HPP_
|
|
|
|
#include "thread.hpp"
|
|
#include "queue.hpp"
|
|
#include "semaphore.hpp"
|
|
|
|
|
|
namespace cpp_freertos {
|
|
|
|
|
|
#define DEFAULT_MAX_WORK_ITEMS 10
|
|
#define DEFAULT_WORK_QUEUE_STACK_SIZE (configMINIMAL_STACK_SIZE * 2)
|
|
#define DEFAULT_WORK_QUEUE_PRIORITY (tskIDLE_PRIORITY + 1)
|
|
|
|
|
|
/**
|
|
* This class encapsulates the idea of a discrete, non-repeating task.
|
|
* Create a WorkItem when there is something you need to do on a different
|
|
* Thread, but doesn't have to happen periodically. This is a great
|
|
* construct for one off fire and forget tasks.
|
|
*
|
|
* This is an abstract base class.
|
|
* To use this, you need to subclass it. All of your WorkItems should
|
|
* be derived from this class. Then implement the virtual Run
|
|
* function. This is a similar design to Java threading.
|
|
*/
|
|
class WorkItem {
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Public API
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////
|
|
public:
|
|
|
|
/**
|
|
* Our constructor.
|
|
*
|
|
* @param freeAfterComplete If you pass in a true, you are
|
|
* requesing the WorkQueue itself to delete this WorkItem after
|
|
* it has run it.
|
|
* @note Only set freeAfterComplete = true if:
|
|
* 1) You dynamically allocated it (i.e. used "new")
|
|
* 2) After you call QueueWork() you promise never to touch
|
|
* this object again.
|
|
*/
|
|
WorkItem(bool freeAfterComplete = false);
|
|
|
|
/**
|
|
* Our destructor.
|
|
*/
|
|
virtual ~WorkItem();
|
|
|
|
/**
|
|
* Allows a client to decide if this WorkItem is marked
|
|
* for automatic deletion.
|
|
*/
|
|
bool FreeAfterRun();
|
|
|
|
/**
|
|
* Implementation of your actual WorkItem function.
|
|
* You must override this function.
|
|
*/
|
|
virtual void Run() = 0;
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Private API
|
|
// The internals of this wrapper class.
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////
|
|
private:
|
|
/**
|
|
* Designates whether this WorkItem should be deleted
|
|
* after the WorkQueue has run it.
|
|
*/
|
|
const bool FreeItemAfterCompleted;
|
|
};
|
|
|
|
|
|
/**
|
|
* This class is the "engine" for WorkItems. Create one or more WorkQueues
|
|
* to accept WorkItems. WorkQueues pull WorkItems off of a FIFO queue and
|
|
* run them sequentially.
|
|
*/
|
|
class WorkQueue {
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Public API
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////
|
|
public:
|
|
/**
|
|
* Constructor to create a named WorkQueue.
|
|
*
|
|
* @throws ThreadCreateException, QueueCreateException,
|
|
* SemaphoreCreateException
|
|
* @param Name Name of the thread internal to the WorkQueue.
|
|
* Only useful for debugging.
|
|
* @param StackDepth Number of "words" allocated for the Thread stack.
|
|
* @param Priority FreeRTOS priority of this Thread.
|
|
* @param MaxWorkItems Maximum number of WorkItems this WorkQueue can hold.
|
|
*/
|
|
WorkQueue( const char * const Name,
|
|
uint16_t StackDepth = DEFAULT_WORK_QUEUE_STACK_SIZE,
|
|
UBaseType_t Priority = DEFAULT_WORK_QUEUE_PRIORITY,
|
|
UBaseType_t MaxWorkItems = DEFAULT_MAX_WORK_ITEMS);
|
|
|
|
/**
|
|
* Constructor to create an unnamed WorkQueue.
|
|
*
|
|
* @throws ThreadCreateException, QueueCreateException,
|
|
* SemaphoreCreateException
|
|
* @param StackDepth Number of "words" allocated for the Thread stack.
|
|
* @param Priority FreeRTOS priority of this Thread.
|
|
* @param MaxWorkItems Maximum number of WorkItems this WorkQueue can hold.
|
|
*/
|
|
WorkQueue( uint16_t StackDepth = DEFAULT_WORK_QUEUE_STACK_SIZE,
|
|
UBaseType_t Priority = DEFAULT_WORK_QUEUE_PRIORITY,
|
|
UBaseType_t MaxWorkItems = DEFAULT_MAX_WORK_ITEMS);
|
|
|
|
#if (INCLUDE_vTaskDelete == 1)
|
|
/**
|
|
* Our destructor.
|
|
*
|
|
* @note Given the multithreaded nature of this class, the dtor
|
|
* may block until the underlying Thread has had a chance to
|
|
* clean up.
|
|
*/
|
|
~WorkQueue();
|
|
#else
|
|
//
|
|
// If we are using C++11 or later, take advantage of the
|
|
// newer features to find bugs.
|
|
//
|
|
#if __cplusplus >= 201103L
|
|
/**
|
|
* If we can't delete a task, it makes no sense to have a
|
|
* destructor.
|
|
*/
|
|
~WorkQueue() = delete;
|
|
#endif
|
|
#endif
|
|
|
|
/**
|
|
* Send a WorkItem off to be executed.
|
|
*
|
|
* @param work Pointer to a WorkItem.
|
|
* @return true if it was queued, false otherwise.
|
|
* @note This function may block if the WorkQueue is presently full.
|
|
*/
|
|
bool QueueWork(WorkItem *work);
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Private API
|
|
// The internals of this class.
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////
|
|
private:
|
|
|
|
/**
|
|
* An internal derived Thread class, in which we do our real work.
|
|
*/
|
|
class CWorkerThread : public Thread {
|
|
|
|
public:
|
|
CWorkerThread( const char * const Name,
|
|
uint16_t StackDepth,
|
|
UBaseType_t Priority,
|
|
WorkQueue *Parent);
|
|
|
|
CWorkerThread( uint16_t StackDepth,
|
|
UBaseType_t Priority,
|
|
WorkQueue *Parent);
|
|
|
|
virtual ~CWorkerThread();
|
|
|
|
protected:
|
|
virtual void Run();
|
|
|
|
private:
|
|
const WorkQueue *ParentWorkQueue;
|
|
};
|
|
|
|
/**
|
|
* Pointer to our WorkerThread.
|
|
*/
|
|
CWorkerThread *WorkerThread;
|
|
|
|
/**
|
|
* Pointer to our work queue itself.
|
|
*/
|
|
Queue *WorkItemQueue;
|
|
|
|
/**
|
|
* Semaphore to support deconstruction without race conditions.
|
|
*/
|
|
BinarySemaphore *ThreadComplete;
|
|
};
|
|
|
|
|
|
}
|
|
#endif
|
|
|
|
|