#ifndef __QUEUE_H__
#define __QUEUE_H__ #include <stdint.h>
#include <stdlib.h>
#include <string.h> /*
* Queues can have more than one producer but only one consumer.
* This means that more than one task or interrupt handler is allowed to store
* new data in the queue but only one task is allowed toget data from the queue.
*
* Queues accept messages of various size. When putting a message into a queue,
* the message size is passed as a parameter.
*
* Retrieving a message from the queue does not copy the message, but returns
* a pointer to the message and its size. Thisenhances performance because the
* data is copied only once, when the message is written into the queue.
*
* The retrieving function has to delete every message after processing it.
* A new message can only be retrieved from the queue when the previous message
* was deleted from the queue.
*
* |---------------------- size -------------------------|
* | |------------ msgCnt ---------------| |
* [ .... ] [ size : message ] [ size : message ] [ .... ]
* | | |
* |pData |offsetFirst |offsetLast
*
*/
typedef struct TAG_QUEUE
{
uint8_t * Memory;
uint32_t Capacity;
uint32_t MessageCount;
uint32_t ReadIndex;
uint32_t WriteIndex;
uint32_t IsUsing;
uint32_t InProgressCount;
} QUEUE; // Creates and initializes a message queue.
QUEUE * Q_Create( uint32_t Capacity ); // Deletes a specific queue.
void Q_Delete( QUEUE * Queue ); // Initializes a message queue.
void Q_Init( QUEUE * Queue, uint8_t * Memory, uint32_t Capacity ); // Deletes the last retrieved message in a queue.
void Q_Purge( QUEUE * Queue ); // Deletes all message in a queue.
void Q_Clear( QUEUE * Queue ); // Returns the number of messages currently in a queue
uint32_t Q_GetCount( QUEUE * Queue ); // Returns the first message size
uint32_t Q_GetSize( QUEUE * Queue ); // Delivers information whether the queue is actually in use.
// A queue must not be cleared or deleted when it is in use.
uint32_t Q_IsUsing( QUEUE * Queue ); // Stores a new message of given size in a queue.
uint32_t Q_Wirte( QUEUE * Queue, void * Message, uint32_t Size ); // Retrieves a message from a queue
uint32_t Q_Read( QUEUE * Queue, void ** Message ); #endif /* __QUEUE_H__ */
#include "queue.h"

#include "cmsis_os.h"
#include "macro_misc.h" // Creates and initializes a message Queue.
QUEUE * Q_Create( uint32_t Capacity )
{
uint32_t Size = ALIGN_UP( sizeof(QUEUE), ) + ALIGN_UP( Capacity, );
QUEUE *Queue = (QUEUE *) osMalloc( Size, osWaitForever );
if ( Queue == NULL )
return NULL; uint8_t * Memory = //
(uint8_t *) ( ( (uint32_t) ( Queue ) ) + ALIGN_UP( sizeof(QUEUE), ) ); Q_Init( Queue, Memory, ALIGN_UP( Capacity, ) ); return Queue;
} // Deletes a specific Queue.
// A Queue must not be cleared or deleted when it is in use.
void Q_Delete( QUEUE * Queue )
{
if ( Queue->IsUsing == )
osFree( Queue );
} // Deletes all messages in a Queue.
// A Queue must not be cleared or deleted when it is in use.
void Q_Clear( QUEUE * Queue )
{
if ( Queue->IsUsing == )
Queue->MessageCount = ;
} // Initializes a message Queue.
void Q_Init( QUEUE * Queue, uint8_t * Memory, uint32_t Capacity )
{
int32_t Delta = (uint32_t) Memory & ;
if ( Delta )
{
Delta -= ;
Capacity += Delta;
Memory -= Delta;
}
memset( Queue, , sizeof(QUEUE) );
Queue->Capacity = Capacity;
Queue->Memory = Memory;
} // Returns the number of messages currently in a Queue
uint32_t Q_GetCount( QUEUE * Queue )
{
return Queue->MessageCount - Queue->InProgressCount;
} // Returns the first message size
uint32_t Q_GetSize( QUEUE * Queue )
{
uint32_t MessageSize = ;
if ( Queue->MessageCount )
MessageSize = *(uint32_t *) ( &Queue->Memory[ Queue->ReadIndex ] );
return MessageSize;
} // Delivers information whether the Queue is actually in use.
// A Queue must not be cleared or deleted when it is in use.
uint32_t Q_IsUsing( QUEUE * Queue )
{
return Queue->IsUsing;
} // Stores a new message of given size in a Queue.
// 0 : Queue could not be stored (Queue is full).
// 1 : Success; message stored.
uint32_t Q_Write( QUEUE * Queue, void * Message, uint32_t Size )
{
uint32_t ReadIndexVal;
uint32_t WriteIndexPending;
uint32_t WriteIndexVal;
uint32_t MessageSize = + ALIGN_UP( Size, );
int32_t * Memory = (int32_t *) Queue->Memory; uint32_t Value = osDisableInterrupt( ); if ( Queue->MessageCount == )
{
// read next message from head of memory
Queue->ReadIndex = ; // Queue could not be stored (memory is full).
WriteIndexVal = -; if ( Queue->Capacity >= MessageSize )
WriteIndexVal = ;
}
else
{
Memory = (int32_t *) Queue->Memory;
WriteIndexPending = Queue->WriteIndex;
int32_t SizePending = Memory[ WriteIndexPending ]; if ( SizePending < )
{
// other task is writting ... but it is preemptived by our task
// WriteIndexPending has been updated
// [ Last Queue ] [ --- Other Queue --- ] [ Our Mesage ]
// | WriteIndexPending
SizePending = -SizePending;
}
else
{
// [ Last Queue ] [ Our Mesage ]
// | WriteIndexPending
} // where our task will write ...
WriteIndexVal = WriteIndexPending + + ALIGN_UP( SizePending, );
ReadIndexVal = Queue->ReadIndex;
if ( ReadIndexVal >= WriteIndexVal )
{
// [ Our Mesage ] [ Last Queue ]
// |<------------>|ReadIndexVal
// |WriteIndexVal
if ( ReadIndexVal - WriteIndexVal < MessageSize )
WriteIndexVal = -;
}
else
{
// [ Our Mesage ] [ Available Space ]
// |WriteIndexVal |Capacity
// |<------------------------------>|
uint32_t sizeAvailableTail = Queue->Capacity - WriteIndexVal;
if ( sizeAvailableTail < MessageSize )
{
// try to write to head of memory
// [ Our Mesage ] [ Last Queue ]
// |<------------>|ReadIndexVal
// |0
if ( ReadIndexVal < MessageSize )
WriteIndexVal = -;
else if ( sizeAvailableTail > )
{
// can not read message from tail of memory
// Marker for Q_Purge()
Memory[ WriteIndexVal ] = ;
// write to head of memory
WriteIndexVal = ;
}
}
}
} // store message to memory
if ( WriteIndexVal != - )
{
// WriteIndexPending for other task if our task be preemptived
Queue->WriteIndex = WriteIndexVal;
Queue->MessageCount++;
Memory[ WriteIndexVal ] = -Size; // SizePending for other task
Queue->InProgressCount++; osRestoreInterrupt( Value );
//
memcpy( &Memory[ WriteIndexVal + ], Message, Size );
//
Value = osDisableInterrupt( );
Memory[ WriteIndexVal ] = Size; // Size for this message
Queue->InProgressCount--;
} osRestoreInterrupt( Value );
return ( WriteIndexVal != - );
} // Retrieves a message from a Queue
// not allowed while the queue is in use.
uint32_t Q_Read( QUEUE * Queue, void ** Message )
{
uint32_t MessageSize = ;
uint32_t * Memory = (uint32_t *) Queue->Memory; uint32_t Value = osDisableInterrupt( );
if ( ( Queue->IsUsing == ) && ( Queue->MessageCount ) )
{
MessageSize = Memory[ Queue->ReadIndex ];
*Message = (void *) ( (uint32_t) ( &Memory[ Queue->ReadIndex ] ) + );
Queue->IsUsing = ;
}
osRestoreInterrupt( Value );
return MessageSize;
} // Deletes the last retrieved message in a Queue.
void Q_Purge( QUEUE * Queue )
{
uint32_t Value = osDisableInterrupt( );
if ( Queue->IsUsing )
{
uint32_t * Memory = (uint32_t *) Queue->Memory;
uint32_t MessageSize = + ALIGN_UP( Memory[ Queue->ReadIndex ], );
Queue->MessageCount--;
uint32_t NextReadIndexVal = Queue->ReadIndex + MessageSize;
Queue->ReadIndex = NextReadIndexVal;
if ( Queue->Capacity - NextReadIndexVal < )
Queue->ReadIndex = ;
else if ( Queue->MessageCount )
{
// Marked by Q_Write(), Next readable message at head of memory
if ( Memory[ NextReadIndexVal ] == )
Queue->ReadIndex = ;
}
Queue->IsUsing = ;
}
osRestoreInterrupt( Value );
}

Queue and Message的更多相关文章

  1. MSMQ(Microsoft Message Queue)

    http://www.cnblogs.com/sk-net/archive/2011/11/25/2232341.html 利用 MSMQ(Microsoft Message Queue),应用程序开 ...

  2. hdu 1509 Windows Message Queue

    题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=1509 Windows Message Queue Description Message queue ...

  3. 消息队列(Message Queue)基本概念(转)

    背景 之前做日志收集模块时,用到flume.另外也有的方案,集成kafaka来提升系统可扩展性,其中涉及到消息队列当时自己并不清楚为什么要使用消息队列.而在我自己提出的原始日志采集方案中不适用消息队列 ...

  4. 常见的Message Queue应用场景

    在最近的工作的里面有同事问到我说,为什么我们需要一个Message Queue,Message Queue可以在哪些地方用,经过一些整理,大概能找到这些点,假如你有这方面的要求,也可以考虑使用Mess ...

  5. 什么是 Message Queue

    Message Queue 是一种非同步的从一个服务到另一个服务的交流形式, 被用于无服务器架构和微服务架构中. Messages 被储存在一个队列中直到被处理了或被删除. 每个Messages只会被 ...

  6. 消息队列(Message Queue)简介及其使用

    消息队列(Message Queue)简介及其使用 摘要:利用 MSMQ(Microsoft Message Queue),应用程序开发人员可以通过发送和接收消息方便地与应用程序进行快速可靠的通信.消 ...

  7. RabbitMQ笔记四:Binding,Queue,Message概念

    Binding详解   黄线部分就是binding Exchange与Exchange,Queue之间的虚拟连接,Binding中可以包含Routing key或者参数   创建binding 注意: ...

  8. Top 10 Uses For A Message Queue

    We’ve been working with, building, and evangelising message queues for the last year, and it’s no se ...

  9. C++ message queue 消息队列入门

    说明:当我们有多个线程以不同的速度运行并且我们想要以特定的顺序从一个线程向另一个线程发送信息时,消息队列可能会有用. 这个想法是,发送线程将消息推送到队列中,而接收线程将消息按自己的步调弹出. 只要发 ...

随机推荐

  1. Android NDK OpenCV C++

    NDK中的OpenCV http://blog.csdn.net/yanzi1225627/article/details/8525720

  2. 如何在MySql中记录SQL日志

    SQL server有一个sql profiler可以实时跟踪服务器执行的SQL语句,这在很多时候调试错误非常有用.例如:别人写的复杂代码.生产系统.无调试环境.无原代码... ...   查了一下资 ...

  3. 堪称最好的A*算法

    原文地址:http://theory.stanford.edu/~amitp/GameProgramming/ 相关链接:http://www-cs-students.stanford.edu/%7E ...

  4. [Everyday Mathematic]20150216

    设 $A,B,C$ 是同阶方阵, 试证: $$\bex (A-B)C=BA^{-1}\ra C(A-B)=A^{-1}B. \eex$$

  5. Delphi 7使用自定义图标关联文件类型

    Delphi 7使用自定义图标关联文件类型 5.2 Delphi编程(40)  版权声明:本文为博主原创文章,未经博主允许不得转载. 在开发过程中,我们经常需要属于自己的文件类型,自定义的后缀名不仅可 ...

  6. bzoj 1492 [NOI2007]货币兑换Cash(斜率dp+cdq分治)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=1492   [题意] 有AB两种货币,每天可以可以付IPi元,买到A券和B券,且A:B= ...

  7. 大数据时代的数据存储,非关系型数据库MongoDB

    在过去的很长一段时间中,关系型数据库(Relational Database Management System)一直是最主流的数据库解决方案,他运用真实世界中事物与关系来解释数据库中抽象的数据架构. ...

  8. Javascript模板及其中的数据逻辑分离思想(MVC)

    #Javascript模板及其中的数据逻辑分离思想 ##需求描述 项目数据库的题目表描述了70-120道题目,并且是会变化的,要根据数据库中的数据描述,比如,选择还是填空题,是不是重点题,题目总分是多 ...

  9. Linux文件系统 (Ubunt)

    Linux 文件系统是linux的一个十分基础的知识,同时也是学习linux的必备知识. 本文将站在一个较高的视图来了解linux的文件系统,主要包括了linux磁盘分区和目录.挂载基本原理.文件存储 ...

  10. jq 选项卡

    <!doctype html> <html> <head> <meta charset="utf-8"> <style> ...