Embedded Artistry Framework
Embedded Systems C++ Framework
Classes
Function Queue

Queues for storing function objects. More...

Collaboration diagram for Function Queue:

Classes

class  embutil::FuncOp
 Base Class for storing functions. More...
 
class  embutil::FuncOpBound< TFuncOp >
 Represents a bound function object. More...
 
class  embutil::StaticFunctionQueue< TQueueElements, TLargestSize, TFunc >
 Static-memory function queue that accepts functors of multiple sizes. More...
 

Detailed Description

Queues for storing function objects.

Users should utilize the embutil::StaticFunctionQueue or embutil::DynamicFunctionQueue template specializations. Other type definitions are used to make the queue work properly.


Class Documentation

◆ embutil::FuncOp

class embutil::FuncOp

Base Class for storing functions.

This base class represents a function operation stored in the function queue.

In order to support functors of different sizes in a single statically-allocated function queue, we need to provide a common interface for each size.

A functor is stored in multiple blocks of FuncOp objects. The derived class, FuncOpBound, overloads exec() to call the bound operation.

Inheritance diagram for embutil::FuncOp:
Inheritance graph

Public Member Functions

virtual ~FuncOp ()
 Default destructor. More...
 
virtual void exec ()
 Invoke the function. More...
 
void operator() ()
 operator() invokes the function. More...
 

Constructor & Destructor Documentation

◆ ~FuncOp()

embutil::FuncOp::~FuncOp ( )
virtualdefault

Default destructor.

Member Function Documentation

◆ exec()

virtual void embutil::FuncOp::exec ( )
inlinevirtual

Invoke the function.

Base class invocation does nothing. Derived FuncOpBound classes overload this for the actual execution.

Reimplemented in embutil::FuncOpBound< TFuncOp >.

Referenced by operator()().

◆ operator()()

void embutil::FuncOp::operator() ( )
inline

operator() invokes the function.

References exec().

◆ embutil::FuncOpBound

class embutil::FuncOpBound

template<typename TFuncOp>
class embutil::FuncOpBound< TFuncOp >

Represents a bound function object.

A bound function object takes in an operation of any type and stores it as a private member. Since our queue is intended to support objects of different sizes, we decay to the FuncOp base class interface for managing the queue.

Template Parameters
TFuncOpThe function prototype to store in the bound object.
Inheritance diagram for embutil::FuncOpBound< TFuncOp >:
Inheritance graph

Public Member Functions

 FuncOpBound (const TFuncOp &op)
 Construct the FuncOpBound object with an operation. More...
 
 FuncOpBound (TFuncOp &&op)
 Construct the FuncOpBound object with an operation. More...
 
 ~FuncOpBound () final=default
 Default destructor. More...
 
void exec () final
 Invoke the bound operation. More...
 
void operator() ()
 operator() invokes the function. More...
 

Private Attributes

TFuncOp op_
 The bound functor. More...
 

Constructor & Destructor Documentation

◆ FuncOpBound() [1/2]

template<typename TFuncOp >
embutil::FuncOpBound< TFuncOp >::FuncOpBound ( const TFuncOp &  op)
inlineexplicit

Construct the FuncOpBound object with an operation.

Parameters
opThe operation to bind. Can be any functor.

◆ FuncOpBound() [2/2]

template<typename TFuncOp >
embutil::FuncOpBound< TFuncOp >::FuncOpBound ( TFuncOp &&  op)
inlineexplicit

Construct the FuncOpBound object with an operation.

Parameters
opThe operation to bind. Can be any functor.

◆ ~FuncOpBound()

template<typename TFuncOp >
embutil::FuncOpBound< TFuncOp >::~FuncOpBound ( )
finaldefault

Default destructor.

Member Function Documentation

◆ exec()

template<typename TFuncOp >
void embutil::FuncOpBound< TFuncOp >::exec ( )
inlinefinalvirtual

Invoke the bound operation.

Reimplemented from embutil::FuncOp.

References embutil::FuncOpBound< TFuncOp >::op_.

◆ operator()()

void embutil::FuncOp::operator() ( )
inlineinherited

operator() invokes the function.

References embutil::FuncOp::exec().

Member Data Documentation

◆ op_

template<typename TFuncOp >
TFuncOp embutil::FuncOpBound< TFuncOp >::op_
private

The bound functor.

Referenced by embutil::FuncOpBound< TFuncOp >::exec().

◆ embutil::StaticFunctionQueue

class embutil::StaticFunctionQueue

template<const size_t TQueueElements, const size_t TLargestSize = DefaultStaticQueueLargestSize, typename TFunc = stdext::inplace_function<void()>>
class embutil::StaticFunctionQueue< TQueueElements, TLargestSize, TFunc >

Static-memory function queue that accepts functors of multiple sizes.

This class stores function objects of varying sizes in a single queue. If you were to manage a queue of stdext::inplace_function, you would have to increase the size of each element to accommodate the largest possible size. This is inefficient. Instead, we support varying sizes by using more complicated memory management.

If you want a dynamic memory alternative, use std::queue<std::function>.

Using a Function Queue

This class is intended to be used with functions of type void(void). You can store functions with arguments in the queue, but you must use a std::bind expression to reduce the arguments.

Functors can be pushed to the queue using push(). This API creates a FuncOpBound object and stores the element for future processing.

Note
After the function is stored in the queue, it cannot be recreated explicitly. It is only accessible as a pointer to a FuncOp object.

Elements can be removed from the queue using front(). A std::unique_ptr is returned, ensuring that the memory will be returned to the function queue's pool once the caller is done with the function. This means that front() can only be called once per queue element - there is no peeking. pop() can then be called to remove the element from the front of the queue.

Invoking the function after pop() ensures two things:

  1. The element is removed, enabling another thread to pop off the next function immediately.
  2. The queue is not blocked while the function is executing.
Note
Elements returned through front() cannot be directly invoked with operator(). Instead, the exec() API must be used.

Here is an example flow for removing elements from the function queue:

auto op = std::move(q_.front());
q_.pop();
op->exec();

If a single thread is managing the queue, popAndExec() can be used to remove the function from the queue and execute it.

Template Parameters
TFuncThe functor storage type, such as std::function or stdext::inplace_function.
TQueueElementsThe number of elements to store in the queue. TQueueElements must be > 0.
TLargestSizeThe size of the largest expected allocation, in bytes.
Note
The total memory pool size in bytes is (TQueueElements * TLargestSize).

Public Member Functions

 StaticFunctionQueue ()=default
 Default constructor. More...
 
 ~StaticFunctionQueue ()=default
 Default destructor. More...
 
 StaticFunctionQueue (const StaticFunctionQueue &)=delete
 Deleted copy constructor. More...
 
const StaticFunctionQueueoperator= (const StaticFunctionQueue &)=delete
 Deleted copy assignment operator. More...
 
 StaticFunctionQueue (StaticFunctionQueue &&)=delete
 Deleted move constructor. More...
 
StaticFunctionQueueoperator= (StaticFunctionQueue &&)=delete
 Deleted move assignment operator. More...
 
template<typename TFuncOp >
void push (const TFuncOp &op) noexcept
 Add a function to the queue. More...
 
template<typename TFuncOp >
void push (TFuncOp &&op) noexcept
 
void popAndExec () noexcept
 Remove the next functor from the front of the queue and execute it. More...
 
auto front () noexcept
 Get a copy of the functor at the front of the queue. More...
 
void pop () noexcept
 Remove the element at the front of the queue. More...
 
bool empty () const noexcept
 Check if the queue is empty. More...
 
size_t size () const noexcept
 Check the current number of elements in the queue. More...
 
constexpr size_t capacity () const noexcept
 Get the capacity in elements. More...
 
constexpr size_t capacity_bytes () const noexcept
 Get the total memory consumed by this queue in bytes. More...
 

Private Types

using UniqueElementPtr_t = typename std::unique_ptr< FuncOp, stdext::inplace_function< void(FuncOp *), 3 *sizeof(void *)> >
 Convenience alias for the unique pointer to the element We return functors to the client as a std::unique_ptr<FuncOp>. More...
 
using ElementPtr_t = FuncOp *
 Alias for our element. More...
 
using FuncOpStorage_t = etl::queue< ElementPtr_t, TQueueElements >
 Alias for the element storage queue. More...
 

Private Member Functions

void deleter (FuncOp *ptr)
 Return FuncOp objects to the memory pool. More...
 

Private Attributes

etl::generic_pool< TLargestSize, etl::largest< FuncOp, TFunc >::alignment, TQueueElements > mem_pool_
 Memory storage for FuncElement types We utilize a memory pool to allocate FuncOpBound objects for storage. More...
 
FuncOpStorage_t queue_
 Queue which stores function objects. More...
 

Member Typedef Documentation

◆ ElementPtr_t

template<const size_t TQueueElements, const size_t TLargestSize = DefaultStaticQueueLargestSize, typename TFunc = stdext::inplace_function<void()>>
using embutil::StaticFunctionQueue< TQueueElements, TLargestSize, TFunc >::ElementPtr_t = FuncOp*
private

Alias for our element.

We store pointers to FuncOp objects.

◆ FuncOpStorage_t

template<const size_t TQueueElements, const size_t TLargestSize = DefaultStaticQueueLargestSize, typename TFunc = stdext::inplace_function<void()>>
using embutil::StaticFunctionQueue< TQueueElements, TLargestSize, TFunc >::FuncOpStorage_t = etl::queue<ElementPtr_t, TQueueElements>
private

Alias for the element storage queue.

◆ UniqueElementPtr_t

template<const size_t TQueueElements, const size_t TLargestSize = DefaultStaticQueueLargestSize, typename TFunc = stdext::inplace_function<void()>>
using embutil::StaticFunctionQueue< TQueueElements, TLargestSize, TFunc >::UniqueElementPtr_t = typename std::unique_ptr<FuncOp, stdext::inplace_function<void(FuncOp*), 3 * sizeof(void*)> >
private

Convenience alias for the unique pointer to the element We return functors to the client as a std::unique_ptr<FuncOp>.

Memory is allocated from mem_pool_, so we use a deleter to ensure memory is recovered.

Constructor & Destructor Documentation

◆ StaticFunctionQueue() [1/3]

template<const size_t TQueueElements, const size_t TLargestSize = DefaultStaticQueueLargestSize, typename TFunc = stdext::inplace_function<void()>>
embutil::StaticFunctionQueue< TQueueElements, TLargestSize, TFunc >::StaticFunctionQueue ( )
default

Default constructor.

◆ ~StaticFunctionQueue()

template<const size_t TQueueElements, const size_t TLargestSize = DefaultStaticQueueLargestSize, typename TFunc = stdext::inplace_function<void()>>
embutil::StaticFunctionQueue< TQueueElements, TLargestSize, TFunc >::~StaticFunctionQueue ( )
default

Default destructor.

◆ StaticFunctionQueue() [2/3]

template<const size_t TQueueElements, const size_t TLargestSize = DefaultStaticQueueLargestSize, typename TFunc = stdext::inplace_function<void()>>
embutil::StaticFunctionQueue< TQueueElements, TLargestSize, TFunc >::StaticFunctionQueue ( const StaticFunctionQueue< TQueueElements, TLargestSize, TFunc > &  )
delete

Deleted copy constructor.

◆ StaticFunctionQueue() [3/3]

template<const size_t TQueueElements, const size_t TLargestSize = DefaultStaticQueueLargestSize, typename TFunc = stdext::inplace_function<void()>>
embutil::StaticFunctionQueue< TQueueElements, TLargestSize, TFunc >::StaticFunctionQueue ( StaticFunctionQueue< TQueueElements, TLargestSize, TFunc > &&  )
delete

Deleted move constructor.

Member Function Documentation

◆ capacity()

template<const size_t TQueueElements, const size_t TLargestSize = DefaultStaticQueueLargestSize, typename TFunc = stdext::inplace_function<void()>>
constexpr size_t embutil::StaticFunctionQueue< TQueueElements, TLargestSize, TFunc >::capacity ( ) const
inlinenoexcept

Get the capacity in elements.

Returns
the number of elements that the queue can support.

References embutil::StaticFunctionQueue< TQueueElements, TLargestSize, TFunc >::queue_.

◆ capacity_bytes()

template<const size_t TQueueElements, const size_t TLargestSize = DefaultStaticQueueLargestSize, typename TFunc = stdext::inplace_function<void()>>
constexpr size_t embutil::StaticFunctionQueue< TQueueElements, TLargestSize, TFunc >::capacity_bytes ( ) const
inlinenoexcept

Get the total memory consumed by this queue in bytes.

Returns
the size of this function queue in bytes.

◆ deleter()

template<const size_t TQueueElements, const size_t TLargestSize = DefaultStaticQueueLargestSize, typename TFunc = stdext::inplace_function<void()>>
void embutil::StaticFunctionQueue< TQueueElements, TLargestSize, TFunc >::deleter ( FuncOp ptr)
inlineprivate

Return FuncOp objects to the memory pool.

This deleter is used by with the std::unique_ptr that is used to store the function elements. When the FuncOp object goes out of scope, its memory is automatically returned to the pool.

References embutil::StaticFunctionQueue< TQueueElements, TLargestSize, TFunc >::mem_pool_.

Referenced by embutil::StaticFunctionQueue< TQueueElements, TLargestSize, TFunc >::front(), and embutil::StaticFunctionQueue< TQueueElements, TLargestSize, TFunc >::popAndExec().

◆ empty()

template<const size_t TQueueElements, const size_t TLargestSize = DefaultStaticQueueLargestSize, typename TFunc = stdext::inplace_function<void()>>
bool embutil::StaticFunctionQueue< TQueueElements, TLargestSize, TFunc >::empty ( ) const
inlinenoexcept

Check if the queue is empty.

Returns
true if the queue is empty, false otherwise.

References embutil::StaticFunctionQueue< TQueueElements, TLargestSize, TFunc >::size().

◆ front()

template<const size_t TQueueElements, const size_t TLargestSize = DefaultStaticQueueLargestSize, typename TFunc = stdext::inplace_function<void()>>
auto embutil::StaticFunctionQueue< TQueueElements, TLargestSize, TFunc >::front ( )
inlinenoexcept

Get a copy of the functor at the front of the queue.

For efficient queue usage, clients will want to get the element from the front of the queue, call pop() to remove it from the queue, and then execute the function. This flow will ensure that the queue is not locked while the function is running (which happens with popAndExec()).

Note
Because we have a std::unique_ptr, front() can only be called once per functor.
Precondition
front() has not been previously called for this element.
Returns
a UniqueElementPtr_t to the functor at the front of the queue. Once the UniqueElementPtr_t goes out of scope, the function queue will recover the memory automatically.

References embutil::StaticFunctionQueue< TQueueElements, TLargestSize, TFunc >::deleter(), and embutil::StaticFunctionQueue< TQueueElements, TLargestSize, TFunc >::queue_.

◆ operator=() [1/2]

template<const size_t TQueueElements, const size_t TLargestSize = DefaultStaticQueueLargestSize, typename TFunc = stdext::inplace_function<void()>>
const StaticFunctionQueue& embutil::StaticFunctionQueue< TQueueElements, TLargestSize, TFunc >::operator= ( const StaticFunctionQueue< TQueueElements, TLargestSize, TFunc > &  )
delete

Deleted copy assignment operator.

◆ operator=() [2/2]

template<const size_t TQueueElements, const size_t TLargestSize = DefaultStaticQueueLargestSize, typename TFunc = stdext::inplace_function<void()>>
StaticFunctionQueue& embutil::StaticFunctionQueue< TQueueElements, TLargestSize, TFunc >::operator= ( StaticFunctionQueue< TQueueElements, TLargestSize, TFunc > &&  )
delete

Deleted move assignment operator.

◆ pop()

template<const size_t TQueueElements, const size_t TLargestSize = DefaultStaticQueueLargestSize, typename TFunc = stdext::inplace_function<void()>>
void embutil::StaticFunctionQueue< TQueueElements, TLargestSize, TFunc >::pop ( )
inlinenoexcept

Remove the element at the front of the queue.

Precondition
There is an element in the queue.
Postcondition
The element has been removed from the queue.

References embutil::StaticFunctionQueue< TQueueElements, TLargestSize, TFunc >::queue_.

◆ popAndExec()

template<const size_t TQueueElements, const size_t TLargestSize = DefaultStaticQueueLargestSize, typename TFunc = stdext::inplace_function<void()>>
void embutil::StaticFunctionQueue< TQueueElements, TLargestSize, TFunc >::popAndExec ( )
inlinenoexcept

◆ push() [1/2]

template<const size_t TQueueElements, const size_t TLargestSize = DefaultStaticQueueLargestSize, typename TFunc = stdext::inplace_function<void()>>
template<typename TFuncOp >
void embutil::StaticFunctionQueue< TQueueElements, TLargestSize, TFunc >::push ( const TFuncOp &  op)
inlinenoexcept

Add a function to the queue.

This function is noexcept because we want our program to abort if we are out of memory. Depending on the underlying queue type, it is certainly likely that there is throw support.

Template Parameters
TFuncOpThe type of the functor to add to the queue. This template parameter is automatically deduced by the compiler.
Parameters
opThe functor object to add to the queue.

References assert, embutil::StaticFunctionQueue< TQueueElements, TLargestSize, TFunc >::mem_pool_, and embutil::StaticFunctionQueue< TQueueElements, TLargestSize, TFunc >::queue_.

◆ push() [2/2]

template<const size_t TQueueElements, const size_t TLargestSize = DefaultStaticQueueLargestSize, typename TFunc = stdext::inplace_function<void()>>
template<typename TFuncOp >
void embutil::StaticFunctionQueue< TQueueElements, TLargestSize, TFunc >::push ( TFuncOp &&  op)
inlinenoexcept

This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.

References assert, embutil::StaticFunctionQueue< TQueueElements, TLargestSize, TFunc >::mem_pool_, and embutil::StaticFunctionQueue< TQueueElements, TLargestSize, TFunc >::queue_.

◆ size()

template<const size_t TQueueElements, const size_t TLargestSize = DefaultStaticQueueLargestSize, typename TFunc = stdext::inplace_function<void()>>
size_t embutil::StaticFunctionQueue< TQueueElements, TLargestSize, TFunc >::size ( ) const
inlinenoexcept

Check the current number of elements in the queue.

Returns
the number of elements currently stored in the queue.

References embutil::StaticFunctionQueue< TQueueElements, TLargestSize, TFunc >::queue_.

Referenced by embutil::StaticFunctionQueue< TQueueElements, TLargestSize, TFunc >::empty().

Member Data Documentation

◆ mem_pool_

template<const size_t TQueueElements, const size_t TLargestSize = DefaultStaticQueueLargestSize, typename TFunc = stdext::inplace_function<void()>>
etl::generic_pool<TLargestSize, etl::largest<FuncOp, TFunc>::alignment, TQueueElements> embutil::StaticFunctionQueue< TQueueElements, TLargestSize, TFunc >::mem_pool_
private

Memory storage for FuncElement types We utilize a memory pool to allocate FuncOpBound objects for storage.

Referenced by embutil::StaticFunctionQueue< TQueueElements, TLargestSize, TFunc >::deleter(), and embutil::StaticFunctionQueue< TQueueElements, TLargestSize, TFunc >::push().

◆ queue_