zoukankan      html  css  js  c++  java
  • RegisterWaitForSingleObject的使用

    参考:

    5天不再惧怕多线程——第五天 线程池

    ThreadPool基础之RegisterWaitForSingleObject

    意图:可控制的线程池

    贴一段chrome的封装代码

    // Copyright (c) 2012 The Chromium Authors. All rights reserved.
    // Use of this source code is governed by a BSD-style license that can be
    // found in the LICENSE file.
    
    #include "base/win/object_watcher.h"
    
    #include "base/bind.h"
    #include "base/logging.h"
    
    namespace base {
    namespace win {
    
    //-----------------------------------------------------------------------------
    
    ObjectWatcher::ObjectWatcher()
        : weak_factory_(this),
          object_(NULL),
          wait_object_(NULL),
          origin_loop_(NULL) {
    }
    
    ObjectWatcher::~ObjectWatcher() {
      StopWatching();
    }
    
    bool ObjectWatcher::StartWatching(HANDLE object, Delegate* delegate) {
      CHECK(delegate);
      if (wait_object_) {
        NOTREACHED() << "Already watching an object";
        return false;
      }
    
      // Since our job is to just notice when an object is signaled and report the
      // result back to this thread, we can just run on a Windows wait thread.
      DWORD wait_flags = WT_EXECUTEINWAITTHREAD | WT_EXECUTEONLYONCE;
    
      // DoneWaiting can be synchronously called from RegisterWaitForSingleObject,
      // so set up all state now.
      callback_ = base::Bind(&ObjectWatcher::Signal, weak_factory_.GetWeakPtr(),
                             delegate);
      object_ = object;
      origin_loop_ = MessageLoop::current();
    
      if (!RegisterWaitForSingleObject(&wait_object_, object, DoneWaiting,
                                       this, INFINITE, wait_flags)) {
        NOTREACHED() << "RegisterWaitForSingleObject failed: " << GetLastError();
        object_ = NULL;
        wait_object_ = NULL;
        return false;
      }
    
      // We need to know if the current message loop is going away so we can
      // prevent the wait thread from trying to access a dead message loop.
      MessageLoop::current()->AddDestructionObserver(this);
      return true;
    }
    
    bool ObjectWatcher::StopWatching() {
      if (!wait_object_)
        return false;
    
      // Make sure ObjectWatcher is used in a single-threaded fashion.
      DCHECK(origin_loop_ == MessageLoop::current());
    
      // Blocking call to cancel the wait. Any callbacks already in progress will
      // finish before we return from this call.
      if (!UnregisterWaitEx(wait_object_, INVALID_HANDLE_VALUE)) {
        NOTREACHED() << "UnregisterWaitEx failed: " << GetLastError();
        return false;
      }
    
      weak_factory_.InvalidateWeakPtrs();
      object_ = NULL;
      wait_object_ = NULL;
    
      MessageLoop::current()->RemoveDestructionObserver(this);
      return true;
    }
    
    HANDLE ObjectWatcher::GetWatchedObject() {
      return object_;
    }
    
    // static
    void CALLBACK ObjectWatcher::DoneWaiting(void* param, BOOLEAN timed_out) {
      DCHECK(!timed_out);
    
      // The destructor blocks on any callbacks that are in flight, so we know that
      // that is always a pointer to a valid ObjectWater.
      ObjectWatcher* that = static_cast<ObjectWatcher*>(param);
      that->origin_loop_->PostTask(FROM_HERE, that->callback_);
      that->callback_.Reset();
    }
    
    void ObjectWatcher::Signal(Delegate* delegate) {
      // Signaling the delegate may result in our destruction or a nested call to
      // StartWatching(). As a result, we save any state we need and clear previous
      // watcher state before signaling the delegate.
      HANDLE object = object_;
      StopWatching();
      delegate->OnObjectSignaled(object);
    }
    
    void ObjectWatcher::WillDestroyCurrentMessageLoop() {
      // Need to shutdown the watch so that we don't try to access the MessageLoop
      // after this point.
      StopWatching();
    }
    
    }  // namespace win
    }  // namespace base
    
    

    测试代码:

    // Copyright (c) 2011 The Chromium Authors. All rights reserved.
    // Use of this source code is governed by a BSD-style license that can be
    // found in the LICENSE file.
    
    #include <process.h>
    
    #include "base/message_loop.h"
    #include "base/win/object_watcher.h"
    #include "testing/gtest/include/gtest/gtest.h"
    
    namespace base {
    namespace win {
    
    namespace {
    
    class QuitDelegate : public ObjectWatcher::Delegate {
     public:
      virtual void OnObjectSignaled(HANDLE object) {
        MessageLoop::current()->Quit();
      }
    };
    
    class DecrementCountDelegate : public ObjectWatcher::Delegate {
     public:
      explicit DecrementCountDelegate(int* counter) : counter_(counter) {
      }
      virtual void OnObjectSignaled(HANDLE object) {
        --(*counter_);
      }
     private:
      int* counter_;
    };
    
    void RunTest_BasicSignal(MessageLoop::Type message_loop_type) {
      MessageLoop message_loop(message_loop_type);
    
      ObjectWatcher watcher;
      EXPECT_EQ(NULL, watcher.GetWatchedObject());
    
      // A manual-reset event that is not yet signaled.
      HANDLE event = CreateEvent(NULL, TRUE, FALSE, NULL);
    
      QuitDelegate delegate;
      bool ok = watcher.StartWatching(event, &delegate);
      EXPECT_TRUE(ok);
      EXPECT_EQ(event, watcher.GetWatchedObject());
    
      SetEvent(event);
    
      MessageLoop::current()->Run();
    
      EXPECT_EQ(NULL, watcher.GetWatchedObject());
      CloseHandle(event);
    }
    
    void RunTest_BasicCancel(MessageLoop::Type message_loop_type) {
      MessageLoop message_loop(message_loop_type);
    
      ObjectWatcher watcher;
    
      // A manual-reset event that is not yet signaled.
      HANDLE event = CreateEvent(NULL, TRUE, FALSE, NULL);
    
      QuitDelegate delegate;
      bool ok = watcher.StartWatching(event, &delegate);
      EXPECT_TRUE(ok);
    
      watcher.StopWatching();
    
      CloseHandle(event);
    }
    
    
    void RunTest_CancelAfterSet(MessageLoop::Type message_loop_type) {
      MessageLoop message_loop(message_loop_type);
    
      ObjectWatcher watcher;
    
      int counter = 1;
      DecrementCountDelegate delegate(&counter);
    
        // A manual-reset event that is not yet signaled.
      HANDLE event = CreateEvent(NULL, TRUE, FALSE, NULL);
    
      bool ok = watcher.StartWatching(event, &delegate);
      EXPECT_TRUE(ok);
    
      SetEvent(event);
    
      // Let the background thread do its business
      Sleep(30);
    
      watcher.StopWatching();
    
      MessageLoop::current()->RunAllPending();
    
      // Our delegate should not have fired.
      EXPECT_EQ(1, counter);
    
      CloseHandle(event);
    }
    
    void RunTest_OutlivesMessageLoop(MessageLoop::Type message_loop_type) {
      // Simulate a MessageLoop that dies before an ObjectWatcher.  This ordinarily
      // doesn't happen when people use the Thread class, but it can happen when
      // people use the Singleton pattern or atexit.
      HANDLE event = CreateEvent(NULL, TRUE, FALSE, NULL);  // not signaled
      {
        ObjectWatcher watcher;
        {
          MessageLoop message_loop(message_loop_type);
    
          QuitDelegate delegate;
          watcher.StartWatching(event, &delegate);
        }
      }
      CloseHandle(event);
    }
    
    }  // namespace
    
    //-----------------------------------------------------------------------------
    
    TEST(ObjectWatcherTest, BasicSignal) {
      RunTest_BasicSignal(MessageLoop::TYPE_DEFAULT);
      RunTest_BasicSignal(MessageLoop::TYPE_IO);
      RunTest_BasicSignal(MessageLoop::TYPE_UI);
    }
    
    TEST(ObjectWatcherTest, BasicCancel) {
      RunTest_BasicCancel(MessageLoop::TYPE_DEFAULT);
      RunTest_BasicCancel(MessageLoop::TYPE_IO);
      RunTest_BasicCancel(MessageLoop::TYPE_UI);
    }
    
    TEST(ObjectWatcherTest, CancelAfterSet) {
      RunTest_CancelAfterSet(MessageLoop::TYPE_DEFAULT);
      RunTest_CancelAfterSet(MessageLoop::TYPE_IO);
      RunTest_CancelAfterSet(MessageLoop::TYPE_UI);
    }
    
    TEST(ObjectWatcherTest, OutlivesMessageLoop) {
      RunTest_OutlivesMessageLoop(MessageLoop::TYPE_DEFAULT);
      RunTest_OutlivesMessageLoop(MessageLoop::TYPE_IO);
      RunTest_OutlivesMessageLoop(MessageLoop::TYPE_UI);
    }
    
    }  // namespace win
    }  // namespace base
    
    
  • 相关阅读:
    【pygame游戏编程】第二篇-----移动图像
    【pygame游戏编程】第五篇-----动画显示
    【pygame游戏编程】第四篇-----打字测速游戏
    【pygame游戏编程】第一篇-----创建一个窗口
    pygame编程之font模块
    pygame编组(精灵组)Group中的常用方法介绍
    javascript遍历对象的属性
    Spring中的@ImportResource
    SpringBoot中的@ConfigurationProperties
    开源协议是什么?有哪些?如何选择?
  • 原文地址:https://www.cnblogs.com/Clingingboy/p/2956245.html
Copyright © 2011-2022 走看看