线程间通信: 消息队列(同步通信和异步通信)

这是一段非常经典的代码,使用 消息队列 实现线程间 同步通信或者异步通信:

/*
     * Copyright (C) 2011 The Android Open Source Project
     *
     * Licensed under the Apache License, Version 2.0 (the "License");
     * you may not use this file except in compliance with the License.
     * You may obtain a copy of the License at
     *
     * http://www.apache.org/licenses/LICENSE-2.0
     *
     * Unless required by applicable law or agreed to in writing, software
     * distributed under the License is distributed on an "AS IS" BASIS,
     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     * See the License for the specific language governing permissions and
     * limitations under the License.
     */
    #ifndef MESSAGE_QUEUE
    #define MESSAGE_QUEUE
    #include <utils/Errors.h>
    #include <utils/Timers.h>
    #include <utils/threads.h>
    #define LOG_TAG "MessageQueue"
    #include <utils/Log.h>
    namespace android {
    template <class MessageType>
    class MessageQueue {
        // constructor / destructor
    public:
        MessageQueue(const char *name, // for debugging
                int numReply = 0) : // set numReply only if you need synchronous messages
            mName(name)
            ,mCount(0)
            ,mHead(0)
            ,mNumReply(numReply)
            ,mReplyMutex(NULL)
            ,mReplyCondition(NULL)
            ,mReplyStatus(NULL)
        {
            if (mNumReply > 0) {
                mReplyMutex = new Mutex[numReply];
                mReplyCondition = new Condition[numReply];
                mReplyStatus = new status_t[numReply];
            }
        }
        ~MessageQueue()
        {
            if (mNumReply > 0) {
                delete [] mReplyMutex;
                delete [] mReplyCondition;
                delete [] mReplyStatus;
            }
        }
        // public methods
    public:
        // Push a message onto the queue. If replyId is not -1 function will block until
        // the caller is signalled with a reply. Caller is unblocked when reply method is
        // called with the corresponding message id.
        status_t send(MessageType *msg, int replyId = -1)   //发送消息,replayId >0 实现同步通信,replayId<0,实现异步通信。
        {
            status_t status = NO_ERROR;
            // someone is misusing the API. replies have not been enabled
            if (replyId != -1 && mNumReply == 0) {
                LOGE("error: %s replies not enabled\n", mName);
                return BAD_VALUE;
            }
            mQueueMutex.lock();
            if (mCount < MESSAGE_QUEUE_SIZE) {
                int tail = (mHead + mCount) % MESSAGE_QUEUE_SIZE;
                circularQueue[tail] = *msg;
                mCount++;              //发送一次消息,增加一个消息数量
            } else {
                LOGE("error: %s message queue is full\n", mName);
                status = NOT_ENOUGH_DATA;
            }
            mQueueMutex.unlock();
            mQueueCondition.signal();
            if (replyId >= 0 && status == NO_ERROR) {   //replyId >= 0 实现同步通信,会一直等待mReplyCondition().
                                                          //replyId < 0 实现异步通信,不进入睡眠等待。
                mReplyCondition[replyId].wait(mReplyMutex[replyId]);
                status = mReplyStatus[replyId];
            }
            return status;
        }
        // Pop a message from the queue
        status_t receive(MessageType *msg)           //接收消息,
        {
            status_t status = NO_ERROR;
            mQueueMutex.lock();
            while (mCount == 0)
                mQueueCondition.wait(mQueueMutex);    //等待消息。
            *msg = circularQueue[mHead];
            mHead = (mHead + 1) % MESSAGE_QUEUE_SIZE;
            mCount--;                                  //接收一个消息,减少一个消息数量
            mQueueMutex.unlock();
            return status;
        }
        // Unblock the caller of send and indicate the status of the received message
        void reply(int replyId, status_t status)
        {
            mReplyStatus[replyId] = status;
            mReplyCondition[replyId].signal();                //回应消息
        }
        // Return true if the queue is empty
        inline bool isEmpty() { return mCount == 0; }
    private:
        static const int MESSAGE_QUEUE_SIZE = 32;
        const char *mName;
        Mutex mQueueMutex;
        Condition mQueueCondition;
        int mCount;
        int mHead;
        MessageType circularQueue[MESSAGE_QUEUE_SIZE];
        int mNumReply;
        Mutex *mReplyMutex;
        Condition *mReplyCondition;
        status_t *mReplyStatus;
        
    }; // class MessageQueue
    }; // namespace android
    #endif // MESSAGE_QUEUE


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值