task_share module

! @file task_share.py This file contains classes which allow tasks to share data without the risk of data corruption by interrupts.

@author JR Ridgely @date 2017-Jan-01 JRR Approximate date of creation of file @date 2021-Dec-18 JRR Docstrings changed to work without DoxyPyPy @copyright This program is copyright (c) 2017-2021 by JR Ridgely and released

under the GNU Public License, version 3.0.

It is intended for educational use only, but its use is not limited thereto. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

class task_share.BaseShare(type_code, thread_protect=True, name=None)

Bases: object

! Base class for queues and shares which exchange data between tasks.

One should never create an object from this class; it doesn’t do anything useful. It exists to implement things which are common between its child classes @c Queue and @c Share.

class task_share.Queue(type_code, size, thread_protect=False, overwrite=False, name=None)

Bases: BaseShare

! A queue which is used to transfer data from one task to another.

If parameter ‘thread_protect’ is @c True when a queue is created, transfers of data will be protected from corruption in the case that one task might interrupt another due to use in a pre-emptive multithreading environment or due to one task being run as an interrupt service routine.

An example of the creation and use of a queue is as follows:

@code import task_share

# This queue holds unsigned short (16-bit) integers my_queue = task_share.Queue (‘H’, 100, name=”My Queue”)

# Somewhere in one task, put data into the queue my_queue.put (some_data)

# In another task, read data from the queue something = my_queue.get () @endcode

any()

! Check if there are any items in the queue.

Returns @c True if there are any items in the queue and @c False if the queue is empty. @return @c True if items are in the queue, @c False if not

clear()

! Remove all contents from the queue.

empty()

! Check if the queue is empty.

Returns @c True if there are no items in the queue and @c False if there are any items therein. @return @c True if queue is empty, @c False if it’s not empty

full()

! Check if the queue is full.

This method returns @c True if the queue is already full and there is no room for more data without overwriting existing data. @return @c True if the queue is full

get(in_ISR=False)

! Read an item from the queue.

If there isn’t anything in there, wait (blocking the calling process) until something becomes available. If non-blocking reads are needed, one should call @c any() to check for items before attempting to read from the queue. This is usually done in a low priority task: @code | def some_task (): | # Setup | while True: | if my_queue.any (): | something = my_queue.get () | do_something_with (something) | # More loop stuff | yield 0 @endcode @param in_ISR Set this to @c True if calling from within an ISR

num_in()

! Check how many items are in the queue.

This method returns the number of items which are currently in the queue. @return The number of items in the queue

put(item, in_ISR=False)

! Put an item into the queue.

If there isn’t room for the item, wait (blocking the calling process) until room becomes available, unless the @c overwrite constructor parameter was set to @c True to allow old data to be clobbered. If non-blocking behavior without overwriting is needed, one should call @c full() to ensure that the queue is not full before putting data into it: @code | def some_task (): | # Setup | while True: | if not my_queue.full (): | my_queue.put (create_something_to_put ()) | yield 0 @endcode @param item The item to be placed into the queue @param in_ISR Set this to @c True if calling from within an ISR

ser_num = 0
class task_share.Share(type_code, thread_protect=True, name=None)

Bases: BaseShare

! An item which holds data to be shared between tasks. This class implements a shared data item which can be protected against data corruption by pre-emptive multithreading. Multithreading which can corrupt shared data includes the use of ordinary interrupts as well as the use of pre-emptive multithreading such as by a Real-Time Operating System (RTOS).

An example of the creation and use of a share is as follows: @code import task_share

# This share holds a signed short (16-bit) integer my_share = task_share.Queue (‘h’, name=”My Share”)

# Somewhere in one task, put data into the share my_share.put (some_data)

# In another task, read data from the share something = my_share.get () @endcode

get(in_ISR=False)

! Read an item of data from the share.

If thread protection is enabled, interrupts are disabled during the time that the data is being read so as to prevent data corruption by changes in the data as it is being read. @param in_ISR Set this to True if calling from within an ISR

put(data, in_ISR=False)

! Write an item of data into the share.

This method puts data into the share; any old data is overwritten. This code disables interrupts during the writing so as to prevent data corrupting by an interrupt service routine which might access the same data. @param data The data to be put into this share @param in_ISR Set this to True if calling from within an ISR

ser_num = 0
task_share.show_all()

! Create a string holding a diagnostic printout showing the status of each queue and share in the system. @return A string containing information about each queue and share