ME507 Utility Library  0.2.1
Mechatronics Course Support Software for ARM/Arduino/FreeRTOS
Share< DataType > Class Template Reference

Class for data to be shared in a thread-safe manner between tasks. More...

#include <taskshare.h>

Inheritance diagram for Share< DataType >:
Collaboration diagram for Share< DataType >:

Public Member Functions

 Share (const char *p_name=NULL)
 Construct a shared data item. More...
 
void put (DataType new_data)
 Put data into the shared data item. More...
 
void ISR_put (DataType new_data)
 Put data into the shared data item from within an ISR. More...
 
void operator<< (DataType new_data)
 Operator which inserts data into the share. More...
 
void operator>> (DataType put_here)
 Read data from the shared data item. More...
 
void get (DataType &recv_data)
 Read data from the shared data item into a variable. More...
 
DataType get (void)
 Read and return data from the shared data item. More...
 
void ISR_get (DataType &recv_data)
 Read data from the shared data item, from within an ISR. More...
 
DataType ISR_get (void)
 Read and return data from the shared data item, from within an ISR. More...
 
void print_in_list (Print &printer)
 Print the name and type (share) of this data item. More...
 
- Public Member Functions inherited from BaseShare
 BaseShare (const char *p_name=NULL)
 Construct a base shared data item. More...
 

Protected Attributes

QueueHandle_t queue
 A queue is used to hold the data, as it's portable to different CPU's.
 
- Protected Attributes inherited from BaseShare
char name [16]
 The name of the shared item. More...
 
BaseSharep_next
 Pointer to the next item in the linked list of shares. More...
 

Additional Inherited Members

- Static Protected Attributes inherited from BaseShare
static BaseSharep_newest = NULL
 Pointer to the most recently created shared data item. More...
 

Detailed Description

template<class DataType>
class Share< DataType >

Class for data to be shared in a thread-safe manner between tasks.

This class implements an item of data which can be shared between tasks without the risk of data corruption associated with global variables. Unlike queues, shares do not use a buffer for many data items; there is only a one-item buffer in which the most recent value of the data is kept. Shares therefore do not provide the task synchronization or incur the overhead associated with queues.

The data is protected by using critical code sections (see the FreeRTOS documentation of portENTER_CRITICAL() ) so that tasks can't interrupt each other when reading or writing the data is taking place. This prevents data corruption due to thread switching. The C++ template mechanism is used to ensure that only data of the correct type is put into or taken from a shared data item. A TaskShare<DataType> object keeps its own separate copy of the data. This uses some memory, but it is necessary to reliably prevent data corruption; it prevents possible side effects from causing the sender's copy of the data from being inadvertently changed.

Usage

The following bits of code show how to set up and use a share to transfer data of type uint16_t from one hypothetical task called task_A to another called task_B.

In the file which contains setup() we create a shared data object. The constructor of the Share<uint16_t> class is given a name for the share; the name will be shown on system diagnostic printouts. If it is desired to print diagnostic information to a serial monitor, a pointer to an output stream may also be given:

#include "taskshare.h"
...
/// Data from sensor number 3 on the moose's right antler
Share<uint16_t> my_share ("Data_3", &Serial);

If there are any tasks which use this share in other source files, we must re-declare this share with the keyword extern near the top of those files to make it accessible to those task(s). This copy of the share does not need a Doxygen comment:

// Sensor 3 (right antler) data
extern Share<uint16_t> my_share;

In the sending task, data is put into the share:

uint16_t a_data_item = 42; ///< Holds antler data
...
a_data_item = antler3 (); // Get the data
my_share.put (a_data_item); // Put data into share

In the receiving task, data is read from the share:

uint16_t got_data; ///< Holds received data
...
my_share.get (got_data); // Get local copy of shared data

The Easy Way It's also possible to use overloaded stream insertion and extraction operators to interact with the share. These operators contain code which checks if they're running in an interrupt service routine (ISR) or not and use the appropriate method to interact with the internal queue which holds the data, so they're a little slower than put() and get(). Usage is as follows, assuming that the share and local variable have been set up above:

my_share << a_data_item; // In sending task
...
my_share >> got_data; // In receiving task

Constructor & Destructor Documentation

◆ Share()

template<class DataType >
Share< DataType >::Share ( const char *  p_name = NULL)
inline

Construct a shared data item.

This constructor for a shared data item creates a queue in which to hold one item of data. Note that the data is not initialized.

Parameters
p_nameA name to be shown in the list of task shares (default NULL)

Member Function Documentation

◆ get() [1/2]

template<class DataType >
void Share< DataType >::get ( DataType &  recv_data)
inline

Read data from the shared data item into a variable.

This method is used to read data from the shared data item with protection to ensure that the data cannot be corrupted by a task switch. The shared data is copied into the variable which is given as this method's parameter, replacing the previous contents of that variable.

Parameters
recv_dataA reference to the variable in which to put received data

◆ get() [2/2]

template<class DataType >
DataType Share< DataType >::get ( void  )
inline

Read and return data from the shared data item.

This method is used to read data from the shared data item with protection to ensure that the data cannot be corrupted by a task switch. A copy of the shared data is returned.

Returns
A copy of the data found in the queue, or a default value of the given data type if no data was found in the queue

◆ ISR_get() [1/2]

template<class DataType >
void Share< DataType >::ISR_get ( DataType &  recv_data)
inline

Read data from the shared data item, from within an ISR.

This method is used to enable code within an ISR to read data from the shared data item. It must only be called from within an interrupt service routine, not a normal task.

Parameters
recv_dataA reference to the variable in which to put received data

◆ ISR_get() [2/2]

template<class DataType >
DataType Share< DataType >::ISR_get ( void  )
inline

Read and return data from the shared data item, from within an ISR.

This method is used to enable code within an ISR to read data from the shared data item. It must only be called from within an interrupt service routine, not a normal task.

Returns
A copy of the data found in the queue, or a default value of the given data type if no data was found in the queue

◆ ISR_put()

template<class DataType >
void Share< DataType >::ISR_put ( DataType  new_data)
inline

Put data into the shared data item from within an ISR.

This method writes data from an ISR into the shared data item. It must only be called from within an interrupt service routine, not a normal task.

Parameters
new_dataThe data to be written into the shared data item

◆ operator<<()

template<class DataType >
void Share< DataType >::operator<< ( DataType  new_data)
inline

Operator which inserts data into the share.

This convenient operator puts data into the share, protecting the data from corruption by thread switching. It checks if the processor is currently in an interupt service routine (ISR); if so, it calls ISR specific functions to prevent corruption, so this function may be used within an ISR or outside one. It runs a little more slowly than the put() method.

Parameters
new_dataThe data which is to be put into the share

◆ operator>>()

template<class DataType >
void Share< DataType >::operator>> ( DataType  put_here)
inline

Read data from the shared data item.

This method is used to read data from the shared data item with critical section protection to ensure that the data cannot be corrupted by a task switch. The shared data is copied into the variable which is given as this method's parameter, replacing the previous contents. This method checks if the processor is currently in an interupt service routine (ISR) and if so, it calls ISR specific functions to prevent corruption, so this function may be used within an ISR or outside one. It runs a little more slowly than the get() method because of the run-time ISR check.

Parameters
put_hereA reference to the variable in which to put received data

◆ print_in_list()

template<class DataType >
void Share< DataType >::print_in_list ( Print &  printer)
virtual

Print the name and type (share) of this data item.

This method prints the share's name and a word indicating that it is a shared data item, as opposed to a queue, formatted to match similar printouts from other task shares such as queues. After printing this share's information, it looks in the linked list of shares for the next one and asks it to print its information too.

Parameters
printerReference to a serial device on which to print the status

Implements BaseShare.

◆ put()

template<class DataType >
void Share< DataType >::put ( DataType  new_data)
inline

Put data into the shared data item.

This method is used to write data into the shared data item.

Parameters
new_dataThe data which is to be written

The documentation for this class was generated from the following file:
taskshare.h
Data which can be shared between tasks in a thread-safe manner.
Share
Class for data to be shared in a thread-safe manner between tasks.
Definition: taskshare.h:119
Share::put
void put(DataType new_data)
Put data into the shared data item.
Definition: taskshare.h:142