Producer - Solutions for Consumer Models - Self-built queue

xiaoxiao2021-03-06  77

The author has encountered such a need: a software may send a text message outward atom, on the one hand, sending a text message is a single resource, on the other hand, there are multiple threads to send text messages. According to the principle of "defining unstable factors in an entity", naturally use a special thread to operate SMS devices, its task is to remove the SMS to be sent from the message queue and send it through the SMS device.

This is a relatively common producer-consumer model, that is, a module generates data, and the other module acquires data and processes. How to achieve mutual exclusion? How do you make producers and consumers to be able to work?

Similar to this situation is very common in programming, using a message queue is a good solution. The message queue given herein has the following features: The size of the message is free, and can even be an object; • The length of the message queue (the number of messages) is set, more than the maximum length can choose to discard Or wait; · New news is generally the last side of the queue, or you can put it on the front; · If you have less code, the ideas are simple, you can expand according to the situation;

[Design Idea] Design ideas is actually very simple, the message queue class CHMQ is a template class, saved the message with the CLIST, using criticalSection to implement mutual exclusion, use Event to control the message queue as empty or full. The following common interfaces are provided: • Push () adds messages at the queue, if the message queue is full, depending on the message, or block the message, or block the queue is not full. · INSERT () adds a message to the column, other same push (). · Pop () takes a message from the team head, if the queue is blocked, until it is not empty. · SetMaxCount () Sets the maximum length of the message queue, and if the message queue is complete, the new message is handled. Or discard the message, or block until the queue is not full. · GetMaxCount () Returns the maximum length of the message queue, returns -1 if the maximum length is not set. GetQueueCount () Returns the number of messages in the current message queue.

[Extension] (1) The current CHMQ object only supports a message queue, which can be extended into multiple message queues (2) When the message queue is empty, POP () has been returned when there is a new message, and can be expanded into timeout returns. (3) When the message queue is full, the push () and INSERT () may blocked into the queue to expand into timeout.

#ifndef chmq_h # define chmq_h

#include #include

TemplateClass CHMQ {public: chmq () {m_nmax = -1; m_bdrop = false;

:: InitializecriticalSection (& M_Lock);

m_hpushevent = :: CreateEvent (NULL, FALSE, FALSE, NULL); asssert (m_hpushevent! = null); m_hpopevent = :: CreateEvent (Null, false, false, null); assert (m_hpopevent! = null);}

~ Chmq () {:: deletecriticalsection ;: closehandle (m_hpushevent) ;: closehandle (m_hpopevent); m_list.removeall ();} // queue increase message, if the message queue is full, depending on the setting or Drop the message or block until the queue is not full. Void Push (Type & Type) {:: EntercriticalSection; // If the message queue is full if (m_nmax> 0 && m_list.getcount ()> = m_nmax) {:: resetEvent (m_hpushevent) ;: LeaveCriticalsection (& m_lock) ; If (m_bdrop) return;

IF (: WaitForsingleObject (m_hpushevent, infinite)! = Wait_Object_0) Assert (false) ;: EntercriticalSection (& m_lock);}

M_List.addtail (TYPE); :: setEvent (m_hpopevent) ;: LeavecriticalSection (& m_lock);

/ / The queue head adds a message if the message queue is full, according to the setting or discard the message, or block the queue is not full. void Insert (TYPE & type) {:: EnterCriticalSection (& m_lock); // if the message queue is full if (m_nMax> 0 && m_list.GetCount ()> = m_nMax) {:: ResetEvent (m_hPushEvent); :: LeaveCriticalSection (& m_lock) ; If (m_bdrop) return;

IF (: WaitForsingleObject (m_hpushevent, infinite)! = Wait_Object_0) Assert (false) ;: EntercriticalSection (& m_lock);}

m_list.addhead (Type); :: setEvent (m_hpopevent) ;: LeavecriticalSection;} // Take a message from the queue header if the queue is blocked until it is not empty. TYPE POP () {Type Type;

:: EntercriticalSection (& m_lock);

// If the queue is empty if (m_list.isempty ()) {:: resetEvent (m_hpopevent) ;: Leavecriticalsection (& m_lock); if (: WaitForsingleObject (M_HPopevent, Infinite)! = Wait_Object_0) Assert (false); ::: EntercriticalSection;} type = m_list.removehead (); :: setEvent (m_hpushevent) ;: LeavecriticalSection; & m_lock;

Return Type;}

/ / Return to the number of messages in the current message queue. INT getQueuecount () {int ncount = 0;

:: EntercriticalSection; Ncount = m_list.getcount () ;: LeavecriticalSection (& M_Lock); Return ncount;}

/ / Set the maximum length of the message queue, and how to process the message when the message queue is full. // or discard the message, or block the queue until the queue is not full. Void setMaxcount (int nmax = -1, bool bdrop = false) {:: EntercriticalSection; m_nmax = nmax; m_bdrop = bdrop ;: :: LeavecriticalSection (& m_lock);

/ / Return to the maximum length of the message queue, return -1 if no maximum length is set. INT getMaxcount () {:: EntercriticalSection (& m_lock) ;: LeavecriticalSection (& m_lock); Return m_nmax;}

Private: critical_section m_lock; clist m_list;

Handle M_HPOPEVENT; Handle M_HPUSHEVENT;

INT M_NMAX; BOOL M_BDROP;

#ENDIF // CHMQ_H

转载请注明原文地址:https://www.9cbs.com/read-120858.html

New Post(0)