好 草 多线程处理
放代码:
class ThreadTest
{
public:
    ThreadTest()
{}
    
~ThreadTest(){}
    
void startup();
    
void addreq(int);

    
void _threadMain();
    
void _waitForNextRequest();
    
void _processNextRequest();

    
struct WorkerFunc OGRE_THREAD_WORKER_INHERIT
    
{
        ThreadTest
* mQueue;

        WorkerFunc(ThreadTest
* q) 
            : mQueue(q) 
{}

        
void operator()();

        
void run();
    }
;
    WorkerFunc
* mWorkerFunc;

    typedef std::deque
<int> RequestQueue;
    RequestQueue mRequestQueue;

    OGRE_MUTEX(mRequestMutex)
    OGRE_MUTEX(mProcessMutex)
    OGRE_MUTEX(mResponseMutex)
    OGRE_THREAD_SYNCHRONISER(mRequestCondition)

}
;

void ThreadTest::addreq(int i)
{
    OGRE_LOCK_MUTEX(mRequestMutex)
    mRequestQueue.push_back(i);
    OGRE_THREAD_NOTIFY_ONE(mRequestCondition)
}

void ThreadTest::startup()
{
    
int i=3;
    
while(i>0)
    
{
        mWorkerFunc 
= OGRE_NEW_T(WorkerFunc(this), MEMCATEGORY_GENERAL);
        OGRE_THREAD_CREATE(t, 
*mWorkerFunc);
        i
--;
    }


}

void ThreadTest::WorkerFunc::operator()()
{
    mQueue
->_threadMain();
}


void ThreadTest::WorkerFunc::run()
{
    mQueue
->_threadMain();
}

void ThreadTest::_threadMain()
{
    
while (true)
    
{
        _waitForNextRequest();
        _processNextRequest();
    }


}


void ThreadTest::_waitForNextRequest()
{
    OGRE_LOCK_MUTEX_NAMED(mRequestMutex, queueLock);
    
if (mRequestQueue.empty())
    
{
        OGRE_THREAD_WAIT(mRequestCondition, mRequestMutex, queueLock);
    }


}


void ThreadTest::_processNextRequest()
{
    OGRE_LOCK_MUTEX(mProcessMutex)
    
{
        OGRE_LOCK_MUTEX(mRequestMutex);
        
if (!mRequestQueue.empty())
        
{
            
int request = mRequestQueue.front();
            mRequestQueue.pop_front();
            cout
<<request<<endl;
        }

    }


}

当然 里面用到了一些ogre中的线程宏,展开也就是boost的线程api:
#define OGRE_LOCK_MUTEX(name) boost::recursive_mutex::scoped_lock ogrenameLock(name);
#define OGRE_LOCK_MUTEX_NAMED(mutexName, lockName) boost::recursive_mutex::scoped_lock lockName(mutexName);

#define OGRE_THREAD_WAIT(sync, mutex, lock) sync.wait(lock);
#define OGRE_THREAD_NOTIFY_ONE(sync) sync.notify_one();
#define OGRE_THREAD_NOTIFY_ALL(sync) sync.notify_all();

#define OGRE_THREAD_SYNCHRONISER(sync) boost::condition sync;

#define OGRE_MUTEX(name) mutable boost::recursive_mutex name;

#define OGRE_THREAD_WAIT(sync, mutex, lock) sync.wait(lock);

主线程不断调用addreq()来增加请求并通知线程后马上返回 线程在得到通知后从阻塞中醒来处理请求
OGRE_LOCK_MUTEX(name):就是在范围内只允许有一个线程进入
OGRE_THREAD_WAIT(mRequestCondition, mRequestMutex, queueLock):该宏会失去queueLock,阻塞当前线程直到被通知,在返回前取得queueLock
来看_waitForNextRequest()的代码:
_waitForNextRequest()
{
   OGRE_LOCK_MUTEX_NAMED(mRequestMutex, queueLock);
    if (mRequestQueue.empty())
    {
        OGRE_THREAD_WAIT(mRequestCondition, mRequestMutex, queueLock);
    }
}
首先取得范围锁queueLock,如果mRequestQueue为空,就等着,同时要注意,由于失去queueLock,其他线程会得到queueLock,并再次导致queueLock的变化
如果有三个线程,分别是1,2,3
假设线程1最先取得queueLock,然后被阻塞,同时线程2或者3会在线程1失去queueLock时取得queueLock,最终,三个线程都会被阻塞,queueLock为失去
继续往下走,假设这时主线程addreq(),那么有一个线程会被唤醒,同时得到queueLock,然后跳出该函数时,queueLock也随着超出范围变为失去,然后来看
下一个函数_processNextRequest()的代码:
_processNextRequest()
{
      Request* request = 0;
      {
          OGRE_LOCK_MUTEX(mRequestMutex)

          if (!mRequestQueue.empty())
          {
              request = mRequestQueue.front();
              mRequestQueue.pop_front();
          }
       }

       if (request)
       {
            processRequestResponse(request, false);
       }

}
函数内容改了下以看得更加清楚,函数取得mRequestMutex,当其队列非空时,从队列中弹出一个请求,随后丢失mRequestMutex,并处理request
在处理完request后,将结果放进一个响应队列中,主线程在其循环中将会看到,整个流程就是这样子
总结:请求队列要注意是否为空,由于有多个线程,需要将其设为阻塞并在需要时唤醒

posted on 2013-01-24 20:07 野猪红 阅读(399) 评论(0)  编辑 收藏 引用 所属分类: C/C++ STL Python Lua

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   博问   Chat2DB   管理