summaryrefslogtreecommitdiffstats
path: root/mojo
diff options
context:
space:
mode:
authorviettrungluu@chromium.org <viettrungluu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-06-12 16:31:16 +0000
committerviettrungluu@chromium.org <viettrungluu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-06-12 16:31:16 +0000
commit22184780a9a695c2e9b1f5dc600598627ea32a33 (patch)
tree45f3e863cb98470f7ebc679261a1d9b1674b8441 /mojo
parentb93e93b9f04ac8167e52211fe33a3e4b6d752030 (diff)
downloadchromium_src-22184780a9a695c2e9b1f5dc600598627ea32a33.zip
chromium_src-22184780a9a695c2e9b1f5dc600598627ea32a33.tar.gz
chromium_src-22184780a9a695c2e9b1f5dc600598627ea32a33.tar.bz2
Mojo: Wrap the satisfied/unsatisfied wait flags state in a single object.
First, add a struct (MojoWaitFlagsState) to the public C API. We'll use this to report additional (e.g., per-handle) information in MojoWait()/MojoWaitMany(). Second, make a subclass struct (mojo::system::WaitFlagsState) that adds a constructor and some simple methods for convenience (but adding no overhead). Third, convert our various separate handling of satisfied/satisfiable state to use the new combined struct. R=sky@chromium.org, darin@chromium.org Review URL: https://codereview.chromium.org/325213004 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@276708 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'mojo')
-rw-r--r--mojo/mojo.gyp1
-rw-r--r--mojo/public/c/system/types.h13
-rw-r--r--mojo/system/data_pipe.cc44
-rw-r--r--mojo/system/data_pipe.h7
-rw-r--r--mojo/system/local_data_pipe.cc41
-rw-r--r--mojo/system/local_data_pipe.h6
-rw-r--r--mojo/system/local_message_pipe_endpoint.cc54
-rw-r--r--mojo/system/local_message_pipe_endpoint.h4
-rw-r--r--mojo/system/platform_handle_dispatcher.cc8
-rw-r--r--mojo/system/platform_handle_dispatcher.h5
-rw-r--r--mojo/system/shared_buffer_dispatcher.cc9
-rw-r--r--mojo/system/shared_buffer_dispatcher.h5
-rw-r--r--mojo/system/simple_dispatcher.cc10
-rw-r--r--mojo/system/simple_dispatcher.h18
-rw-r--r--mojo/system/simple_dispatcher_unittest.cc40
-rw-r--r--mojo/system/wait_flags_state.h48
-rw-r--r--mojo/system/waiter_list.cc12
-rw-r--r--mojo/system/waiter_list.h3
-rw-r--r--mojo/system/waiter_list_unittest.cc53
19 files changed, 216 insertions, 165 deletions
diff --git a/mojo/mojo.gyp b/mojo/mojo.gyp
index ab0ef19..6bbe32f 100644
--- a/mojo/mojo.gyp
+++ b/mojo/mojo.gyp
@@ -216,6 +216,7 @@
'system/simple_dispatcher.h',
'system/transport_data.cc',
'system/transport_data.h',
+ 'system/wait_flags_state.h',
'system/waiter.cc',
'system/waiter.h',
'system/waiter_list.cc',
diff --git a/mojo/public/c/system/types.h b/mojo/public/c/system/types.h
index da4577a..655e302 100644
--- a/mojo/public/c/system/types.h
+++ b/mojo/public/c/system/types.h
@@ -12,6 +12,8 @@
#include <stdint.h>
+#include "mojo/public/c/system/macros.h"
+
// TODO(vtl): Notes: Use of undefined flags will lead to undefined behavior
// (typically they'll be ignored), not necessarily an error.
@@ -162,4 +164,15 @@ const MojoWaitFlags MOJO_WAIT_FLAG_EVERYTHING = ~0;
#define MOJO_WAIT_FLAG_EVERYTHING (~((MojoWaitFlags) 0))
#endif
+// TODO(vtl): Add out parameters with this to MojoWait/MojoWaitMany.
+// Note: This struct is not extensible (and only has 32-bit quantities), so it's
+// 32-bit-aligned.
+MOJO_COMPILE_ASSERT(MOJO_ALIGNOF(int32_t) == 4, int32_t_has_weird_alignment);
+struct MOJO_ALIGNAS(4) MojoWaitFlagsState {
+ MojoWaitFlags satisfied_flags;
+ MojoWaitFlags satisfiable_flags;
+};
+MOJO_COMPILE_ASSERT(sizeof(MojoWaitFlagsState) == 8,
+ MojoWaitFlagsState_has_wrong_size);
+
#endif // MOJO_PUBLIC_C_SYSTEM_TYPES_H_
diff --git a/mojo/system/data_pipe.cc b/mojo/system/data_pipe.cc
index 7f05c04..2af15be 100644
--- a/mojo/system/data_pipe.cc
+++ b/mojo/system/data_pipe.cc
@@ -111,9 +111,10 @@ MojoResult DataPipe::ProducerWriteData(const void* elements,
if (*num_bytes == 0)
return MOJO_RESULT_OK; // Nothing to do.
- MojoWaitFlags old_consumer_satisfied_flags = ConsumerSatisfiedFlagsNoLock();
+ WaitFlagsState old_consumer_state = ConsumerGetWaitFlagsStateNoLock();
MojoResult rv = ProducerWriteDataImplNoLock(elements, num_bytes, all_or_none);
- if (ConsumerSatisfiedFlagsNoLock() != old_consumer_satisfied_flags)
+ WaitFlagsState new_consumer_state = ConsumerGetWaitFlagsStateNoLock();
+ if (!new_consumer_state.equals(old_consumer_state))
AwakeConsumerWaitersForStateChangeNoLock();
return rv;
}
@@ -153,7 +154,7 @@ MojoResult DataPipe::ProducerEndWriteData(uint32_t num_bytes_written) {
// Note: Allow successful completion of the two-phase write even if the
// consumer has been closed.
- MojoWaitFlags old_consumer_satisfied_flags = ConsumerSatisfiedFlagsNoLock();
+ WaitFlagsState old_consumer_state = ConsumerGetWaitFlagsStateNoLock();
MojoResult rv;
if (num_bytes_written > producer_two_phase_max_num_bytes_written_ ||
num_bytes_written % element_num_bytes_ != 0) {
@@ -166,9 +167,10 @@ MojoResult DataPipe::ProducerEndWriteData(uint32_t num_bytes_written) {
DCHECK(!producer_in_two_phase_write_no_lock());
// If we're now writable, we *became* writable (since we weren't writable
// during the two-phase write), so awake producer waiters.
- if ((ProducerSatisfiedFlagsNoLock() & MOJO_WAIT_FLAG_WRITABLE))
+ if (ProducerGetWaitFlagsStateNoLock().satisfies(MOJO_WAIT_FLAG_WRITABLE))
AwakeProducerWaitersForStateChangeNoLock();
- if (ConsumerSatisfiedFlagsNoLock() != old_consumer_satisfied_flags)
+ WaitFlagsState new_consumer_state = ConsumerGetWaitFlagsStateNoLock();
+ if (!new_consumer_state.equals(old_consumer_state))
AwakeConsumerWaitersForStateChangeNoLock();
return rv;
}
@@ -179,9 +181,10 @@ MojoResult DataPipe::ProducerAddWaiter(Waiter* waiter,
base::AutoLock locker(lock_);
DCHECK(has_local_producer_no_lock());
- if ((flags & ProducerSatisfiedFlagsNoLock()))
+ WaitFlagsState producer_state = ProducerGetWaitFlagsStateNoLock();
+ if (producer_state.satisfies(flags))
return MOJO_RESULT_ALREADY_EXISTS;
- if (!(flags & ProducerSatisfiableFlagsNoLock()))
+ if (!producer_state.can_satisfy(flags))
return MOJO_RESULT_FAILED_PRECONDITION;
producer_waiter_list_->AddWaiter(waiter, flags, wake_result);
@@ -234,9 +237,10 @@ MojoResult DataPipe::ConsumerReadData(void* elements,
if (*num_bytes == 0)
return MOJO_RESULT_OK; // Nothing to do.
- MojoWaitFlags old_producer_satisfied_flags = ProducerSatisfiedFlagsNoLock();
+ WaitFlagsState old_producer_state = ProducerGetWaitFlagsStateNoLock();
MojoResult rv = ConsumerReadDataImplNoLock(elements, num_bytes, all_or_none);
- if (ProducerSatisfiedFlagsNoLock() != old_producer_satisfied_flags)
+ WaitFlagsState new_producer_state = ProducerGetWaitFlagsStateNoLock();
+ if (!new_producer_state.equals(old_producer_state))
AwakeProducerWaitersForStateChangeNoLock();
return rv;
}
@@ -255,9 +259,10 @@ MojoResult DataPipe::ConsumerDiscardData(uint32_t* num_bytes,
if (*num_bytes == 0)
return MOJO_RESULT_OK; // Nothing to do.
- MojoWaitFlags old_producer_satisfied_flags = ProducerSatisfiedFlagsNoLock();
+ WaitFlagsState old_producer_state = ProducerGetWaitFlagsStateNoLock();
MojoResult rv = ConsumerDiscardDataImplNoLock(num_bytes, all_or_none);
- if (ProducerSatisfiedFlagsNoLock() != old_producer_satisfied_flags)
+ WaitFlagsState new_producer_state = ProducerGetWaitFlagsStateNoLock();
+ if (!new_producer_state.equals(old_producer_state))
AwakeProducerWaitersForStateChangeNoLock();
return rv;
}
@@ -300,7 +305,7 @@ MojoResult DataPipe::ConsumerEndReadData(uint32_t num_bytes_read) {
if (!consumer_in_two_phase_read_no_lock())
return MOJO_RESULT_FAILED_PRECONDITION;
- MojoWaitFlags old_producer_satisfied_flags = ProducerSatisfiedFlagsNoLock();
+ WaitFlagsState old_producer_state = ProducerGetWaitFlagsStateNoLock();
MojoResult rv;
if (num_bytes_read > consumer_two_phase_max_num_bytes_read_ ||
num_bytes_read % element_num_bytes_ != 0) {
@@ -313,9 +318,11 @@ MojoResult DataPipe::ConsumerEndReadData(uint32_t num_bytes_read) {
DCHECK(!consumer_in_two_phase_read_no_lock());
// If we're now readable, we *became* readable (since we weren't readable
// during the two-phase read), so awake consumer waiters.
- if ((ConsumerSatisfiedFlagsNoLock() & MOJO_WAIT_FLAG_READABLE))
+ WaitFlagsState new_consumer_state = ConsumerGetWaitFlagsStateNoLock();
+ if (new_consumer_state.satisfies(MOJO_WAIT_FLAG_READABLE))
AwakeConsumerWaitersForStateChangeNoLock();
- if (ProducerSatisfiedFlagsNoLock() != old_producer_satisfied_flags)
+ WaitFlagsState new_producer_state = ProducerGetWaitFlagsStateNoLock();
+ if (!new_producer_state.equals(old_producer_state))
AwakeProducerWaitersForStateChangeNoLock();
return rv;
}
@@ -326,9 +333,10 @@ MojoResult DataPipe::ConsumerAddWaiter(Waiter* waiter,
base::AutoLock locker(lock_);
DCHECK(has_local_consumer_no_lock());
- if ((flags & ConsumerSatisfiedFlagsNoLock()))
+ WaitFlagsState consumer_state = ConsumerGetWaitFlagsStateNoLock();
+ if (consumer_state.satisfies(flags))
return MOJO_RESULT_ALREADY_EXISTS;
- if (!(flags & ConsumerSatisfiableFlagsNoLock()))
+ if (!consumer_state.can_satisfy(flags))
return MOJO_RESULT_FAILED_PRECONDITION;
consumer_waiter_list_->AddWaiter(waiter, flags, wake_result);
@@ -377,7 +385,7 @@ void DataPipe::AwakeProducerWaitersForStateChangeNoLock() {
if (!has_local_producer_no_lock())
return;
producer_waiter_list_->AwakeWaitersForStateChange(
- ProducerSatisfiedFlagsNoLock(), ProducerSatisfiableFlagsNoLock());
+ ProducerGetWaitFlagsStateNoLock());
}
void DataPipe::AwakeConsumerWaitersForStateChangeNoLock() {
@@ -385,7 +393,7 @@ void DataPipe::AwakeConsumerWaitersForStateChangeNoLock() {
if (!has_local_consumer_no_lock())
return;
consumer_waiter_list_->AwakeWaitersForStateChange(
- ConsumerSatisfiedFlagsNoLock(), ConsumerSatisfiableFlagsNoLock());
+ ConsumerGetWaitFlagsStateNoLock());
}
} // namespace system
diff --git a/mojo/system/data_pipe.h b/mojo/system/data_pipe.h
index a4a903b..a1d95ad 100644
--- a/mojo/system/data_pipe.h
+++ b/mojo/system/data_pipe.h
@@ -12,6 +12,7 @@
#include "mojo/public/c/system/data_pipe.h"
#include "mojo/public/c/system/types.h"
#include "mojo/system/system_impl_export.h"
+#include "mojo/system/wait_flags_state.h"
namespace mojo {
namespace system {
@@ -105,8 +106,7 @@ class MOJO_SYSTEM_IMPL_EXPORT DataPipe :
virtual MojoResult ProducerEndWriteDataImplNoLock(
uint32_t num_bytes_written) = 0;
// Note: A producer should not be writable during a two-phase write.
- virtual MojoWaitFlags ProducerSatisfiedFlagsNoLock() = 0;
- virtual MojoWaitFlags ProducerSatisfiableFlagsNoLock() = 0;
+ virtual WaitFlagsState ProducerGetWaitFlagsStateNoLock() const = 0;
virtual void ConsumerCloseImplNoLock() = 0;
// |*num_bytes| will be a nonzero multiple of |element_num_bytes_|.
@@ -122,8 +122,7 @@ class MOJO_SYSTEM_IMPL_EXPORT DataPipe :
bool all_or_none) = 0;
virtual MojoResult ConsumerEndReadDataImplNoLock(uint32_t num_bytes_read) = 0;
// Note: A consumer should not be writable during a two-phase read.
- virtual MojoWaitFlags ConsumerSatisfiedFlagsNoLock() = 0;
- virtual MojoWaitFlags ConsumerSatisfiableFlagsNoLock() = 0;
+ virtual WaitFlagsState ConsumerGetWaitFlagsStateNoLock() const = 0;
// Thread-safe and fast (they don't take the lock):
bool may_discard() const { return may_discard_; }
diff --git a/mojo/system/local_data_pipe.cc b/mojo/system/local_data_pipe.cc
index 942e4be..d98ccf4 100644
--- a/mojo/system/local_data_pipe.cc
+++ b/mojo/system/local_data_pipe.cc
@@ -151,19 +151,14 @@ MojoResult LocalDataPipe::ProducerEndWriteDataImplNoLock(
return MOJO_RESULT_OK;
}
-MojoWaitFlags LocalDataPipe::ProducerSatisfiedFlagsNoLock() {
- MojoWaitFlags rv = MOJO_WAIT_FLAG_NONE;
- if (consumer_open_no_lock() &&
- (may_discard() || current_num_bytes_ < capacity_num_bytes()) &&
- !producer_in_two_phase_write_no_lock())
- rv |= MOJO_WAIT_FLAG_WRITABLE;
- return rv;
-}
-
-MojoWaitFlags LocalDataPipe::ProducerSatisfiableFlagsNoLock() {
- MojoWaitFlags rv = MOJO_WAIT_FLAG_NONE;
- if (consumer_open_no_lock())
- rv |= MOJO_WAIT_FLAG_WRITABLE;
+WaitFlagsState LocalDataPipe::ProducerGetWaitFlagsStateNoLock() const {
+ WaitFlagsState rv;
+ if (consumer_open_no_lock()) {
+ if ((may_discard() || current_num_bytes_ < capacity_num_bytes()) &&
+ !producer_in_two_phase_write_no_lock())
+ rv.satisfied_flags |= MOJO_WAIT_FLAG_WRITABLE;
+ rv.satisfiable_flags |= MOJO_WAIT_FLAG_WRITABLE;
+ }
return rv;
}
@@ -278,17 +273,15 @@ MojoResult LocalDataPipe::ConsumerEndReadDataImplNoLock(
return MOJO_RESULT_OK;
}
-MojoWaitFlags LocalDataPipe::ConsumerSatisfiedFlagsNoLock() {
- MojoWaitFlags rv = MOJO_WAIT_FLAG_NONE;
- if (current_num_bytes_ > 0 && !consumer_in_two_phase_read_no_lock())
- rv |= MOJO_WAIT_FLAG_READABLE;
- return rv;
-}
-
-MojoWaitFlags LocalDataPipe::ConsumerSatisfiableFlagsNoLock() {
- MojoWaitFlags rv = MOJO_WAIT_FLAG_NONE;
- if (current_num_bytes_ > 0 || producer_open_no_lock())
- rv |= MOJO_WAIT_FLAG_READABLE;
+WaitFlagsState LocalDataPipe::ConsumerGetWaitFlagsStateNoLock() const {
+ WaitFlagsState rv;
+ if (current_num_bytes_ > 0) {
+ if (!consumer_in_two_phase_read_no_lock())
+ rv.satisfied_flags |= MOJO_WAIT_FLAG_READABLE;
+ rv.satisfiable_flags |= MOJO_WAIT_FLAG_READABLE;
+ } else if (producer_open_no_lock()) {
+ rv.satisfiable_flags |= MOJO_WAIT_FLAG_READABLE;
+ }
return rv;
}
diff --git a/mojo/system/local_data_pipe.h b/mojo/system/local_data_pipe.h
index 973ab68..7eb0f5f 100644
--- a/mojo/system/local_data_pipe.h
+++ b/mojo/system/local_data_pipe.h
@@ -40,8 +40,7 @@ class MOJO_SYSTEM_IMPL_EXPORT LocalDataPipe : public DataPipe {
bool all_or_none) OVERRIDE;
virtual MojoResult ProducerEndWriteDataImplNoLock(
uint32_t num_bytes_written) OVERRIDE;
- virtual MojoWaitFlags ProducerSatisfiedFlagsNoLock() OVERRIDE;
- virtual MojoWaitFlags ProducerSatisfiableFlagsNoLock() OVERRIDE;
+ virtual WaitFlagsState ProducerGetWaitFlagsStateNoLock() const OVERRIDE;
virtual void ConsumerCloseImplNoLock() OVERRIDE;
virtual MojoResult ConsumerReadDataImplNoLock(void* elements,
uint32_t* num_bytes,
@@ -54,8 +53,7 @@ class MOJO_SYSTEM_IMPL_EXPORT LocalDataPipe : public DataPipe {
bool all_or_none) OVERRIDE;
virtual MojoResult ConsumerEndReadDataImplNoLock(
uint32_t num_bytes_read) OVERRIDE;
- virtual MojoWaitFlags ConsumerSatisfiedFlagsNoLock() OVERRIDE;
- virtual MojoWaitFlags ConsumerSatisfiableFlagsNoLock() OVERRIDE;
+ virtual WaitFlagsState ConsumerGetWaitFlagsStateNoLock() const OVERRIDE;
void EnsureBufferNoLock();
void DestroyBufferNoLock();
diff --git a/mojo/system/local_message_pipe_endpoint.cc b/mojo/system/local_message_pipe_endpoint.cc
index 606ffa9..e3deb32 100644
--- a/mojo/system/local_message_pipe_endpoint.cc
+++ b/mojo/system/local_message_pipe_endpoint.cc
@@ -31,17 +31,12 @@ bool LocalMessagePipeEndpoint::OnPeerClose() {
DCHECK(is_open_);
DCHECK(is_peer_open_);
- MojoWaitFlags old_satisfied_flags = SatisfiedFlags();
- MojoWaitFlags old_satisfiable_flags = SatisfiableFlags();
+ WaitFlagsState old_state = GetWaitFlagsState();
is_peer_open_ = false;
- MojoWaitFlags new_satisfied_flags = SatisfiedFlags();
- MojoWaitFlags new_satisfiable_flags = SatisfiableFlags();
+ WaitFlagsState new_state = GetWaitFlagsState();
- if (new_satisfied_flags != old_satisfied_flags ||
- new_satisfiable_flags != old_satisfiable_flags) {
- waiter_list_.AwakeWaitersForStateChange(new_satisfied_flags,
- new_satisfiable_flags);
- }
+ if (!new_state.equals(old_state))
+ waiter_list_.AwakeWaitersForStateChange(new_state);
return true;
}
@@ -53,10 +48,8 @@ void LocalMessagePipeEndpoint::EnqueueMessage(
bool was_empty = message_queue_.IsEmpty();
message_queue_.AddMessage(message.Pass());
- if (was_empty) {
- waiter_list_.AwakeWaitersForStateChange(SatisfiedFlags(),
- SatisfiableFlags());
- }
+ if (was_empty)
+ waiter_list_.AwakeWaitersForStateChange(GetWaitFlagsState());
}
void LocalMessagePipeEndpoint::Close() {
@@ -124,8 +117,7 @@ MojoResult LocalMessagePipeEndpoint::ReadMessage(void* bytes,
if (message_queue_.IsEmpty()) {
// It's currently not possible to wait for non-readability, but we should
// do the state change anyway.
- waiter_list_.AwakeWaitersForStateChange(SatisfiedFlags(),
- SatisfiableFlags());
+ waiter_list_.AwakeWaitersForStateChange(GetWaitFlagsState());
}
}
@@ -140,9 +132,10 @@ MojoResult LocalMessagePipeEndpoint::AddWaiter(Waiter* waiter,
MojoResult wake_result) {
DCHECK(is_open_);
- if ((flags & SatisfiedFlags()))
+ WaitFlagsState state = GetWaitFlagsState();
+ if (state.satisfies(flags))
return MOJO_RESULT_ALREADY_EXISTS;
- if (!(flags & SatisfiableFlags()))
+ if (!state.can_satisfy(flags))
return MOJO_RESULT_FAILED_PRECONDITION;
waiter_list_.AddWaiter(waiter, flags, wake_result);
@@ -154,22 +147,17 @@ void LocalMessagePipeEndpoint::RemoveWaiter(Waiter* waiter) {
waiter_list_.RemoveWaiter(waiter);
}
-MojoWaitFlags LocalMessagePipeEndpoint::SatisfiedFlags() {
- MojoWaitFlags satisfied_flags = 0;
- if (!message_queue_.IsEmpty())
- satisfied_flags |= MOJO_WAIT_FLAG_READABLE;
- if (is_peer_open_)
- satisfied_flags |= MOJO_WAIT_FLAG_WRITABLE;
- return satisfied_flags;
-}
-
-MojoWaitFlags LocalMessagePipeEndpoint::SatisfiableFlags() {
- MojoWaitFlags satisfiable_flags = 0;
- if (!message_queue_.IsEmpty() || is_peer_open_)
- satisfiable_flags |= MOJO_WAIT_FLAG_READABLE;
- if (is_peer_open_)
- satisfiable_flags |= MOJO_WAIT_FLAG_WRITABLE;
- return satisfiable_flags;
+WaitFlagsState LocalMessagePipeEndpoint::GetWaitFlagsState() {
+ WaitFlagsState rv;
+ if (!message_queue_.IsEmpty()) {
+ rv.satisfied_flags |= MOJO_WAIT_FLAG_READABLE;
+ rv.satisfiable_flags |= MOJO_WAIT_FLAG_READABLE;
+ }
+ if (is_peer_open_) {
+ rv.satisfied_flags |= MOJO_WAIT_FLAG_WRITABLE;
+ rv.satisfiable_flags |= MOJO_WAIT_FLAG_READABLE | MOJO_WAIT_FLAG_WRITABLE;
+ }
+ return rv;
}
} // namespace system
diff --git a/mojo/system/local_message_pipe_endpoint.h b/mojo/system/local_message_pipe_endpoint.h
index fdc3211..89dca4e 100644
--- a/mojo/system/local_message_pipe_endpoint.h
+++ b/mojo/system/local_message_pipe_endpoint.h
@@ -10,6 +10,7 @@
#include "mojo/system/message_in_transit_queue.h"
#include "mojo/system/message_pipe_endpoint.h"
#include "mojo/system/system_impl_export.h"
+#include "mojo/system/wait_flags_state.h"
#include "mojo/system/waiter_list.h"
namespace mojo {
@@ -44,8 +45,7 @@ class MOJO_SYSTEM_IMPL_EXPORT LocalMessagePipeEndpoint
MessageInTransitQueue* message_queue() { return &message_queue_; }
private:
- MojoWaitFlags SatisfiedFlags();
- MojoWaitFlags SatisfiableFlags();
+ WaitFlagsState GetWaitFlagsState();
bool is_open_;
bool is_peer_open_;
diff --git a/mojo/system/platform_handle_dispatcher.cc b/mojo/system/platform_handle_dispatcher.cc
index e9b8af0..294a548 100644
--- a/mojo/system/platform_handle_dispatcher.cc
+++ b/mojo/system/platform_handle_dispatcher.cc
@@ -114,12 +114,8 @@ bool PlatformHandleDispatcher::EndSerializeAndCloseImplNoLock(
return true;
}
-MojoWaitFlags PlatformHandleDispatcher::SatisfiedFlagsNoLock() const {
- return MOJO_WAIT_FLAG_NONE;
-}
-
-MojoWaitFlags PlatformHandleDispatcher::SatisfiableFlagsNoLock() const {
- return MOJO_WAIT_FLAG_NONE;
+WaitFlagsState PlatformHandleDispatcher::GetWaitFlagsStateNoLock() const {
+ return WaitFlagsState();
}
} // namespace system
diff --git a/mojo/system/platform_handle_dispatcher.h b/mojo/system/platform_handle_dispatcher.h
index 2bf4d19..2e61098 100644
--- a/mojo/system/platform_handle_dispatcher.h
+++ b/mojo/system/platform_handle_dispatcher.h
@@ -50,9 +50,8 @@ class MOJO_SYSTEM_IMPL_EXPORT PlatformHandleDispatcher
size_t* actual_size,
embedder::PlatformHandleVector* platform_handles) OVERRIDE;
- // |SimpleDispatcher| methods:
- virtual MojoWaitFlags SatisfiedFlagsNoLock() const OVERRIDE;
- virtual MojoWaitFlags SatisfiableFlagsNoLock() const OVERRIDE;
+ // |SimpleDispatcher| method:
+ virtual WaitFlagsState GetWaitFlagsStateNoLock() const OVERRIDE;
embedder::ScopedPlatformHandle platform_handle_;
diff --git a/mojo/system/shared_buffer_dispatcher.cc b/mojo/system/shared_buffer_dispatcher.cc
index 57f0b6e..4400b8a 100644
--- a/mojo/system/shared_buffer_dispatcher.cc
+++ b/mojo/system/shared_buffer_dispatcher.cc
@@ -263,14 +263,9 @@ bool SharedBufferDispatcher::EndSerializeAndCloseImplNoLock(
return true;
}
-MojoWaitFlags SharedBufferDispatcher::SatisfiedFlagsNoLock() const {
+WaitFlagsState SharedBufferDispatcher::GetWaitFlagsStateNoLock() const {
// TODO(vtl): Add transferrable flag.
- return MOJO_WAIT_FLAG_NONE;
-}
-
-MojoWaitFlags SharedBufferDispatcher::SatisfiableFlagsNoLock() const {
- // TODO(vtl): Add transferrable flag.
- return MOJO_WAIT_FLAG_NONE;
+ return WaitFlagsState();
}
} // namespace system
diff --git a/mojo/system/shared_buffer_dispatcher.h b/mojo/system/shared_buffer_dispatcher.h
index f7c4d1b..097bfa2 100644
--- a/mojo/system/shared_buffer_dispatcher.h
+++ b/mojo/system/shared_buffer_dispatcher.h
@@ -84,9 +84,8 @@ class MOJO_SYSTEM_IMPL_EXPORT SharedBufferDispatcher : public SimpleDispatcher {
size_t* actual_size,
embedder::PlatformHandleVector* platform_handles) OVERRIDE;
- // |SimpleDispatcher| methods:
- virtual MojoWaitFlags SatisfiedFlagsNoLock() const OVERRIDE;
- virtual MojoWaitFlags SatisfiableFlagsNoLock() const OVERRIDE;
+ // |SimpleDispatcher| method:
+ virtual WaitFlagsState GetWaitFlagsStateNoLock() const OVERRIDE;
scoped_refptr<RawSharedBuffer> shared_buffer_;
diff --git a/mojo/system/simple_dispatcher.cc b/mojo/system/simple_dispatcher.cc
index ce2baef..717ac00 100644
--- a/mojo/system/simple_dispatcher.cc
+++ b/mojo/system/simple_dispatcher.cc
@@ -15,10 +15,9 @@ SimpleDispatcher::SimpleDispatcher() {
SimpleDispatcher::~SimpleDispatcher() {
}
-void SimpleDispatcher::StateChangedNoLock() {
+void SimpleDispatcher::WaitFlagsStateChangedNoLock() {
lock().AssertAcquired();
- waiter_list_.AwakeWaitersForStateChange(SatisfiedFlagsNoLock(),
- SatisfiableFlagsNoLock());
+ waiter_list_.AwakeWaitersForStateChange(GetWaitFlagsStateNoLock());
}
void SimpleDispatcher::CancelAllWaitersNoLock() {
@@ -31,9 +30,10 @@ MojoResult SimpleDispatcher::AddWaiterImplNoLock(Waiter* waiter,
MojoResult wake_result) {
lock().AssertAcquired();
- if ((flags & SatisfiedFlagsNoLock()))
+ WaitFlagsState state(GetWaitFlagsStateNoLock());
+ if (state.satisfies(flags))
return MOJO_RESULT_ALREADY_EXISTS;
- if (!(flags & SatisfiableFlagsNoLock()))
+ if (!state.can_satisfy(flags))
return MOJO_RESULT_FAILED_PRECONDITION;
waiter_list_.AddWaiter(waiter, flags, wake_result);
diff --git a/mojo/system/simple_dispatcher.h b/mojo/system/simple_dispatcher.h
index 15a64d5..8258c2a 100644
--- a/mojo/system/simple_dispatcher.h
+++ b/mojo/system/simple_dispatcher.h
@@ -10,6 +10,7 @@
#include "base/basictypes.h"
#include "mojo/system/dispatcher.h"
#include "mojo/system/system_impl_export.h"
+#include "mojo/system/wait_flags_state.h"
#include "mojo/system/waiter_list.h"
namespace mojo {
@@ -25,17 +26,12 @@ class MOJO_SYSTEM_IMPL_EXPORT SimpleDispatcher : public Dispatcher {
virtual ~SimpleDispatcher();
// To be called by subclasses when the state changes (so
- // |SatisfiedFlagsNoLock()| and |SatisfiableFlagsNoLock()| should be checked
- // again). Must be called under lock.
- void StateChangedNoLock();
-
- // These should return the wait flags that are satisfied by the object's
- // current state and those that may eventually be satisfied by this object's
- // state, respectively. They should be overridden by subclasses to reflect
- // their notion of state. They are never called after the dispatcher has been
- // closed. They are called under |lock_|.
- virtual MojoWaitFlags SatisfiedFlagsNoLock() const = 0;
- virtual MojoWaitFlags SatisfiableFlagsNoLock() const = 0;
+ // |GetWaitFlagsStateNoLock()| should be checked again). Must be called under
+ // lock.
+ void WaitFlagsStateChangedNoLock();
+
+ // Never called after the dispatcher has been closed; called under |lock_|.
+ virtual WaitFlagsState GetWaitFlagsStateNoLock() const = 0;
// |Dispatcher| protected methods:
virtual void CancelAllWaitersNoLock() OVERRIDE;
diff --git a/mojo/system/simple_dispatcher_unittest.cc b/mojo/system/simple_dispatcher_unittest.cc
index 6f232693..26fc277 100644
--- a/mojo/system/simple_dispatcher_unittest.cc
+++ b/mojo/system/simple_dispatcher_unittest.cc
@@ -28,31 +28,36 @@ namespace {
class MockSimpleDispatcher : public SimpleDispatcher {
public:
MockSimpleDispatcher()
- : satisfied_flags_(MOJO_WAIT_FLAG_NONE),
- satisfiable_flags_(MOJO_WAIT_FLAG_READABLE | MOJO_WAIT_FLAG_WRITABLE) {}
+ : state_(MOJO_WAIT_FLAG_NONE,
+ MOJO_WAIT_FLAG_READABLE | MOJO_WAIT_FLAG_WRITABLE) {}
void SetSatisfiedFlags(MojoWaitFlags new_satisfied_flags) {
base::AutoLock locker(lock());
// Any new flags that are set should be satisfiable.
- CHECK_EQ(new_satisfied_flags & ~satisfied_flags_,
- new_satisfied_flags & ~satisfied_flags_ & satisfiable_flags_);
+ CHECK_EQ(new_satisfied_flags & ~state_.satisfied_flags,
+ new_satisfied_flags & ~state_.satisfied_flags &
+ state_.satisfiable_flags);
- if (new_satisfied_flags == satisfied_flags_)
+ if (new_satisfied_flags == state_.satisfied_flags)
return;
- satisfied_flags_ = new_satisfied_flags;
- StateChangedNoLock();
+ state_.satisfied_flags = new_satisfied_flags;
+ WaitFlagsStateChangedNoLock();
}
void SetSatisfiableFlags(MojoWaitFlags new_satisfiable_flags) {
base::AutoLock locker(lock());
- if (new_satisfiable_flags == satisfiable_flags_)
+ // Satisfied implies satisfiable.
+ CHECK_EQ(new_satisfiable_flags & state_.satisfied_flags,
+ state_.satisfied_flags);
+
+ if (new_satisfiable_flags == state_.satisfiable_flags)
return;
- satisfiable_flags_ = new_satisfiable_flags;
- StateChangedNoLock();
+ state_.satisfiable_flags = new_satisfiable_flags;
+ WaitFlagsStateChangedNoLock();
}
virtual Type GetType() const OVERRIDE {
@@ -66,25 +71,18 @@ class MockSimpleDispatcher : public SimpleDispatcher {
virtual scoped_refptr<Dispatcher>
CreateEquivalentDispatcherAndCloseImplNoLock() OVERRIDE {
scoped_refptr<MockSimpleDispatcher> rv(new MockSimpleDispatcher());
- rv->satisfied_flags_ = satisfied_flags_;
- rv->satisfiable_flags_ = satisfiable_flags_;
+ rv->state_ = state_;
return scoped_refptr<Dispatcher>(rv.get());
}
// |SimpleDispatcher| implementation:
- virtual MojoWaitFlags SatisfiedFlagsNoLock() const OVERRIDE {
- lock().AssertAcquired();
- return satisfied_flags_;
- }
-
- virtual MojoWaitFlags SatisfiableFlagsNoLock() const OVERRIDE {
+ virtual WaitFlagsState GetWaitFlagsStateNoLock() const OVERRIDE {
lock().AssertAcquired();
- return satisfiable_flags_;
+ return state_;
}
// Protected by |lock()|:
- MojoWaitFlags satisfied_flags_;
- MojoWaitFlags satisfiable_flags_;
+ WaitFlagsState state_;
DISALLOW_COPY_AND_ASSIGN(MockSimpleDispatcher);
};
diff --git a/mojo/system/wait_flags_state.h b/mojo/system/wait_flags_state.h
new file mode 100644
index 0000000..aaddd0c
--- /dev/null
+++ b/mojo/system/wait_flags_state.h
@@ -0,0 +1,48 @@
+// Copyright 2014 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 MOJO_SYSTEM_WAIT_FLAGS_STATE_H_
+#define MOJO_SYSTEM_WAIT_FLAGS_STATE_H_
+
+#include "base/macros.h"
+#include "mojo/public/c/system/types.h"
+#include "mojo/system/system_impl_export.h"
+
+namespace mojo {
+namespace system {
+
+// Just "add" some constructors and methods to the C struct |MojoWaitFlagsState|
+// (for convenience). This should add no overhead.
+struct MOJO_SYSTEM_IMPL_EXPORT WaitFlagsState : public MojoWaitFlagsState {
+ WaitFlagsState() {
+ satisfied_flags = MOJO_WAIT_FLAG_NONE;
+ satisfiable_flags = MOJO_WAIT_FLAG_NONE;
+ }
+ WaitFlagsState(MojoWaitFlags satisfied, MojoWaitFlags satisfiable) {
+ satisfied_flags = satisfied;
+ satisfiable_flags = satisfiable;
+ }
+
+ bool equals(const WaitFlagsState& other) const {
+ return satisfied_flags == other.satisfied_flags &&
+ satisfiable_flags == other.satisfiable_flags;
+ }
+
+ bool satisfies(MojoWaitFlags flags) const {
+ return !!(satisfied_flags & flags);
+ }
+
+ bool can_satisfy(MojoWaitFlags flags) const {
+ return !!(satisfiable_flags & flags);
+ }
+
+ // (Copy and assignment allowed.)
+};
+COMPILE_ASSERT(sizeof(WaitFlagsState) == sizeof(MojoWaitFlagsState),
+ WaitFlagsState_should_add_no_overhead);
+
+} // namespace system
+} // namespace mojo
+
+#endif // MOJO_SYSTEM_WAIT_FLAGS_STATE_H_
diff --git a/mojo/system/waiter_list.cc b/mojo/system/waiter_list.cc
index 6f2c444..c398c84 100644
--- a/mojo/system/waiter_list.cc
+++ b/mojo/system/waiter_list.cc
@@ -5,6 +5,7 @@
#include "mojo/system/waiter_list.h"
#include "base/logging.h"
+#include "mojo/system/wait_flags_state.h"
#include "mojo/system/waiter.h"
namespace mojo {
@@ -17,6 +18,17 @@ WaiterList::~WaiterList() {
DCHECK(waiters_.empty());
}
+void WaiterList::AwakeWaitersForStateChange(const WaitFlagsState& state) {
+ for (WaiterInfoList::iterator it = waiters_.begin(); it != waiters_.end();
+ ++it) {
+ if (state.satisfies(it->flags))
+ it->waiter->Awake(it->wake_result);
+ else if (!state.can_satisfy(it->flags))
+ it->waiter->Awake(MOJO_RESULT_FAILED_PRECONDITION);
+ }
+}
+
+//FIXME Remove:
void WaiterList::AwakeWaitersForStateChange(MojoWaitFlags satisfied_flags,
MojoWaitFlags satisfiable_flags) {
for (WaiterInfoList::iterator it = waiters_.begin(); it != waiters_.end();
diff --git a/mojo/system/waiter_list.h b/mojo/system/waiter_list.h
index 7266e2c..105717e 100644
--- a/mojo/system/waiter_list.h
+++ b/mojo/system/waiter_list.h
@@ -15,6 +15,7 @@ namespace mojo {
namespace system {
class Waiter;
+struct WaitFlagsState;
// |WaiterList| tracks all the |Waiter|s that are waiting on a given
// handle/|Dispatcher|. There should be a |WaiterList| for each handle that can
@@ -28,6 +29,8 @@ class MOJO_SYSTEM_IMPL_EXPORT WaiterList {
WaiterList();
~WaiterList();
+ void AwakeWaitersForStateChange(const WaitFlagsState& state);
+//FIXME Remove:
void AwakeWaitersForStateChange(MojoWaitFlags satisfied_flags,
MojoWaitFlags satisfiable_flags);
void CancelAllWaiters();
diff --git a/mojo/system/waiter_list_unittest.cc b/mojo/system/waiter_list_unittest.cc
index 9eeb4e7..eb77681 100644
--- a/mojo/system/waiter_list_unittest.cc
+++ b/mojo/system/waiter_list_unittest.cc
@@ -12,6 +12,7 @@
#include "base/threading/platform_thread.h" // For |Sleep()|.
#include "base/time/time.h"
#include "mojo/system/test_utils.h"
+#include "mojo/system/wait_flags_state.h"
#include "mojo/system/waiter.h"
#include "mojo/system/waiter_test_utils.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -65,9 +66,9 @@ TEST(WaiterListTest, BasicAwakeSatisfied) {
test::SimpleWaiterThread thread(&result);
waiter_list.AddWaiter(thread.waiter(), MOJO_WAIT_FLAG_READABLE, 0);
thread.Start();
- waiter_list.AwakeWaitersForStateChange(MOJO_WAIT_FLAG_READABLE,
- MOJO_WAIT_FLAG_READABLE |
- MOJO_WAIT_FLAG_WRITABLE);
+ waiter_list.AwakeWaitersForStateChange(
+ WaitFlagsState(MOJO_WAIT_FLAG_READABLE,
+ MOJO_WAIT_FLAG_READABLE | MOJO_WAIT_FLAG_WRITABLE));
waiter_list.RemoveWaiter(thread.waiter());
} // Join |thread|.
EXPECT_EQ(0, result);
@@ -77,9 +78,9 @@ TEST(WaiterListTest, BasicAwakeSatisfied) {
WaiterList waiter_list;
test::SimpleWaiterThread thread(&result);
waiter_list.AddWaiter(thread.waiter(), MOJO_WAIT_FLAG_WRITABLE, 1);
- waiter_list.AwakeWaitersForStateChange(MOJO_WAIT_FLAG_WRITABLE,
- MOJO_WAIT_FLAG_READABLE |
- MOJO_WAIT_FLAG_WRITABLE);
+ waiter_list.AwakeWaitersForStateChange(
+ WaitFlagsState(MOJO_WAIT_FLAG_WRITABLE,
+ MOJO_WAIT_FLAG_READABLE | MOJO_WAIT_FLAG_WRITABLE));
waiter_list.RemoveWaiter(thread.waiter());
waiter_list.RemoveWaiter(thread.waiter()); // Double-remove okay.
thread.Start();
@@ -93,9 +94,9 @@ TEST(WaiterListTest, BasicAwakeSatisfied) {
waiter_list.AddWaiter(thread.waiter(), MOJO_WAIT_FLAG_READABLE, 2);
thread.Start();
base::PlatformThread::Sleep(2 * test::EpsilonTimeout());
- waiter_list.AwakeWaitersForStateChange(MOJO_WAIT_FLAG_READABLE,
- MOJO_WAIT_FLAG_READABLE |
- MOJO_WAIT_FLAG_WRITABLE);
+ waiter_list.AwakeWaitersForStateChange(
+ WaitFlagsState(MOJO_WAIT_FLAG_READABLE,
+ MOJO_WAIT_FLAG_READABLE | MOJO_WAIT_FLAG_WRITABLE));
waiter_list.RemoveWaiter(thread.waiter());
} // Join |thread|.
EXPECT_EQ(2, result);
@@ -110,7 +111,8 @@ TEST(WaiterListTest, BasicAwakeUnsatisfiable) {
test::SimpleWaiterThread thread(&result);
waiter_list.AddWaiter(thread.waiter(), MOJO_WAIT_FLAG_READABLE, 0);
thread.Start();
- waiter_list.AwakeWaitersForStateChange(0, MOJO_WAIT_FLAG_WRITABLE);
+ waiter_list.AwakeWaitersForStateChange(
+ WaitFlagsState(MOJO_WAIT_FLAG_NONE, MOJO_WAIT_FLAG_WRITABLE));
waiter_list.RemoveWaiter(thread.waiter());
} // Join |thread|.
EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, result);
@@ -120,8 +122,8 @@ TEST(WaiterListTest, BasicAwakeUnsatisfiable) {
WaiterList waiter_list;
test::SimpleWaiterThread thread(&result);
waiter_list.AddWaiter(thread.waiter(), MOJO_WAIT_FLAG_WRITABLE, 1);
- waiter_list.AwakeWaitersForStateChange(MOJO_WAIT_FLAG_READABLE,
- MOJO_WAIT_FLAG_READABLE);
+ waiter_list.AwakeWaitersForStateChange(
+ WaitFlagsState(MOJO_WAIT_FLAG_READABLE, MOJO_WAIT_FLAG_READABLE));
waiter_list.RemoveWaiter(thread.waiter());
thread.Start();
} // Join |thread|.
@@ -134,7 +136,8 @@ TEST(WaiterListTest, BasicAwakeUnsatisfiable) {
waiter_list.AddWaiter(thread.waiter(), MOJO_WAIT_FLAG_READABLE, 2);
thread.Start();
base::PlatformThread::Sleep(2 * test::EpsilonTimeout());
- waiter_list.AwakeWaitersForStateChange(0, MOJO_WAIT_FLAG_WRITABLE);
+ waiter_list.AwakeWaitersForStateChange(
+ WaitFlagsState(MOJO_WAIT_FLAG_NONE, MOJO_WAIT_FLAG_WRITABLE));
waiter_list.RemoveWaiter(thread.waiter());
waiter_list.RemoveWaiter(thread.waiter()); // Double-remove okay.
} // Join |thread|.
@@ -172,9 +175,9 @@ TEST(WaiterListTest, MultipleWaiters) {
waiter_list.AddWaiter(thread2.waiter(), MOJO_WAIT_FLAG_WRITABLE, 3);
thread2.Start();
base::PlatformThread::Sleep(2 * test::EpsilonTimeout());
- waiter_list.AwakeWaitersForStateChange(MOJO_WAIT_FLAG_READABLE,
- MOJO_WAIT_FLAG_READABLE |
- MOJO_WAIT_FLAG_WRITABLE);
+ waiter_list.AwakeWaitersForStateChange(
+ WaitFlagsState(MOJO_WAIT_FLAG_READABLE,
+ MOJO_WAIT_FLAG_READABLE | MOJO_WAIT_FLAG_WRITABLE));
waiter_list.RemoveWaiter(thread1.waiter());
waiter_list.CancelAllWaiters();
} // Join threads.
@@ -191,7 +194,8 @@ TEST(WaiterListTest, MultipleWaiters) {
waiter_list.AddWaiter(thread2.waiter(), MOJO_WAIT_FLAG_WRITABLE, 5);
thread2.Start();
base::PlatformThread::Sleep(2 * test::EpsilonTimeout());
- waiter_list.AwakeWaitersForStateChange(0, MOJO_WAIT_FLAG_READABLE);
+ waiter_list.AwakeWaitersForStateChange(
+ WaitFlagsState(MOJO_WAIT_FLAG_NONE, MOJO_WAIT_FLAG_READABLE));
waiter_list.RemoveWaiter(thread2.waiter());
waiter_list.CancelAllWaiters();
} // Join threads.
@@ -208,9 +212,9 @@ TEST(WaiterListTest, MultipleWaiters) {
base::PlatformThread::Sleep(1 * test::EpsilonTimeout());
// Should do nothing.
- waiter_list.AwakeWaitersForStateChange(0,
- MOJO_WAIT_FLAG_READABLE |
- MOJO_WAIT_FLAG_WRITABLE);
+ waiter_list.AwakeWaitersForStateChange(
+ WaitFlagsState(MOJO_WAIT_FLAG_NONE,
+ MOJO_WAIT_FLAG_READABLE | MOJO_WAIT_FLAG_WRITABLE));
test::SimpleWaiterThread thread2(&result2);
waiter_list.AddWaiter(thread2.waiter(), MOJO_WAIT_FLAG_WRITABLE, 7);
@@ -219,9 +223,9 @@ TEST(WaiterListTest, MultipleWaiters) {
base::PlatformThread::Sleep(1 * test::EpsilonTimeout());
// Awake #1.
- waiter_list.AwakeWaitersForStateChange(MOJO_WAIT_FLAG_READABLE,
- MOJO_WAIT_FLAG_READABLE |
- MOJO_WAIT_FLAG_WRITABLE);
+ waiter_list.AwakeWaitersForStateChange(
+ WaitFlagsState(MOJO_WAIT_FLAG_READABLE,
+ MOJO_WAIT_FLAG_READABLE | MOJO_WAIT_FLAG_WRITABLE));
waiter_list.RemoveWaiter(thread1.waiter());
base::PlatformThread::Sleep(1 * test::EpsilonTimeout());
@@ -237,7 +241,8 @@ TEST(WaiterListTest, MultipleWaiters) {
base::PlatformThread::Sleep(1 * test::EpsilonTimeout());
// Awake #2 and #3 for unsatisfiability.
- waiter_list.AwakeWaitersForStateChange(0, MOJO_WAIT_FLAG_READABLE);
+ waiter_list.AwakeWaitersForStateChange(
+ WaitFlagsState(MOJO_WAIT_FLAG_NONE, MOJO_WAIT_FLAG_READABLE));
waiter_list.RemoveWaiter(thread2.waiter());
waiter_list.RemoveWaiter(thread3.waiter());