├── .cproject ├── .gitattributes ├── .gitignore ├── .project ├── .settings └── language.settings.xml ├── Makefile ├── README.md ├── include ├── msgQueue.h └── wxMessageQueue.h ├── src ├── msgQueue.c └── wxMessageQueue.cpp └── test ├── cplusplus └── testCplusplus.cpp ├── inter-process ├── testClient.c └── testServer.c └── inter-thread ├── testIntegrated.c ├── testPerformance.c └── testStress.c /.cproject: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | make 106 | 107 | default 108 | true 109 | true 110 | true 111 | 112 | 113 | 114 | 115 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | 7 | # Standard to msysgit 8 | *.doc diff=astextplain 9 | *.DOC diff=astextplain 10 | *.docx diff=astextplain 11 | *.DOCX diff=astextplain 12 | *.dot diff=astextplain 13 | *.DOT diff=astextplain 14 | *.pdf diff=astextplain 15 | *.PDF diff=astextplain 16 | *.rtf diff=astextplain 17 | *.RTF diff=astextplain 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Windows image file caches 2 | Thumbs.db 3 | ehthumbs.db 4 | 5 | # Folder config file 6 | Desktop.ini 7 | 8 | # Recycle Bin used on file shares 9 | $RECYCLE.BIN/ 10 | 11 | # Windows Installer files 12 | *.cab 13 | *.msi 14 | *.msm 15 | *.msp 16 | 17 | # Windows shortcuts 18 | *.lnk 19 | 20 | # ========================= 21 | # Operating System Files 22 | # ========================= 23 | 24 | # OSX 25 | # ========================= 26 | 27 | .DS_Store 28 | .AppleDouble 29 | .LSOverride 30 | 31 | # Thumbnails 32 | ._* 33 | 34 | # Files that might appear on external disk 35 | .Spotlight-V100 36 | .Trashes 37 | 38 | # Directories potentially created on remote AFP share 39 | .AppleDB 40 | .AppleDesktop 41 | Network Trash Folder 42 | Temporary Items 43 | .apdisk 44 | -------------------------------------------------------------------------------- /.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | tinymq 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.cdt.managedbuilder.core.genmakebuilder 10 | clean,full,incremental, 11 | 12 | 13 | 14 | 15 | org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder 16 | full,incremental, 17 | 18 | 19 | 20 | 21 | 22 | org.eclipse.cdt.core.cnature 23 | org.eclipse.cdt.core.ccnature 24 | org.eclipse.cdt.managedbuilder.core.managedBuildNature 25 | org.eclipse.cdt.managedbuilder.core.ScannerConfigNature 26 | 27 | 28 | -------------------------------------------------------------------------------- /.settings/language.settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | CXXFLAGS = -O0 -g -Wall -fmessage-length=0 -I./include -DDEBUG 2 | 3 | OUTPUT = Debug 4 | ifeq ($(type),release) 5 | OUTPUT = Release 6 | endif 7 | 8 | LIB_OBJS = msgQueue.o wxMessageQueue.o 9 | LIBS = 10 | LIBBASE = tinymq 11 | TARGET = lib$(LIBBASE).a 12 | TEST_CLIENT = Client.exe 13 | TEST_SERVER = Server.exe 14 | TEST_CPLUSPLUS = Cplusplus.exe 15 | TEST_INTEGRATED = Integrated.exe 16 | TEST_PERFORMANCE = Performance.exe 17 | TEST_STRESS = Stress.exe 18 | TEST += $(TEST_CLIENT) $(TEST_SERVER) $(TEST_CPLUSPLUS) 19 | TEST += $(TEST_INTEGRATED) $(TEST_PERFORMANCE) $(TEST_STRESS) 20 | TEST_OBJ = $(foreach item, $(patsubst %.exe, %.o, $(TEST)),test$(item)) 21 | 22 | VPATH = src:test/inter-thread:test/inter-process:test/cplusplus 23 | 24 | all: $(TARGET) $(TEST) 25 | 26 | $(TARGET): $(LIB_OBJS) 27 | $(AR) cr $(TARGET) $(LIB_OBJS) 28 | 29 | %.o: %.cpp 30 | $(CXX) $(CXXFLAGS) -c $< -o $@ 31 | 32 | %.o: %.c 33 | $(CC) $(CXXFLAGS) -c $< -o $@ 34 | 35 | %.exe: test%.o 36 | $(CXX) -o $@ $< -L. -l$(LIBBASE) 37 | 38 | clean: 39 | rm -f $(LIB_OBJS) $(TARGET) $(TEST) $(TEST_OBJ) 40 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # tinymq 2 | VxWorks-like lightweight message queue for Windows 3 | 4 | The tinymq implements the functions about a message queue which is similar with 5 | the Wind River VxWorks kernel message queue. 6 | 7 | The memory layout for tinymq message queue: 8 |

 9 | ----------------   -----------------------------------------------------------
10 | | local memory |-->|                     shared memory                       |
11 | ----------------   -----------------------------------------------------------
12 |        ^                                     ^
13 |        |                                     |
14 | ----------------   -----------------------------------------------------------
15 | |    MSG_Q     |   | MSG_SM | MSG_NODE list |       message queue data       |
16 | ----------------   -----------------------------------------------------------
17 |                                     ^                         ^
18 |                                     |                         |
19 |              ---------------------------------------------    |
20 |              | MSG_NODE1 | MSG_NODE2 | ... | MSG_NODE(N) |    |
21 |              ---------------------------------------------    |
22 |                                                               |
23 |                                               ---------------------------------
24 |                                               | data1 | data2 | ... | data(N) |
25 |                                               ---------------------------------
26 | 
27 | 28 | The message queue is divided into two parts in memory, they are local memory and 29 | shared memory, and these two parts are not closed by. The local memory can be 30 | accessed in an process, also can be accessed between threads in a process. 31 | The shared memory can be accessed between threads in a process if the message 32 | queue name is NULL; or can be accessed between processes if the message queue 33 | name is not NULL. 34 | 35 | For each tinymq, the structure MSG_Q which desribe the header of 36 | the queue is stored in local memory; and the structure MSG_SM, MSG_NODE list and 37 | message queue data are stored in shared memory. 38 | 39 | The structure MSG_Q saves the kernel objects handlers and the shared memory 40 | address; MSG_SM saves the message queue attributes; MSG_NODE list saves all the 41 | nodes for the message queue, and each node saves the attributes of a message; 42 | the message queue data area saves the data for all the messages. 43 | -------------------------------------------------------------------------------- /include/msgQueue.h: -------------------------------------------------------------------------------- 1 | /* msgQueue.h - declaration of VxWorks-like message queue */ 2 | 3 | /* 4 | * This file has no copyright assigned and is placed in the Public Domain. 5 | * This file is a part of the virtual operating system package. 6 | * No warranty is given; refer to the file DISCLAIMER within the package. 7 | * 8 | */ 9 | 10 | /* 11 | modification history 12 | -------------------- 13 | 01a,11nov11,sgu created 14 | */ 15 | 16 | /* 17 | DESCRIPTION 18 | This module defines types and prototypes for a message queue. The message queue 19 | manipulation functions in this file are similar with the Wind River VxWorks 20 | kernel message queue interfaces. 21 | 22 | If you meet some problem with this module, please feel free to contact 23 | me via e-mail: gushengyuan2002@163.com 24 | */ 25 | 26 | #ifndef _MSG_QUEUE_H_ 27 | #define _MSG_QUEUE_H_ 28 | 29 | /* defines */ 30 | 31 | /* wait forever for timeout flag */ 32 | #define WAIT_FOREVER -1 33 | 34 | /* version string length */ 35 | #define VERSION_LEN 8 36 | 37 | /* create an inter-thread message queue */ 38 | #define msgQCreate(maxMsgs, maxMsgLength, options) \ 39 | msgQCreateEx(maxMsgs, maxMsgLength, options, NULL) 40 | 41 | /* typedefs */ 42 | 43 | typedef unsigned int UINT; 44 | typedef void* MSG_Q_ID; /* message queue identify */ 45 | 46 | /* message queue options for task waiting for a message */ 47 | enum MSG_Q_OPTION{ 48 | MSG_Q_FIFO = 0x0000, 49 | MSG_Q_PRIORITY = 0x0001 50 | }; 51 | 52 | /* message sending options for sending a message */ 53 | enum MSG_Q_PRIORITY{ 54 | MSG_PRI_NORMAL = 0x0000, /* put the message at the end of the queue */ 55 | MSG_PRI_URGENT = 0x0001 /* put the message at the frond of the queue */ 56 | }; 57 | 58 | /* message queue status */ 59 | typedef struct tagMSG_Q_STAT { 60 | char version[VERSION_LEN]; /* library version */ 61 | int maxMsgs; /* max messages that can be queued */ 62 | UINT maxMsgLength; /* max bytes in a message */ 63 | int options; /* message queue options */ 64 | int msgNum; /* message number in the queue */ 65 | int sendTimes; /* number of sent */ 66 | int recvTimes; /* number of received */ 67 | }MSG_Q_STAT; 68 | 69 | #ifdef __cplusplus 70 | extern "C" 71 | { 72 | #endif 73 | 74 | /* declarations */ 75 | 76 | /******************************************************************************* 77 | * msgQCreateEx - create a message queue, queue pended tasks in FIFO order 78 | * 79 | * create a message queue, queue pended tasks in FIFO order. 80 | * message name, if name equals NULL, create an inter-thread message 81 | * queue, or create an inter-process message queue. 82 | * 83 | * RETURNS: MSG_Q_ID when success or NULL otherwise. 84 | */ 85 | MSG_Q_ID msgQCreateEx 86 | ( 87 | int maxMsgs, /* max messages that can be queued */ 88 | int maxMsgLength,/* max bytes in a message */ 89 | int options, /* message queue options, ignored on Windows platform */ 90 | const char *name /* message name */ 91 | ); 92 | 93 | /******************************************************************************* 94 | * msgQOpen - open a message queue 95 | * 96 | * open a message queue. 97 | * 98 | * RETURNS: MSG_Q_ID when success or NULL otherwise. 99 | */ 100 | MSG_Q_ID msgQOpen 101 | ( 102 | const char * name /* message name */ 103 | ); 104 | 105 | /******************************************************************************* 106 | * msgQDelete - delete a message queue 107 | * 108 | * delete a message queue. 109 | * 110 | * RETURNS: 0 when success or -1 otherwise. 111 | */ 112 | int msgQDelete 113 | ( 114 | MSG_Q_ID msgQId /* message queue to delete */ 115 | ); 116 | 117 | /******************************************************************************* 118 | * msgQReceive - receive a message from a message queue 119 | * 120 | * receive a message from a message queue. 121 | * 122 | * RETURNS: 0 when success or -1 otherwise. 123 | */ 124 | int msgQReceive 125 | ( 126 | MSG_Q_ID msgQId, /* message queue from which to receive */ 127 | char * buffer, /* buffer to receive message */ 128 | UINT maxNBytes, /* length of buffer */ 129 | int timeout /* ticks to wait */ 130 | ); 131 | 132 | /******************************************************************************* 133 | * msgQSend - send a message to a message queue 134 | * 135 | * send a message to a message queue. 136 | * 137 | * RETURNS: 0 when success or -1 otherwise. 138 | */ 139 | int msgQSend 140 | ( 141 | MSG_Q_ID msgQId, /* message queue on which to send */ 142 | char * buffer, /* message to send */ 143 | UINT nBytes, /* length of message */ 144 | int timeout, /* ticks to wait */ 145 | int priority /* MSG_PRI_NORMAL or MSG_PRI_URGENT */ 146 | ); 147 | 148 | /******************************************************************************* 149 | * msgQStat - get the status of message queue 150 | * 151 | * get the detail status of a message queue. 152 | * 153 | * RETURNS: 0 when success or -1 otherwise. 154 | */ 155 | int msgQStat 156 | ( 157 | MSG_Q_ID msgQId, 158 | MSG_Q_STAT * msgQStatus 159 | ); 160 | 161 | /******************************************************************************* 162 | * msgQShow - show the status of message queue 163 | * 164 | * show the detail status of a message queue. 165 | * 166 | * RETURNS: 0 when success or -1 otherwise. 167 | */ 168 | int msgQShow 169 | ( 170 | MSG_Q_ID msgQId 171 | ); 172 | 173 | #ifdef __cplusplus 174 | } 175 | #endif 176 | 177 | #endif 178 | -------------------------------------------------------------------------------- /include/wxMessageQueue.h: -------------------------------------------------------------------------------- 1 | /* 2 | * wxMessageQueue.h 3 | * 4 | * Created on: 2011-8-28 5 | * Author: Nescafe 6 | */ 7 | 8 | #ifndef WXMESSAGEQUEUE_H_ 9 | #define WXMESSAGEQUEUE_H_ 10 | 11 | /* include */ 12 | #include "msgQueue.h" 13 | 14 | class wxMessageQueue 15 | { 16 | public: 17 | /** constructor */ 18 | wxMessageQueue( 19 | int maxMsgs, /** max messages that can be queued */ 20 | int maxMsgLength, /** max bytes in a message */ 21 | int options, /** message queue options, ignored on Windows platform */ 22 | const char * pstrName = NULL /** message name, NULL for inter-thread, or for inter-process */ 23 | ); 24 | 25 | wxMessageQueue( 26 | MSG_Q_ID msgQId /** message queue id */ 27 | ); 28 | 29 | /** destructor */ 30 | ~wxMessageQueue(); 31 | 32 | /** open a message queue, be sure to delete this object one it's not need */ 33 | static wxMessageQueue * Open( 34 | const char * pstrName /** message name */ 35 | ); 36 | 37 | /** receive a message from a message queue */ 38 | int Receive( 39 | char * buffer, /** buffer to receive message */ 40 | UINT maxNBytes, /** length of buffer */ 41 | int timeout /** ticks to wait */ 42 | ); 43 | 44 | /** send a message to a message queue */ 45 | int Send( 46 | char * buffer, /** message to send */ 47 | UINT nBytes, /** length of message */ 48 | int timeout, /** ticks to wait */ 49 | int priority /** MSG_PRI_NORMAL or MSG_PRI_URGENT */ 50 | ); 51 | 52 | /** get the status of message queue */ 53 | int Stat( 54 | MSG_Q_STAT * msgQStatus 55 | ); 56 | 57 | /** show the status of message queue */ 58 | int Show(); 59 | 60 | protected: 61 | wxMessageQueue(); 62 | 63 | private: 64 | MSG_Q_ID m_msgQId; 65 | }; 66 | 67 | #endif /* WXMESSAGEQUEUE_H_ */ 68 | -------------------------------------------------------------------------------- /src/msgQueue.c: -------------------------------------------------------------------------------- 1 | /* msgQueue.c - implementation of VxWorks-like message queue */ 2 | 3 | /* 4 | * This file has no copyright assigned and is placed in the Public Domain. 5 | * This file is a part of the virtual operating system package. 6 | * No warranty is given; refer to the file DISCLAIMER within the package. 7 | * 8 | */ 9 | 10 | /* 11 | modification history 12 | -------------------- 13 | 01a,11nov11,sgu created 14 | */ 15 | 16 | /* 17 | DESCRIPTION 18 | This module implements the functions for a message queue. The message queue 19 | manipulation functions in this file are similar with the Wind River VxWorks 20 | kernel message queue interfaces. 21 | 22 | The memory architecture for a message queue: 23 | ---------------- ----------------------------------------------------------- 24 | | local memory |-->| shared memory | 25 | ---------------- ----------------------------------------------------------- 26 | ^ ^ 27 | | | 28 | ---------------- ----------------------------------------------------------- 29 | | MSG_Q | | MSG_SM | MSG_NODE list | message queue data | 30 | ---------------- ----------------------------------------------------------- 31 | ^ ^ 32 | | | 33 | --------------------------------------------- | 34 | | MSG_NODE1 | MSG_NODE2 | ... | MSG_NODE(N) | | 35 | --------------------------------------------- | 36 | | 37 | --------------------------------- 38 | | data1 | data2 | ... | data(N) | 39 | --------------------------------- 40 | 41 | The message queue in memory can be divided into two parts, local memory and 42 | shared memory, but these two parts are not closed by. The local memory can be 43 | accessed in an process, also can be accessed between threads in the process. 44 | The shared memory can be accessed between threads in a process if the message 45 | queue name is NULL; or can be accessed between processes if the message queue 46 | name is not NULL. There is one data structure MSG_Q in local memory; three data 47 | structures -- MSG_SM, MSG_NODE list and message queue data in shared memory. 48 | The structure MSG_Q saves the kernel objects handlers and the shared memory 49 | address; MSG_SM saves the message queue attributes; MSG_NODE list saves all the 50 | nodes for the message queue, and each node saves all attribute of each message; 51 | the message queue data area saves all the data for all the message. All the 52 | structures defined below. 53 | 54 | If you meet some problem with this module, please feel free to contact 55 | me via e-mail: gushengyuan2002@163.com 56 | */ 57 | 58 | /* includes */ 59 | 60 | #include 61 | #include 62 | #include 63 | #include "msgQueue.h" 64 | 65 | /* defines */ 66 | 67 | /* invalid node index for message queue node */ 68 | #define MSG_Q_INVALID_NODE -1 69 | 70 | /* objects name prefix */ 71 | 72 | #define _MSG_Q_SEM_P_ "_MSG_Q_SEM_P_" /* prefix for pruducer semaphore */ 73 | #define _MSG_Q_SEM_C_ "_MSG_Q_SEM_C_" /* prefix for consumer semaphore */ 74 | #define _MSG_Q_MUTEX_ "_MSG_Q_MUTEX_" /* prefix for mutex */ 75 | #define _MSG_Q_SHMEM_ "_MSG_Q_SHMEM_" /* prefix for shared memory */ 76 | #define MSG_Q_PREFIX_LEN 16 /* max length of object prefix */ 77 | 78 | /* version string */ 79 | #define MSG_Q_VERSION "0.01" 80 | 81 | /* magic string */ 82 | #define MSG_Q_MAGIC "\1\3\5\7\a\7\5\3\1" 83 | 84 | /* magic string length */ 85 | #define MAGIC_LEN 12 86 | 87 | /* debug printable switch */ 88 | #if defined(DEBUG) || defined(_DEBUG) 89 | #define PRINTF(fmt, ...) \ 90 | printf("FAIL - %s@%d: " fmt, __func__, __LINE__, ##__VA_ARGS__) 91 | #else 92 | #define PRINTF(fmt, ...) 93 | #endif 94 | 95 | /* typedefs */ 96 | 97 | /* message node structure */ 98 | typedef struct tagMSG_NODE { 99 | unsigned long length; /* message length */ 100 | int index; /* node index */ 101 | int free; /* next free message index */ 102 | int used; /* next used message index */ 103 | }MSG_NODE, *P_MSG_NODE; 104 | 105 | /* message queue attributes */ 106 | typedef struct tagMSG_SM { 107 | char version[VERSION_LEN]; /* library version */ 108 | char magic[MAGIC_LEN]; /* verify string */ 109 | int maxMsgs; /* max messages that can be queued */ 110 | UINT maxMsgLength; /* max bytes in a message */ 111 | int options; /* message queue options */ 112 | int msgNum; /* message number in the queue */ 113 | int sendTimes; /* number of sent */ 114 | int recvTimes; /* number of received */ 115 | int head; /* head index of the queue */ 116 | int tail; /* tail index of the queue */ 117 | int free; /* next free index of the queue */ 118 | }MSG_SM, *P_MSG_SM; 119 | 120 | /* objects handlers for message queue */ 121 | typedef struct tagMSG_Q { 122 | HANDLE semPId; /* semaphore for producer */ 123 | HANDLE semCId; /* semaphore for consumer */ 124 | HANDLE mutex; /* mutex for shared data protecting */ 125 | HANDLE hFile; /* file handle for the shared memory file mapping */ 126 | MSG_SM * psm; /* shared memory */ 127 | }MSG_Q, *P_MSG_Q; 128 | 129 | /* implementations */ 130 | 131 | /* 132 | * message queue verification. 133 | */ 134 | static int msgQVerify 135 | ( 136 | MSG_Q_ID msgQId, 137 | const char * pSource 138 | ) 139 | { 140 | P_MSG_Q qid = (P_MSG_Q)msgQId; 141 | MSG_SM * psm = NULL; 142 | 143 | if (pSource == NULL) { 144 | pSource = "unknown"; 145 | } 146 | 147 | /* verify the input argument */ 148 | if (qid == NULL){ 149 | PRINTF("%s: message queue id is NULL!\n", pSource); 150 | return -1; 151 | } 152 | 153 | /* get and check the shared memory pointer */ 154 | psm = qid->psm; 155 | if (psm == NULL) { 156 | PRINTF("%s: share memory is NULL.\n", pSource); 157 | return -1; 158 | } 159 | 160 | /* check the version pointer */ 161 | if (psm->version == NULL) { 162 | PRINTF("%s: version string is NULL.\n", pSource); 163 | return -1; 164 | } 165 | 166 | /* check the version string */ 167 | if (strncmp(psm->version, MSG_Q_VERSION, VERSION_LEN) != 0) { 168 | PRINTF("%s: version string: %s, but expect: %s!\n", 169 | pSource, psm->version, MSG_Q_VERSION); 170 | return -1; 171 | } 172 | 173 | /* check the magic pointer */ 174 | if (psm->magic == NULL) { 175 | PRINTF("%s: magic string is NULL.\n", pSource); 176 | return -1; 177 | } 178 | 179 | /* check the magic string */ 180 | if (strncmp(psm->magic, MSG_Q_MAGIC, MAGIC_LEN) != 0) { 181 | PRINTF("%s: magic string: %s, but expect: %s!\n", 182 | pSource, psm->magic, MSG_Q_MAGIC); 183 | return -1; 184 | } 185 | 186 | return 0; 187 | } 188 | 189 | /* 190 | * create and initialize a message queue, queue pended tasks in FIFO order 191 | */ 192 | MSG_Q_ID msgQCreateEx 193 | ( 194 | int maxMsgs, 195 | int maxMsgLength, 196 | int options, 197 | const char * pstrName 198 | ) 199 | { 200 | P_MSG_Q qid = NULL; /* message queue identify */ 201 | HANDLE semPId = NULL; /* semaphore for producer */ 202 | HANDLE semCId = NULL; /* semaphore for consumer */ 203 | HANDLE mutex = NULL; /* mutex for protect accessing to shared data */ 204 | HANDLE hFile = NULL; 205 | char * strName = NULL; 206 | MSG_SM * psm = NULL; 207 | MSG_NODE * pNode = NULL; 208 | int index = 0; 209 | int memSize = 0; 210 | 211 | /* check the inputed parameters */ 212 | 213 | if (maxMsgs <= 0) { 214 | PRINTF("invalid maxMsgs %d.\n", maxMsgs); 215 | return NULL; 216 | } 217 | 218 | if (maxMsgLength <= 0) { 219 | PRINTF("invalid maxMsgLength %d.\n", maxMsgLength); 220 | return NULL; 221 | } 222 | 223 | if (options != MSG_Q_FIFO && options != MSG_Q_PRIORITY) { 224 | PRINTF("invalid options %d.\n", options); 225 | return NULL; 226 | } 227 | 228 | /* allocate the object name memory */ 229 | if (pstrName != NULL) { 230 | int len = strlen(pstrName) + MSG_Q_PREFIX_LEN + 1; 231 | strName = (char*)malloc(len); 232 | if (strName == NULL) { 233 | PRINTF("allocate memory failed with errno %d!\n", errno); 234 | return NULL; 235 | } 236 | memset(strName, 0, len); 237 | } 238 | 239 | /* create the producer semaphore */ 240 | 241 | if (pstrName != NULL) { 242 | sprintf(strName, "%s%s", _MSG_Q_SEM_P_, pstrName); 243 | } 244 | 245 | semPId = CreateSemaphore(NULL, 0, maxMsgs, strName); 246 | if (semPId == NULL) { 247 | PRINTF("create semaphore with errno %d!\n", (int)GetLastError()); 248 | goto FailedExit; 249 | } 250 | 251 | /* create the consumer semaphore */ 252 | 253 | if (pstrName != NULL) { 254 | sprintf(strName, "%s%s", _MSG_Q_SEM_C_, pstrName); 255 | } 256 | 257 | semCId = CreateSemaphore(NULL, maxMsgs, maxMsgs, strName); 258 | if (semCId == NULL) { 259 | PRINTF("create semaphore with errno %d!\n", (int)GetLastError()); 260 | goto FailedExit; 261 | } 262 | 263 | /* create the mutex */ 264 | 265 | if (pstrName != NULL) { 266 | sprintf(strName, "%s%s", _MSG_Q_MUTEX_, pstrName); 267 | } 268 | 269 | mutex = CreateMutex(NULL, FALSE, strName); 270 | if (mutex == NULL) { 271 | PRINTF("create mutex with errno %d!\n", (int)GetLastError()); 272 | goto FailedExit; 273 | } 274 | 275 | /* allocate the message queue control block memory */ 276 | 277 | qid = (P_MSG_Q)malloc(sizeof(MSG_Q)); 278 | if (qid == NULL) { 279 | PRINTF("allocate memory with errno %d!\n", errno); 280 | goto FailedExit; 281 | } 282 | memset(qid, 0, sizeof(MSG_Q)); 283 | 284 | /* allocate the message queue memory */ 285 | 286 | memSize = sizeof(MSG_SM) + maxMsgs * (sizeof(MSG_NODE) + maxMsgLength); 287 | if (pstrName == NULL) { 288 | /* allocate memory for inter-thread message queue */ 289 | psm = (MSG_SM*)malloc(memSize); 290 | } 291 | else { 292 | /* allocate shared memory for inter-process message queue */ 293 | sprintf(strName, "%s%s", _MSG_Q_SHMEM_, pstrName); 294 | hFile = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 295 | 0, memSize, strName); 296 | if (hFile == NULL) { 297 | PRINTF("CreateFileMapping with errno %d!\n", (int)GetLastError()); 298 | goto FailedExit; 299 | } 300 | 301 | psm = (MSG_SM*)MapViewOfFile(hFile, FILE_MAP_ALL_ACCESS, 0, 0, 0); 302 | if (psm == NULL) { 303 | PRINTF("MapViewOfFile with errno %d!\n", (int)GetLastError()); 304 | goto FailedExit; 305 | } 306 | } 307 | 308 | /* 309 | * NOTES: check the magic string of the shared memory to see if the message 310 | * queue was created before. the same object can be create more than one 311 | * time if the object name is not null -- the object reference is returned 312 | * when the same object is created. In order to avoid overwrite the shared 313 | * memory when get the same object reference, must check the magic string 314 | * of the shared memory. 315 | */ 316 | 317 | if (strcmp(psm->magic, MSG_Q_MAGIC) != 0 || pstrName == NULL) { 318 | /* clear all the shared memory */ 319 | memset(psm, 0, memSize); 320 | 321 | /* set message queue attributes in shared memory */ 322 | strcpy(psm->version, MSG_Q_VERSION); 323 | strcpy(psm->magic, MSG_Q_MAGIC); 324 | psm->maxMsgs = maxMsgs; 325 | psm->maxMsgLength = maxMsgLength; 326 | psm->options = options; 327 | psm->msgNum = 0; 328 | psm->sendTimes = 0; 329 | psm->recvTimes = 0; 330 | psm->head = MSG_Q_INVALID_NODE; 331 | psm->tail = MSG_Q_INVALID_NODE; 332 | psm->free = 0; 333 | 334 | /* set the message queue nodes links */ 335 | pNode = (MSG_NODE*)((char*)psm + sizeof(MSG_SM)); 336 | for(index = 0; index < psm->maxMsgs; index++) { 337 | pNode->length = 0; 338 | pNode->index = index; 339 | pNode->free = index + 1; 340 | pNode->used = MSG_Q_INVALID_NODE; 341 | pNode++; 342 | } 343 | 344 | /* set the next free pointer as INVALID for the last Node */ 345 | pNode--; 346 | pNode->free = MSG_Q_INVALID_NODE; 347 | } 348 | 349 | /* set the message queue objects handlers */ 350 | 351 | qid->semPId = semPId; 352 | qid->semCId = semCId; 353 | qid->mutex = mutex; 354 | qid->hFile = hFile; 355 | qid->psm = psm; 356 | 357 | if (strName != NULL) 358 | free(strName); 359 | 360 | return (MSG_Q_ID)qid; 361 | 362 | FailedExit: 363 | if (hFile != NULL && psm != NULL) 364 | UnmapViewOfFile(psm); 365 | if (hFile == NULL && psm != NULL) 366 | free(psm); 367 | if (hFile != NULL) 368 | CloseHandle(hFile); 369 | if (semPId != NULL) 370 | CloseHandle(semPId); 371 | if (semCId != NULL) 372 | CloseHandle(semCId); 373 | if (mutex != NULL) 374 | CloseHandle(mutex); 375 | if (strName != NULL) 376 | free(strName); 377 | if (qid != NULL) 378 | free(qid); 379 | 380 | return NULL; 381 | } 382 | 383 | /* 384 | * open an existed message queue -- inter-process message queue 385 | */ 386 | MSG_Q_ID msgQOpen 387 | ( 388 | const char * pstrName 389 | ) 390 | { 391 | P_MSG_Q qid = NULL; /* message queue identify */ 392 | HANDLE semPId = NULL; /* semaphore for producer */ 393 | HANDLE semCId = NULL; /* semaphore for consumer */ 394 | HANDLE mutex = NULL; /* mutex for protect accessing to shared data */ 395 | HANDLE hFile = NULL; 396 | char * strName = NULL; 397 | MSG_SM * psm = NULL; 398 | 399 | if (pstrName == NULL) { 400 | PRINTF("input NULL parameter.\n"); 401 | return NULL; 402 | } 403 | else { 404 | /* allocate the object name memory */ 405 | int len = strlen(pstrName) + MSG_Q_PREFIX_LEN + 1; 406 | strName = (char*)malloc(len); 407 | if (strName == NULL) { 408 | PRINTF("allocate memory failed with errno %d!\n", errno); 409 | return NULL; 410 | } 411 | memset(strName, 0, len); 412 | } 413 | 414 | /* allocate the message queue control block memory */ 415 | 416 | qid = (P_MSG_Q)malloc(sizeof(MSG_Q)); 417 | if (qid == NULL) { 418 | PRINTF("allocate memory failed with errno %d!\n", errno); 419 | goto FailedExit; 420 | } 421 | memset(qid, 0, sizeof(MSG_Q)); 422 | 423 | /* open the message queue share data */ 424 | 425 | sprintf(strName, "%s%s", _MSG_Q_SHMEM_, pstrName); 426 | hFile = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, strName); 427 | if (hFile == NULL) { 428 | PRINTF("OpenFileMapping with errno %d!\n", (int)GetLastError()); 429 | goto FailedExit; 430 | } 431 | 432 | psm = (MSG_SM*)MapViewOfFile(hFile, FILE_MAP_ALL_ACCESS, 0, 0, 0); 433 | if (psm == NULL) { 434 | PRINTF("MapViewOfFile with errno %d!\n", (int)GetLastError()); 435 | goto FailedExit; 436 | } 437 | 438 | qid->psm = psm; 439 | 440 | /* valid verification */ 441 | 442 | if (msgQVerify(qid, __func__) == -1) { 443 | goto FailedExit; 444 | } 445 | 446 | /* open the producer semaphore */ 447 | 448 | sprintf(strName, "%s%s", _MSG_Q_SEM_P_, pstrName); 449 | semPId = OpenSemaphore(SEMAPHORE_ALL_ACCESS, FALSE, strName); 450 | if (semPId == NULL) { 451 | PRINTF("open semaphore with errno %d!\n", (int)GetLastError()); 452 | goto FailedExit; 453 | } 454 | 455 | /* open the consumer semaphore */ 456 | 457 | sprintf(strName, "%s%s", _MSG_Q_SEM_C_, pstrName); 458 | semCId = OpenSemaphore(SEMAPHORE_ALL_ACCESS, FALSE, strName); 459 | if (semCId == NULL) { 460 | PRINTF("open semaphore with errno %d!\n", (int)GetLastError()); 461 | goto FailedExit; 462 | } 463 | 464 | /* open the protecting mutex */ 465 | 466 | sprintf(strName, "%s%s", _MSG_Q_MUTEX_, pstrName); 467 | mutex = OpenMutex(MUTEX_ALL_ACCESS, FALSE, strName); 468 | if (mutex == NULL) { 469 | PRINTF("open mutex with errno %d!\n", (int)GetLastError()); 470 | goto FailedExit; 471 | } 472 | 473 | /* set the message queue attributes */ 474 | 475 | qid->semPId = semPId; 476 | qid->semCId = semCId; 477 | qid->mutex = mutex; 478 | qid->hFile = hFile; 479 | qid->psm = psm; 480 | 481 | if (strName != NULL) 482 | free(strName); 483 | 484 | return qid; 485 | 486 | FailedExit: 487 | if (psm != NULL) 488 | UnmapViewOfFile(psm); 489 | if (hFile != NULL) 490 | CloseHandle(hFile); 491 | if (semPId != NULL) 492 | CloseHandle(semPId); 493 | if (semCId != NULL) 494 | CloseHandle(semCId); 495 | if (mutex != NULL) 496 | CloseHandle(mutex); 497 | if (strName != NULL) 498 | free(strName); 499 | if (qid != NULL) 500 | free(qid); 501 | 502 | return NULL; 503 | } 504 | 505 | /* 506 | * delete a message queue 507 | */ 508 | int msgQDelete 509 | ( 510 | MSG_Q_ID msgQId 511 | ) 512 | { 513 | int status = 0; 514 | int failed = 0; 515 | P_MSG_Q qid = (P_MSG_Q)msgQId; 516 | 517 | /* verify if the message queue is valid */ 518 | if (msgQVerify(qid, __func__) == -1) { 519 | return -1; 520 | } 521 | 522 | status = CloseHandle(qid->semPId); 523 | if(status == 0) { 524 | PRINTF("close semaphore with errno %d!\n", (int)GetLastError()); 525 | failed++; 526 | } 527 | 528 | status = CloseHandle(qid->semCId); 529 | if(status == 0) { 530 | PRINTF("close semaphore with errno %d!\n", (int)GetLastError()); 531 | failed++; 532 | } 533 | 534 | status = CloseHandle(qid->mutex); 535 | if(status == 0) { 536 | PRINTF("close mutex with errno %d!\n", (int)GetLastError()); 537 | failed++; 538 | } 539 | 540 | if (qid->hFile != NULL) { 541 | 542 | /* 543 | * NOTES: the shared memory must not be cleared when delete this message 544 | * queue. the close operation in this routine only reduce the reference 545 | * count for the objects, and the objects will be destroyed when the 546 | * objects reference count equal to zero. the objects can be reused if 547 | * the objects reference count is not zero. In order to protect the 548 | * shared memory, avoid to call memset(qid->psm, 0x0, sizeof(MSG_SM)); 549 | * or any other clear operation. 550 | */ 551 | 552 | status = UnmapViewOfFile(qid->psm); 553 | if(status == 0) { 554 | PRINTF("UnmapViewOfFile with errno %d!\n", (int)GetLastError()); 555 | failed++; 556 | } 557 | 558 | status = CloseHandle(qid->hFile); 559 | if(status == 0) { 560 | PRINTF("close mapped file with errno %d!\n", (int)GetLastError()); 561 | failed++; 562 | } 563 | } 564 | else { 565 | free((void*)qid->psm); 566 | } 567 | free((void*)qid); 568 | 569 | return failed == 0 ? 0 : -1; 570 | } 571 | 572 | /* 573 | * receive a message from a message queue 574 | */ 575 | int msgQReceive 576 | ( 577 | MSG_Q_ID msgQId, 578 | char * buffer, 579 | UINT maxNBytes, 580 | int timeout 581 | ) 582 | { 583 | unsigned long status = 0; 584 | unsigned long timeLimit = 0; 585 | MSG_NODE * pNode = NULL; 586 | P_MSG_Q qid = (P_MSG_Q)msgQId; 587 | MSG_SM * psm = NULL; 588 | 589 | if(buffer == NULL) { 590 | PRINTF("input buffer equals NULL.\n"); 591 | return -1; 592 | } 593 | 594 | /* verify if the message queue is valid */ 595 | if (msgQVerify(qid, __func__) == -1) { 596 | return -1; 597 | } 598 | 599 | /* get the shared memory pointer */ 600 | psm = qid->psm; 601 | 602 | /* timeout conversion */ 603 | if(timeout <= -1) timeLimit = INFINITE; /* wait forever */ 604 | else timeLimit = (unsigned long)timeout; 605 | 606 | /* message is available if the producer semaphore can be taken */ 607 | status = WaitForSingleObject(qid->semPId, timeLimit); 608 | if(status != WAIT_OBJECT_0) { 609 | if(status == WAIT_FAILED) { 610 | PRINTF("wait for semaphore with errno:%d!\n", (int)GetLastError()); 611 | } 612 | /* WAIT_TIMEOUT */ 613 | return -1; 614 | } 615 | 616 | /* take the mutex for shared memory protecting */ 617 | status = WaitForSingleObject(qid->mutex, INFINITE); 618 | if(status != WAIT_OBJECT_0) { 619 | /* release the producer semaphore if failed to take the mutex */ 620 | if(0 == ReleaseSemaphore(qid->semPId, 1, NULL)) { 621 | PRINTF("release semaphore with errno:%d!\n", (int)GetLastError()); 622 | return -1; 623 | } 624 | 625 | if(status == WAIT_ABANDONED || status == WAIT_FAILED) { 626 | PRINTF("wait for mutex with errno:%d!\n", (int)GetLastError()); 627 | } 628 | /* WAIT_TIMEOUT */ 629 | return -1; 630 | } 631 | 632 | /* get the message node we want to process */ 633 | pNode = (MSG_NODE*)((char*)psm + sizeof(MSG_SM) + \ 634 | psm->tail * sizeof(MSG_NODE)); 635 | 636 | /* calculate the message length */ 637 | maxNBytes = (maxNBytes > pNode->length) ? pNode->length : maxNBytes; 638 | 639 | /* copy the message to buffer */ 640 | memcpy(buffer, (char*)psm + sizeof(MSG_SM) + \ 641 | psm->maxMsgs * sizeof(MSG_NODE) + \ 642 | psm->maxMsgLength * pNode->index, maxNBytes); 643 | 644 | /* update the tail of the used message link */ 645 | psm->tail = pNode->used; 646 | 647 | /* free and append the message node to the free message link */ 648 | pNode->used = MSG_Q_INVALID_NODE; 649 | pNode->free = psm->free; 650 | psm->free = pNode->index; 651 | 652 | /* there is no message if the tail equals to MSG_Q_INVALID_NODE */ 653 | if (psm->tail == MSG_Q_INVALID_NODE) 654 | psm->head = MSG_Q_INVALID_NODE; 655 | 656 | /* update the message counting attributes */ 657 | psm->msgNum--; 658 | psm->recvTimes++; 659 | 660 | /* release mutex */ 661 | status = ReleaseMutex(qid->mutex); 662 | if(status == 0) { 663 | PRINTF(" release mutex with errno:%d!\n", (int)GetLastError()); 664 | return -1; 665 | } 666 | 667 | /* release the consumer semaphore */ 668 | status = ReleaseSemaphore(qid->semCId, 1, NULL); 669 | if(status == 0) { 670 | PRINTF("release semaphore with errno:%d!\n", (int)GetLastError()); 671 | return -1; 672 | } 673 | 674 | return 0; 675 | } 676 | 677 | /* 678 | * send a message to a message queue 679 | */ 680 | int msgQSend 681 | ( 682 | MSG_Q_ID msgQId, 683 | char * buffer, 684 | UINT nBytes, 685 | int timeout, 686 | int priority 687 | ) 688 | { 689 | int status = 0; 690 | unsigned long timeLimit = 0; 691 | MSG_NODE * pNode = NULL; 692 | P_MSG_Q qid = (P_MSG_Q)msgQId; 693 | MSG_SM * psm = NULL; 694 | 695 | if(buffer == NULL) { 696 | PRINTF("input buffer equals NULL.\n"); 697 | return -1; 698 | } 699 | 700 | if(priority != MSG_PRI_NORMAL && priority != MSG_PRI_URGENT) { 701 | PRINTF("invalid priority %d.\n", priority); 702 | return -1; 703 | } 704 | 705 | /* verify if the message queue is valid */ 706 | if (msgQVerify(qid, __func__) == -1) { 707 | return -1; 708 | } 709 | 710 | /* get the shared memory pointer */ 711 | psm = qid->psm; 712 | 713 | /* check the message length */ 714 | if(nBytes > psm->maxMsgLength) { 715 | PRINTF("nBytes %d exceed the maxMsgLength %d.\n", 716 | nBytes, psm->maxMsgLength); 717 | return -1; 718 | } 719 | 720 | /* timeout conversion */ 721 | if(timeout <= -1) timeLimit = INFINITE; /* wait forever */ 722 | else timeLimit = (unsigned long)timeout; 723 | 724 | /* there is free slot in queue if the consumer semaphore can be taken */ 725 | status = WaitForSingleObject(qid->semCId, timeLimit); 726 | if(status != WAIT_OBJECT_0) { /* failed */ 727 | if(status == WAIT_FAILED) { 728 | PRINTF("wait for semaphore with errno:%d!\n", (int)GetLastError()); 729 | } 730 | /* WAIT_TIMEOUT */ 731 | return -1; 732 | } 733 | 734 | /* take the mutex for shared memory protecting */ 735 | status = WaitForSingleObject(qid->mutex, INFINITE); 736 | if(status != WAIT_OBJECT_0) { 737 | /* release the consumer semaphore if failed to take the mutex */ 738 | if(0 == ReleaseSemaphore(qid->semCId, 1, NULL)) { 739 | PRINTF("release semaphore with errno:%d!\n", (int)GetLastError()); 740 | return -1; 741 | } 742 | 743 | if(status == WAIT_ABANDONED || status == WAIT_FAILED) { 744 | PRINTF("wait for mutex with errno:%d!\n", (int)GetLastError()); 745 | } 746 | /* WAIT_TIMEOUT */ 747 | return -1; 748 | } 749 | 750 | /* get a free message node we want to use */ 751 | pNode = (MSG_NODE*)((char*)psm + sizeof(MSG_SM) + \ 752 | psm->free * sizeof(MSG_NODE)); 753 | 754 | /* update the next free message node number */ 755 | psm->free = pNode->free; 756 | 757 | /* set the node attributes */ 758 | pNode->free = MSG_Q_INVALID_NODE; 759 | pNode->used = MSG_Q_INVALID_NODE; 760 | pNode->length = nBytes; 761 | 762 | /* copy the buffer to the message node */ 763 | memcpy((char*)psm + sizeof(MSG_SM) + \ 764 | psm->maxMsgs * sizeof(MSG_NODE) + \ 765 | psm->maxMsgLength * pNode->index, buffer, nBytes); 766 | 767 | /* both the head and tail pointer to this node if it's the first message */ 768 | if (psm->head == MSG_Q_INVALID_NODE) { 769 | psm->head = pNode->index; 770 | psm->tail = pNode->index; 771 | } 772 | else { 773 | /* or send a normal message or urgent message */ 774 | if (priority == MSG_PRI_NORMAL) { 775 | /* get the head message node */ 776 | MSG_NODE * temp = (MSG_NODE*)((char*)psm + sizeof(MSG_SM) + \ 777 | psm->head * sizeof(MSG_NODE)); 778 | 779 | /* append the new message node to the head message node */ 780 | temp->used = pNode->index; 781 | psm->head = pNode->index; 782 | } 783 | else { 784 | /* append the new message node to the tail message node */ 785 | pNode->used = psm->tail; 786 | psm->tail = pNode->index; 787 | } 788 | } 789 | 790 | /* update the message counting attributes */ 791 | psm->msgNum++; 792 | psm->sendTimes++; 793 | 794 | /* release the mutex */ 795 | status = ReleaseMutex(qid->mutex); 796 | if(status == 0) { 797 | PRINTF("release mutex with errno:%d!\n", (int)GetLastError()); 798 | return -1; 799 | } 800 | 801 | /* release the producer semaphore */ 802 | status = ReleaseSemaphore(qid->semPId, 1, NULL); 803 | if(status == 0) { 804 | PRINTF("release semaphore with errno:%d!\n", (int)GetLastError()); 805 | return -1; 806 | } 807 | 808 | return 0; 809 | } 810 | 811 | /* 812 | * get the status of message queue 813 | */ 814 | int msgQStat 815 | ( 816 | MSG_Q_ID msgQId, 817 | MSG_Q_STAT * msgQStatus 818 | ) 819 | { 820 | P_MSG_Q qid = (P_MSG_Q)msgQId; 821 | MSG_SM * psm = NULL; 822 | 823 | /* verify if the message queue is valid */ 824 | if (msgQVerify(qid, __func__) == -1) { 825 | return -1; 826 | } 827 | 828 | /* save all the message queue attributes */ 829 | 830 | psm = qid->psm; 831 | msgQStatus->maxMsgs = psm->maxMsgs; 832 | msgQStatus->maxMsgLength = psm->maxMsgLength; 833 | msgQStatus->msgNum = psm->msgNum; 834 | msgQStatus->options = psm->options; 835 | msgQStatus->recvTimes = psm->recvTimes; 836 | msgQStatus->sendTimes = psm->sendTimes; 837 | strncpy(msgQStatus->version, psm->version, VERSION_LEN); 838 | 839 | return 0; 840 | } 841 | 842 | /* 843 | * show the status of message queue 844 | */ 845 | int msgQShow 846 | ( 847 | MSG_Q_ID msgQId 848 | ) 849 | { 850 | P_MSG_Q qid = (P_MSG_Q)msgQId; 851 | MSG_SM * psm = NULL; 852 | 853 | /* verify if the message queue is valid */ 854 | if (msgQVerify(qid, __func__) == -1) { 855 | return -1; 856 | } 857 | 858 | /* 859 | * show all the message queue attributes, 860 | * the private attributes like magic, free, head and tail won't be show. 861 | */ 862 | 863 | psm = qid->psm; 864 | printf("msgQueue.version = %s\n", psm->version); 865 | printf("msgQueue.maxMsg = %d\n", psm->maxMsgs); 866 | printf("msgQueue.maxMsgLength = %d\n", psm->maxMsgLength); 867 | printf("msgQueue.msgNum = %d\n", psm->msgNum); 868 | printf("msgQueue.options = %d\n", psm->options); 869 | printf("msgQueue.recvTimes = %d\n", psm->recvTimes); 870 | printf("msgQueue.sendTimes = %d\n", psm->sendTimes); 871 | 872 | return 0; 873 | } 874 | -------------------------------------------------------------------------------- /src/wxMessageQueue.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * wxMessageQueue.cpp 3 | * This file has no copyright assigned and is placed in the Public Domain. 4 | * This file is a part of the virtual operating system package. 5 | * No warranty is given; refer to the file DISCLAIMER within the package. 6 | * 7 | * Implements of functions for message queue. 8 | * 9 | * NOTE: The message queue manipulation functions in this file are similar 10 | * with the Wind River VxWorks kernel message queue interfaces. 11 | * 12 | * If you meet some problem with this module, please feel free to contact 13 | * me via e-mail: gushengyuan2002@163.com 14 | */ 15 | 16 | #include 17 | #include 18 | #include "wxMessageQueue.h" 19 | 20 | wxMessageQueue::wxMessageQueue(int maxMsgs, int maxMsgLength, int options, const char * pstrName) 21 | { 22 | m_msgQId = msgQCreateEx(maxMsgs, maxMsgLength, options, pstrName); 23 | } 24 | 25 | wxMessageQueue::wxMessageQueue(MSG_Q_ID msgQId) 26 | { 27 | m_msgQId = msgQId; 28 | } 29 | 30 | wxMessageQueue::wxMessageQueue() 31 | { 32 | m_msgQId = NULL; 33 | } 34 | 35 | wxMessageQueue::~wxMessageQueue() 36 | { 37 | msgQDelete(m_msgQId); 38 | } 39 | 40 | wxMessageQueue * wxMessageQueue::Open( 41 | const char * pstrName /* message name */ 42 | ) 43 | { 44 | MSG_Q_ID msgQId = msgQOpen(pstrName); 45 | if (msgQId == NULL) 46 | return NULL; 47 | 48 | return new wxMessageQueue(msgQId); 49 | } 50 | 51 | int wxMessageQueue::Receive( 52 | char * buffer, /* buffer to receive message */ 53 | UINT maxNBytes, /* length of buffer */ 54 | int timeout /* ticks to wait */ 55 | ) 56 | { 57 | return msgQReceive(m_msgQId, buffer, maxNBytes, timeout); 58 | } 59 | 60 | int wxMessageQueue::Send( 61 | char * buffer, /* message to send */ 62 | UINT nBytes, /* length of message */ 63 | int timeout, /* ticks to wait */ 64 | int priority /* MSG_PRI_NORMAL or MSG_PRI_URGENT */ 65 | ) 66 | { 67 | return msgQSend(m_msgQId, buffer, nBytes, timeout, priority); 68 | } 69 | 70 | int wxMessageQueue::Stat(MSG_Q_STAT * msgQStatus) 71 | { 72 | return msgQStat(m_msgQId, msgQStatus); 73 | } 74 | 75 | int wxMessageQueue::Show() 76 | { 77 | return msgQShow(m_msgQId); 78 | } 79 | 80 | -------------------------------------------------------------------------------- /test/cplusplus/testCplusplus.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * test.cpp 3 | * This file has no copyright assigned and is placed in the Public Domain. 4 | * This file is a part of the virtual operating system package. 5 | * No warranty is given; refer to the file DISCLAIMER within the package. 6 | * 7 | * Test cases and examples for the message queue module. 8 | * 9 | * NOTE: The message queue manipulation functions in this file are similar 10 | * with the Wind River VxWorks kernel message queue interfaces. 11 | * 12 | * If you meet some problem with this module, please feel free to contact 13 | * me via e-mail: gushengyuan2002@163.com 14 | **/ 15 | 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include "wxMessageQueue.h" 22 | 23 | unsigned int msgQSender(void *param) { 24 | int i = 0; 25 | int priority = 0; 26 | int rc = 0; 27 | MSG_Q_STAT stat; 28 | wxMessageQueue * msgQTest = (wxMessageQueue *)param; 29 | 30 | rc = msgQTest->Stat(&stat); 31 | if(rc != 0) { 32 | printf("Get the message queue state failed in %s.\n", __func__); 33 | exit(1); 34 | } 35 | 36 | Sleep(1000); 37 | while(1) { 38 | do { 39 | char buf[64] = {0}; 40 | sprintf(buf, "%s-%08d", "ab", i); 41 | srand((unsigned)time(NULL)); 42 | if(0 == (rand() % 2)) 43 | priority = MSG_PRI_NORMAL; 44 | else priority = MSG_PRI_URGENT; 45 | rc = msgQTest->Send(buf, strlen(buf), WAIT_FOREVER, priority); 46 | if(rc != 0) { 47 | printf("send message failed in %s.\n", __func__); 48 | exit(1); 49 | } 50 | printf("Send %08d time to recever\n", i); 51 | i++; 52 | } 53 | while((i % (stat.maxMsgs * 3)) == 0); 54 | // Sleep(1000); 55 | } 56 | return 0; 57 | } 58 | 59 | unsigned int msgQReceiver(void *param) { 60 | char buf[64] = {0}; 61 | int i = 0; 62 | int rc = 0; 63 | wxMessageQueue * msgQTest = (wxMessageQueue *)param; 64 | 65 | while(1) { 66 | memset(buf, 0, sizeof(buf)); 67 | rc = msgQTest->Receive(buf, sizeof(buf), WAIT_FOREVER); 68 | if(rc != 0) { 69 | printf("receive message failed in %s.\n", __func__); 70 | exit(1); 71 | } 72 | printf("Recv %08d time of %s\n", i, buf); 73 | Sleep(100); 74 | i++; 75 | } 76 | return 0; 77 | } 78 | 79 | int main(int argc, char* argv[]) { 80 | HANDLE hSender = NULL; 81 | HANDLE hReceiver = NULL; 82 | unsigned int tSender = 0; 83 | unsigned int tReceiver = 0; 84 | char c = 0; 85 | wxMessageQueue * msgQTest = NULL; 86 | int maxMsgs = 3; 87 | 88 | /* Fix the eclipse CDT output issue */ 89 | setbuf(stdout, NULL); 90 | setbuf(stderr, NULL); 91 | 92 | msgQTest = new wxMessageQueue(maxMsgs, 100, MSG_Q_FIFO); 93 | if(msgQTest == NULL) { 94 | printf("create message queue failed in %s.\n", __func__); 95 | exit(1); 96 | } 97 | 98 | hSender = (HANDLE)CreateThread(NULL, 0, 99 | (LPTHREAD_START_ROUTINE)msgQSender, 100 | msgQTest, 0, (DWORD*)&tSender); 101 | 102 | hReceiver = (HANDLE)CreateThread(NULL, 0, 103 | (LPTHREAD_START_ROUTINE)msgQReceiver, 104 | msgQTest, 0, (DWORD*)&tReceiver); 105 | 106 | while((c = getchar()) != 'q') { 107 | msgQTest->Show(); 108 | } 109 | 110 | CloseHandle(hReceiver); 111 | CloseHandle(hSender); 112 | 113 | delete msgQTest; 114 | 115 | return 0; 116 | } 117 | -------------------------------------------------------------------------------- /test/inter-process/testClient.c: -------------------------------------------------------------------------------- 1 | /** 2 | * test.cpp 3 | * This file has no copyright assigned and is placed in the Public Domain. 4 | * This file is a part of the virtual operating system package. 5 | * No warranty is given; refer to the file DISCLAIMER within the package. 6 | * 7 | * Test cases and examples for the message queue module. 8 | * 9 | * NOTE: The message queue manipulation functions in this file are similar 10 | * with the Wind River VxWorks kernel message queue interfaces. 11 | * 12 | * If you meet some problem with this module, please feel free to contact 13 | * me via e-mail: gushengyuan2002@163.com 14 | **/ 15 | 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include "msgQueue.h" 22 | 23 | unsigned int msgQReceiver(void *param) { 24 | char buf[64] = {0}; 25 | int i = 0; 26 | int rc = 0; 27 | MSG_Q_ID msgQTest = (MSG_Q_ID)param; 28 | 29 | while(1) { 30 | memset(buf, 0, sizeof(buf)); 31 | rc = msgQReceive(msgQTest, buf, sizeof(buf), WAIT_FOREVER); 32 | if(rc != 0) { 33 | printf("receive message failed in %s.\n", __func__); 34 | exit(1); 35 | } 36 | printf("Recv %08d time of %s\n", i, buf); 37 | Sleep(100); 38 | i++; 39 | } 40 | return 0; 41 | } 42 | 43 | int main(int argc, char* argv[]) { 44 | HANDLE hReceiver = NULL; 45 | unsigned int tReceiver = 0; 46 | char c = 0; 47 | MSG_Q_ID msgQTest = NULL; 48 | int maxMsgs = 3; 49 | 50 | /* Fix the eclipse CDT output issue */ 51 | setbuf(stdout, NULL); 52 | setbuf(stderr, NULL); 53 | 54 | msgQTest = msgQOpen("test"); 55 | if(msgQTest == NULL) { 56 | msgQTest = msgQCreateEx(maxMsgs, 100, MSG_Q_FIFO, "test"); 57 | printf("%s: message queue created.\n", __func__); 58 | } 59 | else { 60 | printf("%s: message queue opened.\n", __func__); 61 | } 62 | 63 | hReceiver = (HANDLE)CreateThread(NULL, 0, 64 | (LPTHREAD_START_ROUTINE)msgQReceiver, 65 | msgQTest, 0, (DWORD*)&tReceiver); 66 | 67 | while((c = getchar()) != 'q') { 68 | msgQShow(msgQTest); 69 | } 70 | 71 | CloseHandle(hReceiver); 72 | 73 | msgQShow(msgQTest); 74 | 75 | msgQDelete(msgQTest); 76 | 77 | return 0; 78 | } 79 | -------------------------------------------------------------------------------- /test/inter-process/testServer.c: -------------------------------------------------------------------------------- 1 | /** 2 | * test.cpp 3 | * This file has no copyright assigned and is placed in the Public Domain. 4 | * This file is a part of the virtual operating system package. 5 | * No warranty is given; refer to the file DISCLAIMER within the package. 6 | * 7 | * Test cases and examples for the message queue module. 8 | * 9 | * NOTE: The message queue manipulation functions in this file are similar 10 | * with the Wind River VxWorks kernel message queue interfaces. 11 | * 12 | * If you meet some problem with this module, please feel free to contact 13 | * me via e-mail: gushengyuan2002@163.com 14 | **/ 15 | 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include "msgQueue.h" 22 | 23 | unsigned int msgQSender(void *param) { 24 | int i = 0; 25 | int priority = 0; 26 | int rc = 0; 27 | MSG_Q_STAT stat; 28 | MSG_Q_ID msgQTest = (MSG_Q_ID)param; 29 | 30 | rc = msgQStat(msgQTest, &stat); 31 | if(rc != 0) { 32 | printf("Get the message queue state failed in %s.\n", __func__); 33 | exit(1); 34 | } 35 | 36 | Sleep(1000); 37 | while(1) { 38 | do { 39 | char buf[64] = {0}; 40 | sprintf(buf, "%s-%08d", "ab", i); 41 | srand((unsigned)time(NULL)); 42 | if(0 == (rand() % 2)) 43 | priority = MSG_PRI_NORMAL; 44 | else priority = MSG_PRI_URGENT; 45 | rc = msgQSend(msgQTest, buf, strlen(buf), WAIT_FOREVER, priority); 46 | if(rc != 0) { 47 | printf("send message failed in %s.\n", __func__); 48 | exit(1); 49 | } 50 | printf("Send %08d time to recever\n", i); 51 | i++; 52 | } 53 | while((i % (stat.maxMsgs * 3)) == 0); 54 | // Sleep(1000); 55 | } 56 | return 0; 57 | } 58 | 59 | int main(int argc, char* argv[]) { 60 | HANDLE hSender = NULL; 61 | unsigned int tSender = 0; 62 | char c = 0; 63 | MSG_Q_ID msgQTest = NULL; 64 | int maxMsgs = 3; 65 | 66 | /* Fix the eclipse CDT output issue */ 67 | setbuf(stdout, NULL); 68 | setbuf(stderr, NULL); 69 | 70 | msgQTest = msgQOpen("test"); 71 | if(msgQTest == NULL) { 72 | msgQTest = msgQCreateEx(maxMsgs, 100, MSG_Q_FIFO, "test"); 73 | printf("%s: message queue created.\n", __func__); 74 | } 75 | else { 76 | printf("%s: message queue opened.\n", __func__); 77 | } 78 | 79 | hSender = (HANDLE)CreateThread(NULL, 0, 80 | (LPTHREAD_START_ROUTINE)msgQSender, 81 | msgQTest, 0, (DWORD*)&tSender); 82 | 83 | while((c = getchar()) != 'q') { 84 | msgQShow(msgQTest); 85 | } 86 | 87 | CloseHandle(hSender); 88 | 89 | msgQShow(msgQTest); 90 | 91 | msgQDelete(msgQTest); 92 | 93 | return 0; 94 | } 95 | -------------------------------------------------------------------------------- /test/inter-thread/testIntegrated.c: -------------------------------------------------------------------------------- 1 | /** 2 | * test.cpp 3 | * This file has no copyright assigned and is placed in the Public Domain. 4 | * This file is a part of the virtual operating system package. 5 | * No warranty is given; refer to the file DISCLAIMER within the package. 6 | * 7 | * Test cases and examples for the message queue module. 8 | * 9 | * NOTE: The message queue manipulation functions in this file are similar 10 | * with the Wind River VxWorks kernel message queue interfaces. 11 | * 12 | * If you meet some problem with this module, please feel free to contact 13 | * me via e-mail: gushengyuan2002@163.com 14 | **/ 15 | 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include "msgQueue.h" 22 | 23 | unsigned int msgQSender(void *param) { 24 | int i = 0; 25 | int priority = 0; 26 | int rc = 0; 27 | MSG_Q_STAT stat; 28 | MSG_Q_ID msgQTest = (MSG_Q_ID)param; 29 | 30 | rc = msgQStat(msgQTest, &stat); 31 | if(rc != 0) { 32 | printf("Get the message queue state failed in %s.\n", __func__); 33 | exit(1); 34 | } 35 | 36 | Sleep(1000); 37 | while(1) { 38 | do { 39 | char buf[64] = {0}; 40 | sprintf(buf, "%s-%08d", "ab", i); 41 | srand((unsigned)time(NULL)); 42 | if(0 == (rand() % 2)) 43 | priority = MSG_PRI_NORMAL; 44 | else priority = MSG_PRI_URGENT; 45 | rc = msgQSend(msgQTest, buf, strlen(buf), WAIT_FOREVER, priority); 46 | if(rc != 0) { 47 | printf("send message failed in %s.\n", __func__); 48 | exit(1); 49 | } 50 | printf("Send %08d time to recever\n", i); 51 | i++; 52 | } 53 | while((i % (stat.maxMsgs * 3)) == 0); 54 | // Sleep(1000); 55 | } 56 | return 0; 57 | } 58 | 59 | unsigned int msgQReceiver(void *param) { 60 | char buf[64] = {0}; 61 | int i = 0; 62 | int rc = 0; 63 | MSG_Q_ID msgQTest = (MSG_Q_ID)param; 64 | 65 | while(1) { 66 | memset(buf, 0, sizeof(buf)); 67 | rc = msgQReceive(msgQTest, buf, sizeof(buf), WAIT_FOREVER); 68 | if(rc != 0) { 69 | printf("receive message failed in %s.\n", __func__); 70 | exit(1); 71 | } 72 | printf("Recv %08d time of %s\n", i, buf); 73 | Sleep(100); 74 | i++; 75 | } 76 | return 0; 77 | } 78 | 79 | int main(int argc, char* argv[]) { 80 | HANDLE hSender = NULL; 81 | HANDLE hReceiver = NULL; 82 | unsigned int tSender = 0; 83 | unsigned int tReceiver = 0; 84 | char c = 0; 85 | MSG_Q_ID msgQTest = NULL; 86 | int maxMsgs = 8; 87 | 88 | /* Fix the eclipse CDT output issue */ 89 | setbuf(stdout, NULL); 90 | setbuf(stderr, NULL); 91 | 92 | msgQTest = msgQCreate(maxMsgs, 100, MSG_Q_FIFO); 93 | if(msgQTest == NULL) { 94 | printf("create message queue failed in %s.\n", __func__); 95 | exit(1); 96 | } 97 | 98 | hSender = (HANDLE)CreateThread(NULL, 0, 99 | (LPTHREAD_START_ROUTINE)msgQSender, 100 | msgQTest, 0, (DWORD*)&tSender); 101 | 102 | hReceiver = (HANDLE)CreateThread(NULL, 0, 103 | (LPTHREAD_START_ROUTINE)msgQReceiver, 104 | msgQTest, 0, (DWORD*)&tReceiver); 105 | 106 | while((c = getchar()) != 'q') { 107 | msgQShow(msgQTest); 108 | } 109 | 110 | CloseHandle(hReceiver); 111 | CloseHandle(hSender); 112 | 113 | msgQDelete(msgQTest); 114 | 115 | return 0; 116 | } 117 | -------------------------------------------------------------------------------- /test/inter-thread/testPerformance.c: -------------------------------------------------------------------------------- 1 | /** 2 | * test.cpp 3 | * This file has no copyright assigned and is placed in the Public Domain. 4 | * This file is a part of the virtual operating system package. 5 | * No warranty is given; refer to the file DISCLAIMER within the package. 6 | * 7 | * Test cases and examples for the message queue module. 8 | * 9 | * NOTE: The message queue manipulation functions in this file are similar 10 | * with the Wind River VxWorks kernel message queue interfaces. 11 | * 12 | * If you meet some problem with this module, please feel free to contact 13 | * me via e-mail: gushengyuan2002@163.com 14 | **/ 15 | 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include "msgQueue.h" 22 | 23 | typedef struct tagMSG_Q_TEST { 24 | MSG_Q_ID msgQId; 25 | MSG_Q_ID send; 26 | MSG_Q_ID recv; 27 | int count; 28 | }MSG_Q_TEST; 29 | 30 | typedef struct tagMSG_Q_RESULT { 31 | int count; 32 | int time; 33 | }MSG_Q_RESULT; 34 | 35 | int tc_create_delete(void) { 36 | int i = 0; 37 | int rc = 0; 38 | MSG_Q_ID * msgQId = NULL; 39 | int count = 10000; 40 | int slice = 0; 41 | int result = 0; 42 | 43 | printf("start of test %s.\n", __func__); 44 | 45 | /* allocate memory for MSG_Q_ID */ 46 | msgQId = (MSG_Q_ID*)malloc(sizeof(MSG_Q_ID) * count); 47 | memset(msgQId, 0, sizeof(MSG_Q_ID) * count); 48 | 49 | /* test for msgQCreate */ 50 | slice = GetTickCount(); 51 | for(i = 0; i < count; i++) { 52 | msgQId[i] = msgQCreate(100, 100, MSG_Q_FIFO); 53 | if(msgQId[i] == NULL) { 54 | printf("%s: create message queue failed in loop %d.\n", __func__, i); 55 | result = -1; 56 | break; 57 | } 58 | } 59 | slice = GetTickCount() - slice; 60 | printf("finish msgQCreate(...) in %d times with %d ms.\n", i, slice); 61 | 62 | /* test for msgQDelete */ 63 | slice = GetTickCount(); 64 | for(i = 0; i < count; i++) { 65 | if (msgQId[i] != NULL) 66 | rc = msgQDelete(msgQId[i]); 67 | if(rc != 0) { 68 | printf("%s: delete message queue failed in loop %d.\n", __func__, i); 69 | result = -1; 70 | break; 71 | } 72 | } 73 | slice = GetTickCount() - slice; 74 | printf("finish msgQDelete(...) in %d times with %d ms.\n", i, slice); 75 | 76 | free(msgQId); 77 | printf("end of testing %s.\n", __func__); 78 | 79 | return result; 80 | } 81 | 82 | int tc_create_delete_ex(void) { 83 | int i = 0; 84 | int rc = 0; 85 | MSG_Q_ID * msgQId = NULL; 86 | int count = 10000; 87 | int slice = 0; 88 | int result = 0; 89 | char buf[64] = {0}; 90 | 91 | printf("start of test %s.\n", __func__); 92 | 93 | /* allocate memory for MSG_Q_ID */ 94 | msgQId = (MSG_Q_ID*)malloc(sizeof(MSG_Q_ID) * count); 95 | memset(msgQId, 0, sizeof(MSG_Q_ID) * count); 96 | 97 | /* test for msgQCreateEx */ 98 | slice = GetTickCount(); 99 | for(i = 0; i < count; i++) { 100 | sprintf(buf, "test_%d", i); 101 | msgQId[i] = msgQCreateEx(100, 100, MSG_Q_FIFO, buf); 102 | if(msgQId[i] == NULL) { 103 | printf("%s: create message queue failed in loop %d.\n", __func__, i); 104 | result = -1; 105 | break; 106 | } 107 | } 108 | slice = GetTickCount() - slice; 109 | printf("finish msgQCreateEx(...) in %d times with %d ms.\n", i, slice); 110 | 111 | /* test for msgQDelete */ 112 | slice = GetTickCount(); 113 | for(i = 0; i < count; i++) { 114 | if (msgQId[i] != NULL) 115 | rc = msgQDelete(msgQId[i]); 116 | if(rc != 0) { 117 | printf("%s: delete message queue failed in loop %d.\n", __func__, i); 118 | result = -1; 119 | break; 120 | } 121 | } 122 | slice = GetTickCount() - slice; 123 | printf("finish msgQDelete(...) in %d times with %d ms.\n", i, slice); 124 | 125 | free(msgQId); 126 | printf("end of testing %s.\n", __func__); 127 | 128 | return result; 129 | } 130 | 131 | unsigned int msgQSender(void *param) { 132 | int i = 0; 133 | int priority = 0; 134 | int rc = 0; 135 | MSG_Q_TEST * msgQTest = (MSG_Q_TEST*)param; 136 | MSG_Q_ID msgQId = msgQTest->msgQId; 137 | MSG_Q_ID send = msgQTest->send; 138 | int count = msgQTest->count; 139 | int slice = 0; 140 | MSG_Q_RESULT ret = {0}; 141 | 142 | slice = GetTickCount(); 143 | for (i = 0; i < count; i++) { 144 | char buf[64] = {0}; 145 | sprintf(buf, "%s-%08d", "ab", i); 146 | srand((unsigned)time(NULL)); 147 | if(0 == (rand() % 2)) 148 | priority = MSG_PRI_NORMAL; 149 | else priority = MSG_PRI_URGENT; 150 | rc = msgQSend(msgQId, buf, strlen(buf), WAIT_FOREVER, priority); 151 | if(rc != 0) { 152 | printf("send message failed in %s.\n", __func__); 153 | break; 154 | } 155 | } 156 | slice = GetTickCount() - slice; 157 | 158 | ret.count = i; 159 | ret.time = slice; 160 | rc = msgQSend(send, (char*)&ret, sizeof(ret), WAIT_FOREVER, MSG_PRI_NORMAL); 161 | if(rc != 0) { 162 | printf("send message failed in %s.\n", __func__); 163 | return -1; 164 | } 165 | 166 | return 0; 167 | } 168 | 169 | unsigned int msgQReceiver(void *param) { 170 | char buf[64] = {0}; 171 | int i = 0; 172 | int rc = 0; 173 | MSG_Q_TEST * msgQTest = (MSG_Q_TEST*)param; 174 | MSG_Q_ID msgQId = msgQTest->msgQId; 175 | MSG_Q_ID recv = msgQTest->recv; 176 | int count = msgQTest->count; 177 | int slice = 0; 178 | MSG_Q_RESULT ret = {0}; 179 | 180 | slice = GetTickCount(); 181 | for (i = 0; i < count; i++) { 182 | memset(buf, 0, sizeof(buf)); 183 | rc = msgQReceive(msgQId, buf, sizeof(buf), WAIT_FOREVER); 184 | if(rc != 0) { 185 | printf("receive message failed in %s.\n", __func__); 186 | break; 187 | } 188 | } 189 | slice = GetTickCount() - slice; 190 | 191 | ret.count = i; 192 | ret.time = slice; 193 | rc = msgQSend(recv, (char*)&ret, sizeof(ret), WAIT_FOREVER, MSG_PRI_NORMAL); 194 | if(rc != 0) { 195 | printf("send message failed in %s.\n", __func__); 196 | return -1; 197 | } 198 | 199 | return 0; 200 | } 201 | 202 | int tc_send_recv(int buffer, int tests, int ext) { 203 | HANDLE hSender = NULL; 204 | HANDLE hReceiver = NULL; 205 | unsigned int tSender = 0; 206 | unsigned int tReceiver = 0; 207 | MSG_Q_ID msgQId = NULL; 208 | MSG_Q_ID send = NULL; 209 | MSG_Q_ID recv = NULL; 210 | MSG_Q_TEST msgQTest = {0}; 211 | MSG_Q_RESULT ret = {0}; 212 | int rc = 0; 213 | 214 | if (ext) { 215 | msgQId = msgQCreateEx(buffer, 100, MSG_Q_FIFO, "self"); 216 | } 217 | else { 218 | msgQId = msgQCreate(buffer, 100, MSG_Q_FIFO); 219 | } 220 | if(msgQId == NULL) { 221 | printf("create message queue failed in %s.\n", __func__); 222 | exit(1); 223 | } 224 | 225 | send = msgQCreate(4, 100, MSG_Q_FIFO); 226 | if(send == NULL) { 227 | printf("create message queue failed in %s.\n", __func__); 228 | exit(1); 229 | } 230 | 231 | recv = msgQCreate(4, 100, MSG_Q_FIFO); 232 | if(recv == NULL) { 233 | printf("create message queue failed in %s.\n", __func__); 234 | exit(1); 235 | } 236 | 237 | /* test structure */ 238 | msgQTest.msgQId = msgQId; 239 | msgQTest.send = send; 240 | msgQTest.recv = recv; 241 | msgQTest.count = tests; 242 | 243 | hSender = (HANDLE)CreateThread(NULL, 0, 244 | (LPTHREAD_START_ROUTINE)msgQSender, 245 | &msgQTest, 0, (DWORD*)&tSender); 246 | 247 | hReceiver = (HANDLE)CreateThread(NULL, 0, 248 | (LPTHREAD_START_ROUTINE)msgQReceiver, 249 | &msgQTest, 0, (DWORD*)&tReceiver); 250 | 251 | /* wait for result */ 252 | rc = msgQReceive(send, (char*)&ret, sizeof(ret), WAIT_FOREVER); 253 | if(rc != 0) { 254 | printf("receive message failed in %s.\n", __func__); 255 | return -1; 256 | } 257 | printf("finish msgQSend(...) in %d times with %d ms.\n", ret.count, ret.time); 258 | 259 | rc = msgQReceive(recv, (char*)&ret, sizeof(ret), WAIT_FOREVER); 260 | if(rc != 0) { 261 | printf("receive message failed in %s.\n", __func__); 262 | return -1; 263 | } 264 | printf("finish msgQReceive(...) in %d times with %d ms.\n", ret.count, ret.time); 265 | 266 | CloseHandle(hReceiver); 267 | CloseHandle(hSender); 268 | 269 | msgQDelete(send); 270 | msgQDelete(recv); 271 | msgQDelete(msgQId); 272 | 273 | return 0; 274 | } 275 | 276 | int tc_msgQSend_msgQReveive(int maxMsgs, int tests){ 277 | int rc = 0; 278 | 279 | printf("start of test %s with buffer %d.\n", __func__, maxMsgs); 280 | rc = tc_send_recv(maxMsgs, tests, 0); 281 | printf("end of testing %s with buffer %d.\n", __func__, maxMsgs); 282 | 283 | return rc; 284 | } 285 | 286 | int tc_msgQSend_msgQReveive_Ex(int maxMsgs, int tests){ 287 | int rc = 0; 288 | 289 | printf("start of test %s with buffer %d.\n", __func__, maxMsgs); 290 | rc = tc_send_recv(maxMsgs, tests, 1); 291 | printf("end of testing %s with buffer %d.\n", __func__, maxMsgs); 292 | 293 | return rc; 294 | } 295 | 296 | int main(int argc, char **argv) { 297 | int tests = 1000000; 298 | int buffer[] = {1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024}; 299 | unsigned int index = 0; 300 | 301 | /* Fix the eclipse CDT output issue */ 302 | setbuf(stdout, NULL); 303 | setbuf(stderr, NULL); 304 | 305 | tc_create_delete(); 306 | tc_create_delete_ex(); 307 | 308 | for (index = 0; index < sizeof(buffer)/sizeof(int); index++) { 309 | tc_msgQSend_msgQReveive(buffer[index], tests); 310 | } 311 | 312 | for (index = 0; index < sizeof(buffer)/sizeof(int); index++) { 313 | tc_msgQSend_msgQReveive_Ex(buffer[index], tests); 314 | } 315 | 316 | return 0; 317 | } 318 | -------------------------------------------------------------------------------- /test/inter-thread/testStress.c: -------------------------------------------------------------------------------- 1 | /** 2 | * test.cpp 3 | * This file has no copyright assigned and is placed in the Public Domain. 4 | * This file is a part of the virtual operating system package. 5 | * No warranty is given; refer to the file DISCLAIMER within the package. 6 | * 7 | * Test cases and examples for the message queue module. 8 | * 9 | * NOTE: The message queue manipulation functions in this file are similar 10 | * with the Wind River VxWorks kernel message queue interfaces. 11 | * 12 | * If you meet some problem with this module, please feel free to contact 13 | * me via e-mail: gushengyuan2002@163.com 14 | **/ 15 | 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include "msgQueue.h" 22 | 23 | HANDLE mutex = NULL; 24 | 25 | int tc_msgQCreateEx_parameters(void) { 26 | MSG_Q_ID msgQId = NULL; 27 | int fails = 0; 28 | 29 | printf("start of test %s.\n", __func__); 30 | 31 | msgQId = msgQCreateEx(0, 100, MSG_Q_FIFO, NULL); 32 | if (msgQId != NULL) { 33 | printf("Failed to test maxMsgs with 0.\n"); 34 | fails++; 35 | } 36 | 37 | msgQId = msgQCreateEx(-1, 100, MSG_Q_FIFO, NULL); 38 | if (msgQId != NULL) { 39 | printf("Failed to test maxMsgs with -1.\n"); 40 | fails++; 41 | } 42 | 43 | msgQId = msgQCreateEx(100, 0, MSG_Q_FIFO, NULL); 44 | if (msgQId != NULL) { 45 | printf("Failed to test maxMsgLength with 0.\n"); 46 | fails++; 47 | } 48 | 49 | msgQId = msgQCreateEx(100, -1, MSG_Q_FIFO, NULL); 50 | if (msgQId != NULL) { 51 | printf("Failed to test maxMsgLength with -1.\n"); 52 | fails++; 53 | } 54 | 55 | msgQId = msgQCreateEx(100, 100, MSG_Q_FIFO + 100, NULL); 56 | if (msgQId != NULL) { 57 | printf("Failed to test options with invalid value.\n"); 58 | fails++; 59 | } 60 | 61 | printf("end of testing %s.\n", __func__); 62 | return fails; 63 | } 64 | 65 | int tc_open_delete_parameters(void) { 66 | int rc = 0; 67 | MSG_Q_ID msgQId = NULL; 68 | char *ptr = NULL; 69 | int fails = 0; 70 | 71 | printf("start of test %s.\n", __func__); 72 | 73 | msgQId = msgQOpen(NULL); 74 | if (msgQId != NULL) { 75 | printf("Failed to test msgQOpen with invalid value.\n"); 76 | fails++; 77 | } 78 | 79 | msgQId = msgQOpen("test_001"); 80 | if (msgQId != NULL) { 81 | printf("Failed to test msgQOpen with unknown name.\n"); 82 | fails++; 83 | } 84 | 85 | ptr = (char*)malloc(1000); 86 | if (ptr == NULL) { 87 | printf("Failed to allocate memory.\n"); 88 | fails++; 89 | goto exit; 90 | } 91 | memset(ptr, 0, 1000); 92 | 93 | rc = msgQDelete((MSG_Q_ID)ptr); 94 | if (rc == 0) { 95 | printf("Failed to test msgQDelete with invalid message queue.\n"); 96 | fails++; 97 | } 98 | 99 | if (ptr != NULL) { 100 | free(ptr); 101 | } 102 | 103 | exit: 104 | printf("end of testing %s.\n", __func__); 105 | return fails; 106 | } 107 | 108 | unsigned int msgQStressSender(void *param) { 109 | int i = 0; 110 | int index = 0; 111 | int priority = 0; 112 | int rc = 0; 113 | MSG_Q_STAT stat = {{0},0}; 114 | MSG_Q_ID msgQTest = (MSG_Q_ID)param; 115 | 116 | rc = msgQStat(msgQTest, &stat); 117 | if(rc != 0) { 118 | printf("Get the message queue state failed in %s.\n", __func__); 119 | exit(1); 120 | } 121 | 122 | while(1) { 123 | /* protect common data */ 124 | rc = WaitForSingleObject(mutex, INFINITE); 125 | if(rc != WAIT_OBJECT_0) { 126 | printf("wait for mutex with errno:%d!\n", (int)GetLastError()); 127 | return -1; 128 | } 129 | 130 | for (index = 0; index <= stat.maxMsgs; index++) { 131 | char buf[64] = {0}; 132 | sprintf(buf, "%s-%08d", "ab", i); 133 | srand((unsigned)time(NULL)); 134 | if(0 == (rand() % 2)) 135 | priority = MSG_PRI_NORMAL; 136 | else priority = MSG_PRI_URGENT; 137 | rc = msgQSend(msgQTest, buf, strlen(buf), 2000, priority); 138 | if(rc != 0) { 139 | printf("send message failed in %s.\n", __func__); 140 | break; 141 | } 142 | printf("Send %08d time to recever\n", i); 143 | i++; 144 | Sleep(5 + i % 2); 145 | } 146 | 147 | rc = ReleaseMutex(mutex); 148 | if(rc == 0) { 149 | printf(" release mutex with errno:%d!\n", (int)GetLastError()); 150 | return -1; 151 | } 152 | } 153 | return 0; 154 | } 155 | 156 | unsigned int msgQStressReceiver(void *param) { 157 | char buf[64] = {0}; 158 | int i = 0; 159 | int index = 0; 160 | int rc = 0; 161 | MSG_Q_STAT stat = {{0},0}; 162 | MSG_Q_ID msgQTest = (MSG_Q_ID)param; 163 | 164 | rc = msgQStat(msgQTest, &stat); 165 | if(rc != 0) { 166 | printf("Get the message queue state failed in %s.\n", __func__); 167 | exit(1); 168 | } 169 | 170 | Sleep(1000); 171 | 172 | while(1) { 173 | /* protect common data */ 174 | rc = WaitForSingleObject(mutex, INFINITE); 175 | if(rc != WAIT_OBJECT_0) { 176 | printf("wait for mutex with errno:%d!\n", (int)GetLastError()); 177 | return -1; 178 | } 179 | 180 | for (index = 0; index <= stat.maxMsgs; index++) { 181 | memset(buf, 0, sizeof(buf)); 182 | rc = msgQReceive(msgQTest, buf, sizeof(buf), 2000); 183 | if(rc != 0) { 184 | printf("receive message failed in %s.\n", __func__); 185 | break; 186 | } 187 | printf("Recv %08d time of %s\n", i, buf); 188 | i++; 189 | } 190 | 191 | rc = ReleaseMutex(mutex); 192 | if(rc == 0) { 193 | printf(" release mutex with errno:%d!\n", (int)GetLastError()); 194 | return -1; 195 | } 196 | 197 | Sleep(100); 198 | } 199 | return 0; 200 | } 201 | 202 | int main(int argc, char* argv[]) { 203 | HANDLE hSender = NULL; 204 | HANDLE hReceiver = NULL; 205 | unsigned int tSender = 0; 206 | unsigned int tReceiver = 0; 207 | char c = 0; 208 | MSG_Q_ID msgQTest = NULL; 209 | int maxMsgs = 8; 210 | 211 | /* Fix the eclipse CDT output issue */ 212 | setbuf(stdout, NULL); 213 | setbuf(stderr, NULL); 214 | 215 | tc_msgQCreateEx_parameters(); 216 | 217 | tc_open_delete_parameters(); 218 | 219 | mutex = CreateMutex(NULL, FALSE, NULL); 220 | if (mutex == NULL) { 221 | printf("create mutex with errno %d!\n", (int)GetLastError()); 222 | return -1; 223 | } 224 | 225 | msgQTest = msgQCreate(maxMsgs, 100, MSG_Q_FIFO); 226 | if(msgQTest == NULL) { 227 | printf("create message queue failed in %s.\n", __func__); 228 | exit(1); 229 | } 230 | 231 | hSender = (HANDLE)CreateThread(NULL, 0, 232 | (LPTHREAD_START_ROUTINE)msgQStressSender, 233 | msgQTest, 0, (DWORD*)&tSender); 234 | 235 | hReceiver = (HANDLE)CreateThread(NULL, 0, 236 | (LPTHREAD_START_ROUTINE)msgQStressReceiver, 237 | msgQTest, 0, (DWORD*)&tReceiver); 238 | 239 | while((c = getchar()) != 'q') { 240 | msgQShow(msgQTest); 241 | } 242 | 243 | CloseHandle(hReceiver); 244 | CloseHandle(hSender); 245 | 246 | msgQDelete(msgQTest); 247 | 248 | return 0; 249 | } 250 | --------------------------------------------------------------------------------