Message queue to synchronize and share information between threads. It is a template class, so it can hold elements of different types.

Dependents:   Nucleo_modbus_protocol_test F103RB_tcp_rtu_modbus_copy_v1_0

MessageQueue.h

Committer:
gabrielrivas
Date:
2015-01-19
Revision:
2:5e151e3834db
Parent:
1:c5b6cfae502d

File content as of revision 2:5e151e3834db:

/** Message Queue Library
 * Copyright (c) 2015 Gabriel Rivas
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#ifndef _MESSAGE_QUEUE_H_
#define _MESSAGE_QUEUE_H_

#include "mbed.h"
#include "rtos.h"
#include <queue>

#define MESSAGE_QUEUE_MAX_SIZE (256)

/**
 * Message queue class  that is a wrapper for the STL queue container intended to 
 * be used to share data among threads using the mbed-rtos so the write and read access 
 * to the queue is protected from simultaneous access.
 */
template <class T>
class MessageQueue
{
public:
    /** 
     *  Create a message queue object.
     *  @param size The size for the queue.
     */
    MessageQueue(uint32_t size);

public:
    /** 
     *  Write a data element into the back of the queue.
     *  @param data Value or object to be writen into the queue.
     */
    void write(T data);
    
    /**
     * Reads a element from the queue.
     * @return The element in the front of the queue.
     */    
    T read();
    
    /**
     * Tells if a number of elements written has reached the size of the queue.
     *
     * @return The full status flag.
     */
    bool isFull();
    
    /**
     * Tells if no data elements can be read from the queue.
     * @return The empty status flag.
     */
    bool isEmpty();
    
    /**
     * Get the number of elements written into the queue.
     * @return Index of the last element written in the queue.
     */    
    uint32_t getWriteIndex();
    
     /**
      * Get the number of elements read from the queue.
      * @return Index of the last element read from the queue.
      */      
    uint32_t getReadIndex();
    
     /**
      * Removes all the elements in the queue and reset all its internal counters and status.
      */     
    void reset();

private:
    /** Internal queue that holds data elements.
     */    
    std::queue<T> m_queue;
    
    /** Mutex to protect the queue from simultaneous access.
     */ 
    Mutex m_mutex;
    
    /** Number of elements allowed to be written into the queue.
     */ 
    uint32_t m_size;
    
    /** Internal full status flag.
     */ 
    bool m_full;
    
    /** Internal empty status flag.
     */ 
    bool m_empty;
    
    /** Internal index for elements read from the queue.
     */ 
    uint32_t m_readIndex;
    
    /** Internal index for elements written into the queue.
     */ 
    uint32_t m_writeIndex;

};


template <class T>
MessageQueue<T>::MessageQueue(uint32_t size)
{
//    assert(size < MESSAGE_QUEUE_MAX_SIZE);
    m_size = size;
    m_full = false;
    m_empty = true;
    m_readIndex = 0;
    m_writeIndex = 0;
}

template <class T>
void MessageQueue<T>::write(T data)
{
    m_mutex.lock();

    if (m_writeIndex == m_size) {
        m_full = true;
    } else {
        m_queue.push(data);
        m_empty = false;
        m_writeIndex++;
    }
    m_mutex.unlock();
}

template <class T>
T MessageQueue<T>::read()
{
    T data = 0;

    m_mutex.lock();

    if (m_readIndex == m_writeIndex) {
        m_empty = true;
    } else {
        data = m_queue.front();
        m_full = false;
        m_queue.pop();
        m_readIndex++;
    }

    m_mutex.unlock();

    return data;
}

template <class T>
bool MessageQueue<T>::isFull()
{
    return m_full;
}

template <class T>
bool MessageQueue<T>::isEmpty()
{
    return m_empty;
}

template <class T>
uint32_t MessageQueue<T>::getWriteIndex()
{
    return m_writeIndex;
}

template <class T>
uint32_t MessageQueue<T>::getReadIndex()
{
    return m_readIndex;
}

template <class T>
void MessageQueue<T>::reset()
{
    m_mutex.lock();

    while(!isEmpty()) read();
    m_full = false;
    m_empty = true;
    m_readIndex = 0;
    m_writeIndex = 0;

    m_mutex.unlock();
}

#endif