Heim  >  Artikel  >  Backend-Entwicklung  >  C++-Multithreading-Framework (3): Nachrichtenwarteschlange

C++-Multithreading-Framework (3): Nachrichtenwarteschlange

黄舟
黄舟Original
2017-02-06 13:53:192156Durchsuche

Zuvor haben wir einige grundlegende Dinge zum Thema Multithreading zusammengefasst, einschließlich Thread-Erstellung, Mutex-Sperren und Semaphoren.


Wir Versuchen Sie, die mit dem System gelieferte Nachrichtenwarteschlange (z. B. sys/msgqueue) so wenig wie möglich zu verwenden. Natürlich hoffen wir, dass die Nachrichtenwarteschlange Standard-C++-Datenstrukturen verwendet Sie können auch eine verknüpfte Liste oder einen FIFO verwenden. In diesem Fall müssen Sie zuerst eine verknüpfte Liste oder einen FIFO schreiben.


Ich bin faul und verwende direkt die STL-Warteschlange von C++, die eine Dual-Port-Warteschlange ist. Natürlich ist die Geschwindigkeit nicht so hoch Wie die von mir selbst geschriebene verknüpfte Liste spielt jedoch keine Rolle. Bei Verwendung einer Dual-Port-Warteschlange können Sie je nach Bedarf auch Daten in den Kopf oder das Ende der Warteschlange einfügen, was immer noch nützlich ist, wenn Nachrichten Priorität haben.


Die Kernfunktion der Nachrichtenwarteschlange ist eigentlich sehr einfach. Ein oder mehrere Threads stapeln Daten am Ende einer Warteschlange, und ein anderer Thread übernimmt Daten vom Anfang der Warteschlange Für die Verarbeitung gibt es auch nur zwei, eine sendende und eine empfangende, daher definieren wir die Basisklasse der Nachrichtenwarteschlange als:

class CMsgQueue  
{  
    public:  
        CMsgQueue(const char *pName=NULL);  
        ~CMsgQueue();  
        //revice data from message queue  
        virtual bool recvMsg(unsigned int &m_msg_code,void *&p_msg)=0;  
        //send data to message queue  
        virtual bool sendMsg(unsigned int m_msg_code,void *p_msg)=0;  
        const char * getName(void) const {  
                return msg_queue_name;  
            }        
    private:  
        char *msg_queue_name;  
};


Dann denken Sie daran Fügen Sie die Methode zum Erstellen der Nachrichtenwarteschlange in COperratingSystemFactory hinzu:

class COperatingSystemFactory  
{  
    public:  
        static COperatingSystem *newOperatingSystem();  
        static CCountingSem  *newCountingSem(unsigned int init);  
        static CMutex           *newMutex(const char *pName=NULL);  
        static CMsgQueue     *newMsgQueue(const char *pName=NULL);  
  
};


Erben Sie abschließend eine CLinuxMsgQueue von CMsgQueue und implementieren Sie dann recvMsg und sendMsg. Achten Sie bei der Implementierung darauf.


Eine einfache Bedienung des Dual-Port-FIFO funktioniert nicht. Wir hoffen, dass der Thread dort blockiert und auf die Nachricht wartet, wenn beim Empfang einer Nachricht keine Nachricht vorliegt Eine Nachricht kommt an, bevor sie weiter ausgeführt wird. Wenn wir Nachrichten empfangen, verwenden wir einen Semaphor und blockieren den Semaphor. Wenn wir Nachrichten senden, beenden wir den Betrieb der Warteschlange und senden einen Semaphor.


Zweitens hoffen wir, dass der Betrieb der Warteschlange atomar ist, sonst wird es chaotisch, wenn einer empfängt und der andere sendet, also verwenden wir einen Mutex Beim Betreiben der Warteschlange sperren Lassen Sie uns sie sperren, um die grundlegende Atomizität sicherzustellen. Das spezifische Programm, das


entspricht, ist


1. Beantragen Sie eine Sperre und ein Semaphor für jede Nachrichtenwarteschlange

CLinuxMsgQueue::CLinuxMsgQueue(const char *pName):  
CMsgQueue(pName)  
{  
    p_mutex=COperatingSystemFactory::newMutex("Msg Mutex");  
    p_sem=COperatingSystemFactory::newCountingSem(0);  
}


Beim Empfang einer Nachricht:

bool CLinuxMsgQueue::recvMsg(unsigned int &m_msg_code,void *&p_msg)  
{  
    bool result;  
        Elements queue_element;  
    p_sem->Get();  //通过信号量阻塞在这里,有消息到达了才接着往下走  
    p_mutex->Lock();  //锁定,保证原子性  
        //操作队列  
    if (m_queue.empty()) {  
                p_mutex-> UnLock ();  
            return false;    
    }  
    queue_element = m_queue.front();  
    m_queue.pop_front();  
    m_msg_code = queue_element.msg_code;  
    p_msg = queue_element.p_message;  
        //操作队列结束  
    p_mutex->UnLock(); //解除锁定  
        return true;  
}


Beim Versenden geschieht es ähnlich. Auf diese Weise wird eine einfachste Nachrichtenwarteschlange vervollständigt. Wenn wir die Nachrichtenwarteschlange verwenden möchten, ist dies sehr einfach:

int main()  
{  
        //首先,新建一个消息队列  
        CMsgQueue *q=COperatingSystemFactory::newMsgQueue("B to A message Queue");  
        //新建两个线程,TestThread和TestThreadB都是从CThread继承下来的线程类  
    TestThread *a=new TestThread("A");  
    TestThreadB *b=new TestThreadB("B");  
        //将消息队列放到两个线程实体的局部变量中  
    a->setMsgQueue(q);  
    b->setMsgQueue(q);  
        //启动线程  
    a->run();  
    b->run();  
}


Wenn Sie eine Nachricht in Mainloop senden möchten, müssen Sie nur Folgendes tun anrufen

p_msg_send->sendMsg(code, (void *)p_msg);  
//其中p_msg_send是b线程的局部变量,实际指向的是之前新建的消息队列q

Github-Adresse:

https://github.com/wyh267/Cplusplus_Thread_Lib

Auf der Rückseite steht:

Natürlich Dieser Code ist sehr unbefriedigend. Der gesamte Code enthält nicht viele Zeilen. Hier stelle ich nur eine Code-Framework-Methode als Referenz zur Verfügung. Wenn sie wirklich für die tatsächliche Verwendung benötigt wird, gibt es viele, viele Stellen Mein Code auf Github kann auch nicht in der Produktionssoftware verwendet werden. Ich habe auch eine Thread-Bibliothek ohne Drittanbieter implementiert. Es ist auch viel komplizierter Timeout, Message Broadcast, Message Subscription und andere Module können auf mehreren Plattformen wie Linux und Ecos ausgeführt werden und sind grundsätzlich plattformunabhängig. Aus verschiedenen Gründen kann ich jedoch nicht alle hier genannten Codes veröffentlichen Nur ein sehr kleiner Teil der aus dem Projekt extrahierten Thread-Bibliothek bietet auch nur eine Idee für das Programmierdesign. Ich hoffe, dass Ihnen nach dem Lesen weitere Dinge einfallen leistungsstarkes und prägnantes Framework.


Außerdem werde ich den Code auf Github weiter verbessern und nach und nach weitere Module hinzufügen. Wenn Sie Interesse haben, können Sie ihn mit mir verbessern Verwenden Sie es nicht, bevor Sie den Code der Thread-Bibliothek implementiert haben, um unnötige Probleme zu vermeiden.

Das Obige ist der Inhalt des C++-Multithreading-Frameworks (3): Nachrichtenwarteschlange Weitere verwandte Inhalte finden Sie auf der chinesischen PHP-Website (www.php.cn)!


Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn