OLD | NEW |
---|---|
(Empty) | |
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. | |
4 | |
5 #ifndef MEDIA_AUDIO_SHARED_MEM_SYNCHRONIZER_H_ | |
6 #define MEDIA_AUDIO_SHARED_MEM_SYNCHRONIZER_H_ | |
7 | |
8 #include "base/basictypes.h" | |
9 #include "base/process.h" | |
10 #include "media/base/media_export.h" | |
11 | |
12 #if defined(OS_WIN) | |
13 #include "base/win/scoped_handle.h" | |
14 #else | |
15 #include "base/file_descriptor_posix.h" | |
16 #include "base/sync_socket.h" | |
17 #endif | |
18 | |
19 // A mechanism to synchronize access to a shared memory segment between | |
20 // two parties when the usage pattern resembles that of two players playing | |
21 // a game of chess. Each end has an instance of SharedMemSynchronizer and | |
22 // calls Signal() when it has finished reading from/writing to the shared | |
23 // memory section. Before accessing the memory, it must call Wait() in order | |
24 // to know when the other end has called Signal(). | |
25 // | |
26 // Here's some pseudo code for how this class can be used: | |
27 // | |
28 // This method is used by both processes as it's a general way to access the | |
29 // shared memory section, write to it and then grant the privilege to the | |
30 // other process: | |
31 // | |
32 // void WriteToSharedMemory(SharedMemSynchronizer* synchronizer, | |
33 // SharedMemory* mem, | |
34 // const char my_char) { | |
35 // synchronizer_->Wait(); // Wait for the other process to yield access. | |
Ami GONE FROM CHROMIUM
2012/03/08 17:04:36
underscores here and two lines lower are superfluo
tommi (sloooow) - chröme
2012/03/09 12:15:49
Done.
| |
36 // reinterpret_cast<char*>(mem->memory())[0] = my_char; | |
37 // synchronizer_.Signal(); // Grant the other process access. | |
38 // } | |
39 // | |
40 // Process A: | |
41 // | |
42 // class A { | |
43 // public: | |
44 // void Initialize(base::ProcessHandle process_b) { | |
45 // mem_.CreateNamed("foo", false, 1024); | |
46 // | |
47 // SharedMemSynchronizer b; | |
48 // SharedMemSynchronizer::InitializePair(&synchronizer_, &b); | |
Ami GONE FROM CHROMIUM
2012/03/09 16:36:47
No error handling
tommi (sloooow) - chröme
2012/03/13 12:26:13
It's in a more recent patch set. Basically just a
| |
49 // SharedMemSynchronizer::IPCHandle handle_1, handle_2; | |
50 // b.ShareToProcess(process_b, &handle_1, &handle_2); | |
Ami GONE FROM CHROMIUM
2012/03/09 16:36:47
No error handling
tommi (sloooow) - chröme
2012/03/13 12:26:13
ditto.
| |
51 // // This could be implemented by using some IPC mechanism | |
52 // // such as MessageLoop. | |
53 // SendToProcessB(mem_, handle_1, handle_2); | |
54 // // Allow process B the first chance to write to the memory: | |
55 // synchronizer_.Signal(); | |
56 // // Once B is done, we'll write 'A' to the shared memory. | |
57 // WriteToSharedMemory(&synchronizer_, &mem_, 'A'); | |
58 // } | |
59 // | |
60 // SharedMemSynchronizer synchronizer_; | |
61 // SharedMemory mem_; | |
62 // }; | |
63 // | |
64 // Process B: | |
65 // | |
66 // class B { | |
67 // public: | |
68 // // Called when we receive the IPC message from A. | |
69 // void Initialize(SharedMemoryHandle mem, | |
70 // SharedMemSynchronizer::IPCHandle handle_1, | |
71 // SharedMemSynchronizer::IPCHandle handle_2) { | |
72 // mem_.reset(new SharedMemory(mem, false)); | |
73 // synchronizer_.reset(new SharedMemSynchronizer(handle_1, handle_2)); | |
74 // WriteToSharedMemory(&synchronizer_, &mem_, 'B'); | |
75 // } | |
76 // | |
77 // SharedMemSynchronizer synchronizer_; | |
78 // scoped_ptr<SharedMemory> mem_; | |
79 // }; | |
80 // | |
81 class MEDIA_EXPORT SharedMemSynchronizer { | |
82 public: | |
83 #if defined(OS_WIN) | |
84 typedef HANDLE IPCHandle; | |
85 #else | |
86 typedef base::FileDescriptor IPCHandle; | |
87 #endif | |
88 | |
89 // Default ctor. Initializes a NULL synchronizer. User must call | |
90 // InitializePair() to initialize the instance along with a connected one. | |
91 SharedMemSynchronizer(); | |
92 | |
93 // Ctor for the user that does not call InitializePair but instead receives | |
94 // handles from the one that did. These handles come from a call to | |
95 // ShareToProcess. | |
96 SharedMemSynchronizer(IPCHandle handle_1, IPCHandle handle_2); | |
97 ~SharedMemSynchronizer(); | |
98 | |
99 // Raises a signal that the shared memory now can be accessed by the | |
100 // other party. | |
101 void Signal(); | |
102 | |
103 // Waits for the other party to finish using the shared memory. | |
104 void Wait(); | |
105 | |
106 bool IsValid() const; | |
107 | |
108 // Copies the internal handles to the output parameters, |handle_1| and | |
109 // |handle_2|. The operation can fail, so the caller must be prepared to | |
110 // handle that case. | |
Ami GONE FROM CHROMIUM
2012/03/08 17:04:36
the sample code above will be copy/pasted, so it s
tommi (sloooow) - chröme
2012/03/09 12:15:49
Done.
| |
111 bool ShareToProcess(base::ProcessHandle process, IPCHandle* handle_1, | |
112 IPCHandle* handle_2); | |
113 | |
114 // Initializes a pair of SharedMemSynchronizer instances. Note that this can | |
115 // fail (e.g. due to EMFILE on Linux), so the caller must handle that case. | |
116 static bool InitializePair(SharedMemSynchronizer* a, | |
117 SharedMemSynchronizer* b); | |
118 | |
119 // Use an instance of this class when you have to repeatedly wait | |
120 // for multiple instances of SharedMemSynchronizer on the same thread. | |
121 // The class will store information about which synchronizer was last signaled | |
122 // and try to distribute the signals so that all synchronizers get a chance to | |
123 // be processed in times of high load and a busy one won't starve the | |
124 // others. | |
125 // TODO(tommi): Support a way to abort the wait. | |
126 class MEDIA_EXPORT WaitForMultiple { | |
127 public: | |
128 WaitForMultiple(SharedMemSynchronizer* synchronizers, size_t count); | |
Ami GONE FROM CHROMIUM
2012/03/08 17:04:36
vector to replace the ptr+size?
tommi (sloooow) - chröme
2012/03/09 12:15:49
what's the benefit? vectors are more expensive.
Ami GONE FROM CHROMIUM
2012/03/09 16:36:47
The benefit is that it's more difficult to make pr
tommi (sloooow) - chröme
2012/03/13 12:26:13
Done. Changed to std::vector<SharedMemSynchronize
| |
129 | |
130 // Waits for any of the synchronizers to be signaled. Returns the 0 based | |
131 // index of a signaled synchronizer. | |
132 int Wait(); | |
133 | |
134 private: | |
135 SharedMemSynchronizer* synchronizers_; | |
136 size_t count_; | |
137 size_t last_; | |
138 }; | |
139 | |
140 private: | |
141 // Only called by the WaitForMultiple class. See documentation | |
142 // for WaitForMultiple and comments inside WaitMultiple for details. | |
143 static int WaitMultiple(SharedMemSynchronizer* synchronizers, size_t count, | |
144 size_t last_signaled); | |
145 | |
146 #if defined(OS_WIN) | |
147 base::win::ScopedHandle mine_; | |
148 base::win::ScopedHandle other_; | |
149 #else | |
150 typedef base::CancelableSyncSocket SocketClass; | |
151 SocketClass socket_; | |
152 #endif | |
153 | |
154 private: | |
155 DISALLOW_COPY_AND_ASSIGN(SharedMemSynchronizer); | |
156 }; | |
157 | |
158 #endif // MEDIA_AUDIO_SHARED_MEM_SYNCHRONIZER_H_ | |
OLD | NEW |