Separate Simple Backend creation from initialization.
[chromium-blink-merge.git] / media / audio / cross_process_notification.h
blobcae74355a7b74bf5a9148294d5c5a59622cfef68
1 // Copyright (c) 2012 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.
5 #ifndef MEDIA_AUDIO_CROSS_PROCESS_NOTIFICATION_H_
6 #define MEDIA_AUDIO_CROSS_PROCESS_NOTIFICATION_H_
8 #include <vector>
10 #include "base/basictypes.h"
11 #include "base/process.h"
12 #include "base/threading/non_thread_safe.h"
13 #include "media/base/media_export.h"
15 #if defined(OS_WIN)
16 #include "base/win/scoped_handle.h"
17 #else
18 #include "base/file_descriptor_posix.h"
19 #include "base/sync_socket.h"
20 #endif
22 // A mechanism to synchronize access to a shared resource between two parties
23 // when the usage pattern resembles that of two players playing a game of chess.
24 // Each end has an instance of CrossProcessNotification and calls Signal() when
25 // it has finished using the shared resource.
26 // Before accessing the resource, it must call Wait() in order to know when the
27 // other end has called Signal().
29 // Here's some pseudo code for how this class can be used:
31 // This method is used by both processes as it's a general way to use the
32 // shared resource and then grant the privilege to the other process:
34 // void WriteToSharedMemory(CrossProcessNotification* notification,
35 // SharedMemory* mem,
36 // const char my_char) {
37 // notification->Wait(); // Wait for the other process to yield access.
38 // reinterpret_cast<char*>(mem->memory())[0] = my_char;
39 // notification->Signal(); // Grant the other process access.
40 // }
42 // Process A:
44 // class A {
45 // public:
46 // void Initialize(base::ProcessHandle process_b) {
47 // mem_.CreateNamed("foo", false, 1024);
49 // CrossProcessNotification other;
50 // CHECK(CrossProcessNotification::InitializePair(&notification_, &other));
51 // CrossProcessNotification::IPCHandle handle_1, handle_2;
52 // CHECK(other.ShareToProcess(process_b, &handle_1, &handle_2));
53 // // This could be implemented by using some IPC mechanism
54 // // such as MessageLoop.
55 // SendToProcessB(mem_, handle_1, handle_2);
56 // // Allow process B the first chance to write to the memory:
57 // notification_.Signal();
58 // // Once B is done, we'll write 'A' to the shared memory.
59 // WriteToSharedMemory(&notification_, &mem_, 'A');
60 // }
62 // CrossProcessNotification notification_;
63 // SharedMemory mem_;
64 // };
66 // Process B:
68 // class B {
69 // public:
70 // // Called when we receive the IPC message from A.
71 // void Initialize(SharedMemoryHandle mem,
72 // CrossProcessNotification::IPCHandle handle_1,
73 // CrossProcessNotification::IPCHandle handle_2) {
74 // mem_.reset(new SharedMemory(mem, false));
75 // notification_.reset(new CrossProcessNotification(handle_1, handle_2));
76 // WriteToSharedMemory(&notification_, &mem_, 'B');
77 // }
79 // CrossProcessNotification notification_;
80 // scoped_ptr<SharedMemory> mem_;
81 // };
83 class MEDIA_EXPORT CrossProcessNotification {
84 public:
85 #if defined(OS_WIN)
86 typedef HANDLE IPCHandle;
87 #else
88 typedef base::FileDescriptor IPCHandle;
89 #endif
91 typedef std::vector<CrossProcessNotification*> Notifications;
93 // Default ctor. Initializes a NULL notification. User must call
94 // InitializePair() to initialize the instance along with a connected one.
95 CrossProcessNotification();
97 // Ctor for the user that does not call InitializePair but instead receives
98 // handles from the one that did. These handles come from a call to
99 // ShareToProcess.
100 CrossProcessNotification(IPCHandle handle_1, IPCHandle handle_2);
101 ~CrossProcessNotification();
103 // Raises a signal that the shared resource now can be accessed by the other
104 // party.
105 // NOTE: Calling Signal() more than once without calling Wait() in between
106 // is not a supported scenario and will result in undefined behavior (and
107 // different depending on platform).
108 void Signal();
110 // Waits for the other party to finish using the shared resource.
111 // NOTE: As with Signal(), you must not call Wait() more than once without
112 // calling Signal() in between.
113 void Wait();
115 bool IsValid() const;
117 // Copies the internal handles to the output parameters, |handle_1| and
118 // |handle_2|. The operation can fail, so the caller must be prepared to
119 // handle that case.
120 bool ShareToProcess(base::ProcessHandle process, IPCHandle* handle_1,
121 IPCHandle* handle_2);
123 // Initializes a pair of CrossProcessNotification instances. Note that this
124 // can fail (e.g. due to EMFILE on Linux).
125 static bool InitializePair(CrossProcessNotification* a,
126 CrossProcessNotification* b);
128 // Use an instance of this class when you have to repeatedly wait for multiple
129 // notifications on the same thread. The class will store information about
130 // which notification was last signaled and try to distribute the signals so
131 // that all notifications get a chance to be processed in times of high load
132 // and a busy one won't starve the others.
133 // TODO(tommi): Support a way to abort the wait.
134 class MEDIA_EXPORT WaitForMultiple :
135 public NON_EXPORTED_BASE(base::NonThreadSafe) {
136 public:
137 // Caller must make sure that the lifetime of the array is greater than
138 // that of the WaitForMultiple instance.
139 explicit WaitForMultiple(const Notifications* notifications);
141 // Waits for any of the notifications to be signaled. Returns the 0 based
142 // index of a signaled notification.
143 int Wait();
145 // Call when the array changes. This should be called on the same thread
146 // as Wait() is called on and the array must never change while a Wait()
147 // is in progress.
148 void Reset(const Notifications* notifications);
150 private:
151 const Notifications* notifications_;
152 size_t wait_offset_;
155 private:
156 // Only called by the WaitForMultiple class. See documentation
157 // for WaitForMultiple and comments inside WaitMultiple for details.
158 static int WaitMultiple(const Notifications& notifications,
159 size_t wait_offset);
161 #if defined(OS_WIN)
162 base::win::ScopedHandle mine_;
163 base::win::ScopedHandle other_;
164 #else
165 typedef base::CancelableSyncSocket SocketClass;
166 SocketClass socket_;
167 #endif
169 DISALLOW_COPY_AND_ASSIGN(CrossProcessNotification);
172 #endif // MEDIA_AUDIO_CROSS_PROCESS_NOTIFICATION_H_