1// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef BASE_WIN_OBJECT_WATCHER_H_
6#define BASE_WIN_OBJECT_WATCHER_H_
7#pragma once
8
9#include <windows.h>
10
11#include "base/base_api.h"
12#include "base/message_loop.h"
13
14namespace base {
15namespace win {
16
17// A class that provides a means to asynchronously wait for a Windows object to
18// become signaled.  It is an abstraction around RegisterWaitForSingleObject
19// that provides a notification callback, OnObjectSignaled, that runs back on
20// the origin thread (i.e., the thread that called StartWatching).
21//
22// This class acts like a smart pointer such that when it goes out-of-scope,
23// UnregisterWaitEx is automatically called, and any in-flight notification is
24// suppressed.
25//
26// Typical usage:
27//
28//   class MyClass : public base::ObjectWatcher::Delegate {
29//    public:
30//     void DoStuffWhenSignaled(HANDLE object) {
31//       watcher_.StartWatching(object, this);
32//     }
33//     virtual void OnObjectSignaled(HANDLE object) {
34//       // OK, time to do stuff!
35//     }
36//    private:
37//     base::ObjectWatcher watcher_;
38//   };
39//
40// In the above example, MyClass wants to "do stuff" when object becomes
41// signaled.  ObjectWatcher makes this task easy.  When MyClass goes out of
42// scope, the watcher_ will be destroyed, and there is no need to worry about
43// OnObjectSignaled being called on a deleted MyClass pointer.  Easy!
44//
45class BASE_API ObjectWatcher : public MessageLoop::DestructionObserver {
46 public:
47  class Delegate {
48   public:
49    virtual ~Delegate() {}
50    // Called from the MessageLoop when a signaled object is detected.  To
51    // continue watching the object, AddWatch must be called again.
52    virtual void OnObjectSignaled(HANDLE object) = 0;
53  };
54
55  ObjectWatcher();
56  ~ObjectWatcher();
57
58  // When the object is signaled, the given delegate is notified on the thread
59  // where StartWatching is called.  The ObjectWatcher is not responsible for
60  // deleting the delegate.
61  //
62  // Returns true if the watch was started.  Otherwise, false is returned.
63  //
64  bool StartWatching(HANDLE object, Delegate* delegate);
65
66  // Stops watching.  Does nothing if the watch has already completed.  If the
67  // watch is still active, then it is canceled, and the associated delegate is
68  // not notified.
69  //
70  // Returns true if the watch was canceled.  Otherwise, false is returned.
71  //
72  bool StopWatching();
73
74  // Returns the handle of the object being watched, or NULL if the object
75  // watcher is stopped.
76  HANDLE GetWatchedObject();
77
78 private:
79  // Called on a background thread when done waiting.
80  static void CALLBACK DoneWaiting(void* param, BOOLEAN timed_out);
81
82  // MessageLoop::DestructionObserver implementation:
83  virtual void WillDestroyCurrentMessageLoop();
84
85  // Internal state.
86  struct Watch;
87  Watch* watch_;
88
89  DISALLOW_COPY_AND_ASSIGN(ObjectWatcher);
90};
91
92}  // namespace win
93}  // namespace base
94
95#endif  // BASE_OBJECT_WATCHER_H_
96