C++程序  |  135行  |  5.08 KB

// Copyright 2013 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_DATA_PIPE_H_
#define MOJO_SYSTEM_DATA_PIPE_H_

#include "base/basictypes.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "base/synchronization/lock.h"
#include "mojo/public/system/core.h"
#include "mojo/system/system_impl_export.h"

namespace mojo {
namespace system {

class Waiter;
class WaiterList;

// |DataPipe| is a base class for secondary objects implementing data pipes,
// similar to |MessagePipe| (see the explanatory comment in core_impl.cc). It is
// typically owned by the dispatcher(s) corresponding to the local endpoints.
// Its subclasses implement the three cases: local producer and consumer, local
// producer and remote consumer, and remote producer and local consumer. This
// class is thread-safe.
class MOJO_SYSTEM_IMPL_EXPORT DataPipe :
    public base::RefCountedThreadSafe<DataPipe> {
 public:
  // These are called by the producer dispatcher to implement its methods of
  // corresponding names.
  void ProducerCancelAllWaiters();
  void ProducerClose();
  // This does not validate its arguments.
  MojoResult ProducerWriteData(const void* elements,
                               uint32_t* num_elements,
                               MojoWriteDataFlags flags);
  // This does not validate its arguments.
  MojoResult ProducerBeginWriteData(void** buffer,
                                    uint32_t* buffer_num_elements,
                                    MojoWriteDataFlags flags);
  MojoResult ProducerEndWriteData(uint32_t num_elements_written);
  MojoResult ProducerAddWaiter(Waiter* waiter,
                               MojoWaitFlags flags,
                               MojoResult wake_result);
  void ProducerRemoveWaiter(Waiter* waiter);

  // These are called by the consumer dispatcher to implement its methods of
  // corresponding names.
  void ConsumerCancelAllWaiters();
  void ConsumerClose();
  // This does not validate its arguments.
  MojoResult ConsumerReadData(void* elements,
                              uint32_t* num_elements,
                              MojoReadDataFlags flags);
  // This does not validate its arguments.
  MojoResult ConsumerBeginReadData(const void** buffer,
                                   uint32_t* buffer_num_elements,
                                   MojoReadDataFlags flags);
  MojoResult ConsumerEndReadData(uint32_t num_elements_read);
  MojoResult ConsumerAddWaiter(Waiter* waiter,
                               MojoWaitFlags flags,
                               MojoResult wake_result);
  void ConsumerRemoveWaiter(Waiter* waiter);

  // Thread-safe and fast (they don't take the lock):
  bool may_discard() const { return may_discard_; }
  size_t element_size() const { return element_size_; }
  size_t capacity_num_elements() const { return capacity_num_elements_; }

 protected:
  DataPipe(bool has_local_producer, bool has_local_consumer);

  friend class base::RefCountedThreadSafe<DataPipe>;
  virtual ~DataPipe();

  // Not thread-safe; must be called before any other methods are called. This
  // object is only usable on success.
  MojoResult Init(bool may_discard,
                  size_t element_size,
                  size_t capacity_num_elements);

  void AwakeProducerWaitersForStateChangeNoLock();
  void AwakeConsumerWaitersForStateChangeNoLock();

  virtual void ProducerCloseImplNoLock() = 0;
  virtual MojoResult ProducerBeginWriteDataImplNoLock(
      void** buffer,
      uint32_t* buffer_num_elements,
      MojoWriteDataFlags flags) = 0;
  virtual MojoResult ProducerEndWriteDataImplNoLock(
      uint32_t num_elements_written) = 0;
  virtual MojoWaitFlags ProducerSatisfiedFlagsNoLock() = 0;
  virtual MojoWaitFlags ProducerSatisfiableFlagsNoLock() = 0;

  virtual void ConsumerCloseImplNoLock() = 0;
  virtual MojoResult ConsumerDiscardDataNoLock(uint32_t* num_elements,
                                               bool all_or_none) = 0;
  virtual MojoResult ConsumerQueryDataNoLock(uint32_t* num_elements) = 0;
  virtual MojoResult ConsumerBeginReadDataImplNoLock(
      const void** buffer,
      uint32_t* buffer_num_elements,
      MojoReadDataFlags flags) = 0;
  virtual MojoResult ConsumerEndReadDataImplNoLock(
      uint32_t num_elements_read) = 0;
  virtual MojoWaitFlags ConsumerSatisfiedFlagsNoLock() = 0;
  virtual MojoWaitFlags ConsumerSatisfiableFlagsNoLock() = 0;

 private:
  bool has_local_producer_no_lock() const {
    return !!producer_waiter_list_.get();
  }
  bool has_local_consumer_no_lock() const {
    return !!consumer_waiter_list_.get();
  }

  // Set by |Init()| and never changed afterwards:
  bool may_discard_;
  size_t element_size_;
  size_t capacity_num_elements_;

  base::Lock lock_;  // Protects the following members.
  scoped_ptr<WaiterList> producer_waiter_list_;
  scoped_ptr<WaiterList> consumer_waiter_list_;
  bool producer_in_two_phase_write_;
  bool consumer_in_two_phase_read_;

  DISALLOW_COPY_AND_ASSIGN(DataPipe);
};

}  // namespace system
}  // namespace mojo

#endif  // MOJO_SYSTEM_DATA_PIPE_H_