google base库中的WaitableEvent

这个类说白了就是对windows event的封装,没有什么特别的,常规做法,等侍另一线程无非就是等侍事件置信waitsingleobject,通知事件无非就是setevent,一看就明白,不就详解,写在这里只是为了这个系更的完整性

下边的示例代码注意下:

  //   WaitableEvent *e = new WaitableEvent;
  //   SendToOtherThread(e);
  //   e->Wait();
  //   delete e;

   SendToOtherThread(e); 这个应当就是开启另外一个线程什么的,然后将事件传递过去,然后等侍事情做完以后再继续,这是这样写的话还不如将要写的代码写在当前线程,看来还没明白它的深意,具体用在什么样的场景比较好

// 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.

#ifndef BASE_SYNCHRONIZATION_WAITABLE_EVENT_H_
#define BASE_SYNCHRONIZATION_WAITABLE_EVENT_H_

#include "base/base_export.h"
#include "base/basictypes.h"

#if defined(OS_WIN)
#include <windows.h>
#endif

#if defined(OS_POSIX)
#include <list>
#include <utility>
#include "base/memory/ref_counted.h"
#include "base/synchronization/lock.h"
#endif

namespace base {

// This replaces INFINITE from Win32
static const int kNoTimeout = -1;

class TimeDelta;

// A WaitableEvent can be a useful thread synchronization tool when you want to
// allow one thread to wait for another thread to finish some work. For
// non-Windows systems, this can only be used from within a single address
// space.
//
// Use a WaitableEvent when you would otherwise use a Lock+ConditionVariable to
// protect a simple boolean value.  However, if you find yourself using a
// WaitableEvent in conjunction with a Lock to wait for a more complex state
// change (e.g., for an item to be added to a queue), then you should probably
// be using a ConditionVariable instead of a WaitableEvent.
//
// NOTE: On Windows, this class provides a subset of the functionality afforded
// by a Windows event object.  This is intentional.  If you are writing Windows
// specific code and you need other features of a Windows event, then you might
// be better off just using an Windows event directly.
class BASE_EXPORT WaitableEvent {
 public:
  // If manual_reset is true, then to set the event state to non-signaled, a
  // consumer must call the Reset method.  If this parameter is false, then the
  // system automatically resets the event state to non-signaled after a single
  // waiting thread has been released.
  WaitableEvent(bool manual_reset, bool initially_signaled);

#if defined(OS_WIN)
  // Create a WaitableEvent from an Event HANDLE which has already been
  // created. This objects takes ownership of the HANDLE and will close it when
  // deleted.
  explicit WaitableEvent(HANDLE event_handle);

  // Releases ownership of the handle from this object.
  HANDLE Release();
#endif

  ~WaitableEvent();

  // Put the event in the un-signaled state.
  void Reset();

  // Put the event in the signaled state.  Causing any thread blocked on Wait
  // to be woken up.
  void Signal();

  // Returns true if the event is in the signaled state, else false.  If this
  // is not a manual reset event, then this test will cause a reset.
  bool IsSignaled();

  // Wait indefinitely for the event to be signaled. Wait‘s return "happens
  // after" |Signal| has completed. This means that it‘s safe for a
  // WaitableEvent to synchronise its own destruction, like this:
  //
  //   WaitableEvent *e = new WaitableEvent;
  //   SendToOtherThread(e);
  //   e->Wait();
  //   delete e;
  void Wait();

  // Wait up until max_time has passed for the event to be signaled.  Returns
  // true if the event was signaled.  If this method returns false, then it
  // does not necessarily mean that max_time was exceeded.
  //
  // TimedWait can synchronise its own destruction like |Wait|.
  bool TimedWait(const TimeDelta& max_time);

#if defined(OS_WIN)
  HANDLE handle() const { return handle_; }
#endif

  // Wait, synchronously, on multiple events.
  //   waitables: an array of WaitableEvent pointers
  //   count: the number of elements in @waitables
  //
  // returns: the index of a WaitableEvent which has been signaled.
  //
  // You MUST NOT delete any of the WaitableEvent objects while this wait is
  // happening, however WaitMany‘s return "happens after" the |Signal| call
  // that caused it has completed, like |Wait|.
  static size_t WaitMany(WaitableEvent** waitables, size_t count);

  // For asynchronous waiting, see WaitableEventWatcher

  // This is a private helper class. It‘s here because it‘s used by friends of
  // this class (such as WaitableEventWatcher) to be able to enqueue elements
  // of the wait-list
  class Waiter {
   public:
    // Signal the waiter to wake up.
    //
    // Consider the case of a Waiter which is in multiple WaitableEvent‘s
    // wait-lists. Each WaitableEvent is automatic-reset and two of them are
    // signaled at the same time. Now, each will wake only the first waiter in
    // the wake-list before resetting. However, if those two waiters happen to
    // be the same object (as can happen if another thread didn‘t have a chance
    // to dequeue the waiter from the other wait-list in time), two auto-resets
    // will have happened, but only one waiter has been signaled!
    //
    // Because of this, a Waiter may "reject" a wake by returning false. In
    // this case, the auto-reset WaitableEvent shouldn‘t act as if anything has
    // been notified.
    virtual bool Fire(WaitableEvent* signaling_event) = 0;

    // Waiters may implement this in order to provide an extra condition for
    // two Waiters to be considered equal. In WaitableEvent::Dequeue, if the
    // pointers match then this function is called as a final check. See the
    // comments in ~Handle for why.
    virtual bool Compare(void* tag) = 0;

   protected:
    virtual ~Waiter() {}
  };

 private:
  friend class WaitableEventWatcher;

#if defined(OS_WIN)
  HANDLE handle_;
#else
  // On Windows, one can close a HANDLE which is currently being waited on. The
  // MSDN documentation says that the resulting behaviour is ‘undefined‘, but
  // it doesn‘t crash. However, if we were to include the following members
  // directly then, on POSIX, one couldn‘t use WaitableEventWatcher to watch an
  // event which gets deleted. This mismatch has bitten us several times now,
  // so we have a kernel of the WaitableEvent, which is reference counted.
  // WaitableEventWatchers may then take a reference and thus match the Windows
  // behaviour.
  struct WaitableEventKernel :
      public RefCountedThreadSafe<WaitableEventKernel> {
   public:
    WaitableEventKernel(bool manual_reset, bool initially_signaled);

    bool Dequeue(Waiter* waiter, void* tag);

    base::Lock lock_;
    const bool manual_reset_;
    bool signaled_;
    std::list<Waiter*> waiters_;

   private:
    friend class RefCountedThreadSafe<WaitableEventKernel>;
    ~WaitableEventKernel();
  };

  typedef std::pair<WaitableEvent*, size_t> WaiterAndIndex;

  // When dealing with arrays of WaitableEvent*, we want to sort by the address
  // of the WaitableEvent in order to have a globally consistent locking order.
  // In that case we keep them, in sorted order, in an array of pairs where the
  // second element is the index of the WaitableEvent in the original,
  // unsorted, array.
  static size_t EnqueueMany(WaiterAndIndex* waitables,
                            size_t count, Waiter* waiter);

  bool SignalAll();
  bool SignalOne();
  void Enqueue(Waiter* waiter);

  scoped_refptr<WaitableEventKernel> kernel_;
#endif

  DISALLOW_COPY_AND_ASSIGN(WaitableEvent);
};

}  // namespace base

#endif  // BASE_SYNCHRONIZATION_WAITABLE_EVENT_H_

  

时间: 2024-10-25 02:13:05

google base库中的WaitableEvent的相关文章

google base库之simplethread

// This is the base SimpleThread. You can derive from it and implement the // virtual Run method, or you can use the DelegateSimpleThread interface. class BASE_EXPORT SimpleThread : public PlatformThread::Delegate { public: class BASE_EXPORT Options

google base 之MessagePumpForUI

base库中比较有意思就是这个类了,如同很多界面库一样,创建了一个隐藏窗口来处理需要在界面线程处理的消息,大体原理也就是需要执行task的时候发送一个自定义的消息,当窗口接收到task的时候调用保存起来的回调函数,还有的是通过把回调放在消息结构体里面 自下义的消息 // Message sent to get an additional time slice for pumping (processing) another // task (a series of such messages c

VS2015--win32工程配置的一些想法之Google Code Style中头文件的顺序

工程大了,有很多的头文件,也要引用很多的库文件. 从我们学习C++写hello world的那一刻起,就知道要包含一些系统文件. 那么顺序如何呢? 在review的时候,感觉自己写的东西就是一坨屎. 看看Google code style中是如何描述include文件顺序的: Names and Order of Includes Use standard order for readability and to avoid hidden dependencies: C library, C++

[C++11笔记001]修改通用库中的XDynamicArray,使它可以支持C++11的初始化列表和for循环

今天,有空翻了一下<C++Primer plus(第六版)>,看到里面有介绍新的for循环和初始化列表,但是我实现的动态数组XDynamicArray不支持这些新特性,没办法,只好进行改造了. 首先是for循环,如下面的样式 for(auto e:stList) { cout<<e<<endl; } 是于就各种google,和查找C++11的array的源代码,总结:就是提供一个标准的iterator和begin,end这两个方法,就可以了. 是于定义了一个iterat

第一个lucene程序,把一个信息写入到索引库中、根据关键词把对象从索引库中提取出来、lucene读写过程分析

新建一个Java Project :LunceneTest 准备lucene的jar包,要加入的jar包至少有: 1)lucene-core-3.1.0.jar     (核心包) 2) lucene-analyzers-3.1.0.jar    (分词器) 3) lucene-highlighter-3.1.0.jar    (高亮器) 4) lucene-memory-3.1.0.jar       (高亮器) 新建实体类:Article, 属性:id,title,content; gett

SVN Error: “&#39; &#39;x&#39; isn&#39;t in the same repository as &#39;y&#39; ” during merge (并不在同一个版本库中)

在使用svn merge命令报错 英文版本:SVN Error: “' 'x' isn't in the same repository as 'y' ” during merge 中文版本报错:并不在同一个版本库中 如果你使用的是中文版本,那你就悲剧了,跟我一样,Google.百度都搜不到答案 不过现在不用担心,我费劲九牛二虎之力找到答案了,非常恶心的一个小问题: Questions: I get the error svn: 'x' isn't in the same repository

从tlb,ocx,dll类型库中提取com组件的CLSID

最近在做项目的时候遇到了这个问题. 项目需要动态根据添加com组件,获取组件的某个接口函数.   一般情况下,我们创建com组件的方法是根据它的CLSID号,获得相应的interface,然后通过返回的指针调用相应的接口函数.如下: CoInitialize( NULL ); IpTest* pMask = NULL; HRESULT hr = CoCreateInstance( CLSID_TEST, NULL, CLSCTX_INPROC, IID_ITEST, (LPVOID*)&IpTe

结构体在固件库中的应用

上次介绍了一般结构体的定义以及引用方法,那么接下来将对结构体在官方固件库是如何具体使用的做出简单说明. 结构体指针成员变量引用方法是通过“→”符号来实现,比如要访问student1结构体指针指向的结构体的成员变量name,那么方法是: stuednt1—>name; 如在STM32官方固件库中对端口使用模式结构体定义如下: typedef enum { GPIO_Mode_AIN = 0x0, //模拟输入模式 GPIO_Mode_IN_FLOATING = 0x04, //浮空输入模式 GPI

Google”在垃圾中寻找黄金“——Page-Rank

GOOGLE"在垃圾中寻找黄金"--Page Rank GOOGLE"在垃圾中寻找黄金"--Page Rank 1.Google的低成本之道 ○不使用超级计算机,不使用存储(淘宝的去i,去e,去o之路) ○大量使用普通的PC服务器(去掉机箱,外设,硬盘),提供有冗余的集群服务 ○全世界多个数据中心,有些附带发电厂 ○运营商向Google倒付费 2.Google面对的数据和计算难题 大量的网页如何存储? Google的爬虫每天在全世界各个服务器里面爬到的很多网页,这些