summaryrefslogtreecommitdiffstats
path: root/mojo/public/cpp
diff options
context:
space:
mode:
Diffstat (limited to 'mojo/public/cpp')
-rw-r--r--mojo/public/cpp/bindings/DEPS4
-rw-r--r--mojo/public/cpp/bindings/allocation_scope.h2
-rw-r--r--mojo/public/cpp/bindings/array.h2
-rw-r--r--mojo/public/cpp/bindings/callback.h4
-rw-r--r--mojo/public/cpp/bindings/callback.h.pump4
-rw-r--r--mojo/public/cpp/bindings/lib/DEPS5
-rw-r--r--mojo/public/cpp/bindings/lib/TODO7
-rw-r--r--mojo/public/cpp/bindings/lib/array.cc38
-rw-r--r--mojo/public/cpp/bindings/lib/array_internal.cc59
-rw-r--r--mojo/public/cpp/bindings/lib/array_internal.h372
-rw-r--r--mojo/public/cpp/bindings/lib/bindings_internal.h141
-rw-r--r--mojo/public/cpp/bindings/lib/bindings_serialization.cc73
-rw-r--r--mojo/public/cpp/bindings/lib/bindings_serialization.h67
-rw-r--r--mojo/public/cpp/bindings/lib/buffer.cc27
-rw-r--r--mojo/public/cpp/bindings/lib/callback_internal.h55
-rw-r--r--mojo/public/cpp/bindings/lib/connector.cc130
-rw-r--r--mojo/public/cpp/bindings/lib/connector.h80
-rw-r--r--mojo/public/cpp/bindings/lib/fixed_buffer.cc54
-rw-r--r--mojo/public/cpp/bindings/lib/fixed_buffer.h68
-rw-r--r--mojo/public/cpp/bindings/lib/interface.cc19
-rw-r--r--mojo/public/cpp/bindings/lib/message.cc84
-rw-r--r--mojo/public/cpp/bindings/lib/message_builder.cc52
-rw-r--r--mojo/public/cpp/bindings/lib/message_builder.h63
-rw-r--r--mojo/public/cpp/bindings/lib/message_internal.h44
-rw-r--r--mojo/public/cpp/bindings/lib/message_queue.cc50
-rw-r--r--mojo/public/cpp/bindings/lib/message_queue.h47
-rw-r--r--mojo/public/cpp/bindings/lib/router.cc137
-rw-r--r--mojo/public/cpp/bindings/lib/router.h73
-rw-r--r--mojo/public/cpp/bindings/lib/scratch_buffer.cc98
-rw-r--r--mojo/public/cpp/bindings/lib/scratch_buffer.h54
-rw-r--r--mojo/public/cpp/bindings/lib/shared_data.h81
-rw-r--r--mojo/public/cpp/bindings/lib/shared_ptr.h63
-rw-r--r--mojo/public/cpp/bindings/lib/sync_dispatcher.cc27
-rw-r--r--mojo/public/cpp/bindings/message.h2
-rw-r--r--mojo/public/cpp/bindings/passable.h2
-rw-r--r--mojo/public/cpp/bindings/remote_ptr.h2
36 files changed, 2077 insertions, 13 deletions
diff --git a/mojo/public/cpp/bindings/DEPS b/mojo/public/cpp/bindings/DEPS
deleted file mode 100644
index ba2a571..0000000
--- a/mojo/public/cpp/bindings/DEPS
+++ /dev/null
@@ -1,4 +0,0 @@
-include_rules = [
- # TODO(vtl): Temporary, until we move lib here.
- "+mojo/public/bindings/lib",
-]
diff --git a/mojo/public/cpp/bindings/allocation_scope.h b/mojo/public/cpp/bindings/allocation_scope.h
index e372457..110c9b3 100644
--- a/mojo/public/cpp/bindings/allocation_scope.h
+++ b/mojo/public/cpp/bindings/allocation_scope.h
@@ -5,7 +5,7 @@
#ifndef MOJO_PUBLIC_CPP_BINDINGS_ALLOCATION_SCOPE_H_
#define MOJO_PUBLIC_CPP_BINDINGS_ALLOCATION_SCOPE_H_
-#include "mojo/public/bindings/lib/scratch_buffer.h"
+#include "mojo/public/cpp/bindings/lib/scratch_buffer.h"
#include "mojo/public/cpp/system/macros.h"
namespace mojo {
diff --git a/mojo/public/cpp/bindings/array.h b/mojo/public/cpp/bindings/array.h
index 601eedc..72aa56d 100644
--- a/mojo/public/cpp/bindings/array.h
+++ b/mojo/public/cpp/bindings/array.h
@@ -11,7 +11,7 @@
#include <string>
#include <vector>
-#include "mojo/public/bindings/lib/array_internal.h"
+#include "mojo/public/cpp/bindings/lib/array_internal.h"
#include "mojo/public/cpp/bindings/type_converter.h"
namespace mojo {
diff --git a/mojo/public/cpp/bindings/callback.h b/mojo/public/cpp/bindings/callback.h
index 766c9c3..4192f89 100644
--- a/mojo/public/cpp/bindings/callback.h
+++ b/mojo/public/cpp/bindings/callback.h
@@ -11,8 +11,8 @@
#ifndef MOJO_PUBLIC_CPP_BINDINGS_CALLBACK_H_
#define MOJO_PUBLIC_CPP_BINDINGS_CALLBACK_H_
-#include "mojo/public/bindings/lib/callback_internal.h"
-#include "mojo/public/bindings/lib/shared_ptr.h"
+#include "mojo/public/cpp/bindings/lib/callback_internal.h"
+#include "mojo/public/cpp/bindings/lib/shared_ptr.h"
namespace mojo {
diff --git a/mojo/public/cpp/bindings/callback.h.pump b/mojo/public/cpp/bindings/callback.h.pump
index 998324f..5452abb 100644
--- a/mojo/public/cpp/bindings/callback.h.pump
+++ b/mojo/public/cpp/bindings/callback.h.pump
@@ -14,8 +14,8 @@ $var MAX_ARITY = 7
#ifndef MOJO_PUBLIC_CPP_BINDINGS_CALLBACK_H_
#define MOJO_PUBLIC_CPP_BINDINGS_CALLBACK_H_
-#include "mojo/public/bindings/lib/callback_internal.h"
-#include "mojo/public/bindings/lib/shared_ptr.h"
+#include "mojo/public/cpp/bindings/lib/callback_internal.h"
+#include "mojo/public/cpp/bindings/lib/shared_ptr.h"
namespace mojo {
diff --git a/mojo/public/cpp/bindings/lib/DEPS b/mojo/public/cpp/bindings/lib/DEPS
new file mode 100644
index 0000000..b809b58
--- /dev/null
+++ b/mojo/public/cpp/bindings/lib/DEPS
@@ -0,0 +1,5 @@
+include_rules = [
+ "+mojo/public/cpp/bindings",
+ "+mojo/public/cpp/environment",
+ "+mojo/public/cpp/system",
+]
diff --git a/mojo/public/cpp/bindings/lib/TODO b/mojo/public/cpp/bindings/lib/TODO
new file mode 100644
index 0000000..318edcf
--- /dev/null
+++ b/mojo/public/cpp/bindings/lib/TODO
@@ -0,0 +1,7 @@
+TODOs:
+ - Ensure validation checks are solid
+ - Add tests of validation logic
+ - Optimize Buffer classes?
+ - Make "Clone" method public?
+ - Add compile-time asserts to verify object packing and padding.
+ - Investigate making arrays of objects not be arrays of pointers.
diff --git a/mojo/public/cpp/bindings/lib/array.cc b/mojo/public/cpp/bindings/lib/array.cc
new file mode 100644
index 0000000..6745adc
--- /dev/null
+++ b/mojo/public/cpp/bindings/lib/array.cc
@@ -0,0 +1,38 @@
+// 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.
+
+#include "mojo/public/cpp/bindings/array.h"
+
+namespace mojo {
+
+// static
+String TypeConverter<String, std::string>::ConvertFrom(const std::string& input,
+ Buffer* buf) {
+ String::Builder result(input.size(), buf);
+ if (!input.empty())
+ memcpy(&result[0], input.data(), input.size());
+ return result.Finish();
+}
+// static
+std::string TypeConverter<String, std::string>::ConvertTo(const String& input) {
+ if (input.is_null() || input.size() == 0)
+ return std::string();
+
+ return std::string(&input[0], &input[0] + input.size());
+}
+
+// static
+String TypeConverter<String, const char*>::ConvertFrom(const char* input,
+ Buffer* buf) {
+ if (!input)
+ return String();
+
+ size_t size = strlen(input);
+ String::Builder result(size, buf);
+ if (size != 0)
+ memcpy(&result[0], input, size);
+ return result.Finish();
+}
+
+} // namespace mojo
diff --git a/mojo/public/cpp/bindings/lib/array_internal.cc b/mojo/public/cpp/bindings/lib/array_internal.cc
new file mode 100644
index 0000000..efdda8c
--- /dev/null
+++ b/mojo/public/cpp/bindings/lib/array_internal.cc
@@ -0,0 +1,59 @@
+// 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.
+
+#include "mojo/public/cpp/bindings/lib/array_internal.h"
+
+namespace mojo {
+namespace internal {
+
+ArrayDataTraits<bool>::BitRef::~BitRef() {
+}
+
+ArrayDataTraits<bool>::BitRef::BitRef(uint8_t* storage, uint8_t mask)
+ : storage_(storage),
+ mask_(mask) {
+}
+
+ArrayDataTraits<bool>::BitRef&
+ArrayDataTraits<bool>::BitRef::operator=(bool value) {
+ if (value) {
+ *storage_ |= mask_;
+ } else {
+ *storage_ &= ~mask_;
+ }
+ return *this;
+}
+
+ArrayDataTraits<bool>::BitRef&
+ArrayDataTraits<bool>::BitRef::operator=(const BitRef& value) {
+ return (*this) = static_cast<bool>(value);
+}
+
+ArrayDataTraits<bool>::BitRef::operator bool() const {
+ return (*storage_ & mask_) != 0;
+}
+
+// static
+void ArraySerializationHelper<Handle>::EncodePointersAndHandles(
+ const ArrayHeader* header,
+ ElementType* elements,
+ std::vector<Handle>* handles) {
+ for (uint32_t i = 0; i < header->num_elements; ++i)
+ EncodeHandle(&elements[i], handles);
+}
+
+// static
+bool ArraySerializationHelper<Handle>::DecodePointersAndHandles(
+ const ArrayHeader* header,
+ ElementType* elements,
+ Message* message) {
+ for (uint32_t i = 0; i < header->num_elements; ++i) {
+ if (!DecodeHandle(&elements[i], message->mutable_handles()))
+ return false;
+ }
+ return true;
+}
+
+} // namespace internal
+} // namespace mojo
diff --git a/mojo/public/cpp/bindings/lib/array_internal.h b/mojo/public/cpp/bindings/lib/array_internal.h
new file mode 100644
index 0000000..978dca3
--- /dev/null
+++ b/mojo/public/cpp/bindings/lib/array_internal.h
@@ -0,0 +1,372 @@
+// 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_PUBLIC_CPP_BINDINGS_LIB_ARRAY_INTERNAL_H_
+#define MOJO_PUBLIC_CPP_BINDINGS_LIB_ARRAY_INTERNAL_H_
+
+#include <new>
+
+#include "mojo/public/cpp/bindings/buffer.h"
+#include "mojo/public/cpp/bindings/lib/bindings_internal.h"
+#include "mojo/public/cpp/bindings/lib/bindings_serialization.h"
+#include "mojo/public/cpp/bindings/passable.h"
+#include "mojo/public/cpp/system/core.h"
+
+namespace mojo {
+template <typename T> class Array;
+
+namespace internal {
+
+template <typename T>
+struct ArrayDataTraits {
+ typedef T StorageType;
+ typedef Array<T> Wrapper;
+ typedef T& Ref;
+ typedef T const& ConstRef;
+
+ static size_t GetStorageSize(size_t num_elements) {
+ return sizeof(StorageType) * num_elements;
+ }
+ static Ref ToRef(StorageType* storage, size_t offset) {
+ return storage[offset];
+ }
+ static ConstRef ToConstRef(const StorageType* storage, size_t offset) {
+ return storage[offset];
+ }
+};
+
+template <typename P>
+struct ArrayDataTraits<P*> {
+ typedef StructPointer<P> StorageType;
+ typedef Array<typename P::Wrapper> Wrapper;
+ typedef P*& Ref;
+ typedef P* const& ConstRef;
+
+ static size_t GetStorageSize(size_t num_elements) {
+ return sizeof(StorageType) * num_elements;
+ }
+ static Ref ToRef(StorageType* storage, size_t offset) {
+ return storage[offset].ptr;
+ }
+ static ConstRef ToConstRef(const StorageType* storage, size_t offset) {
+ return storage[offset].ptr;
+ }
+};
+
+// Specialization of Arrays for bools, optimized for space. It has the
+// following differences from a generalized Array:
+// * Each element takes up a single bit of memory.
+// * Accessing a non-const single element uses a helper class |BitRef|, which
+// emulates a reference to a bool.
+template <>
+struct ArrayDataTraits<bool> {
+ // Helper class to emulate a reference to a bool, used for direct element
+ // access.
+ class BitRef {
+ public:
+ ~BitRef();
+ BitRef& operator=(bool value);
+ BitRef& operator=(const BitRef& value);
+ operator bool() const;
+ private:
+ friend struct ArrayDataTraits<bool>;
+ BitRef(uint8_t* storage, uint8_t mask);
+ BitRef();
+ uint8_t* storage_;
+ uint8_t mask_;
+ };
+
+ typedef uint8_t StorageType;
+ typedef Array<bool> Wrapper;
+ typedef BitRef Ref;
+ typedef bool ConstRef;
+
+ static size_t GetStorageSize(size_t num_elements) {
+ return ((num_elements + 7) / 8);
+ }
+ static BitRef ToRef(StorageType* storage, size_t offset) {
+ return BitRef(&storage[offset / 8], 1 << (offset % 8));
+ }
+ static bool ToConstRef(const StorageType* storage, size_t offset) {
+ return (storage[offset / 8] & (1 << (offset % 8))) != 0;
+ }
+};
+
+// What follows is code to support the serialization of Array_Data<T>. There
+// are two interesting cases: arrays of primitives and arrays of objects.
+// Arrays of objects are represented as arrays of pointers to objects.
+
+template <typename T>
+struct ArraySerializationHelper {
+ typedef T ElementType;
+
+ static size_t ComputeSizeOfElements(const ArrayHeader* header,
+ const ElementType* elements) {
+ return 0;
+ }
+
+ static void CloneElements(const ArrayHeader* header,
+ ElementType* elements,
+ Buffer* buf) {
+ }
+
+ static void EncodePointersAndHandles(const ArrayHeader* header,
+ ElementType* elements,
+ std::vector<Handle>* handles) {
+ }
+
+ static bool DecodePointersAndHandles(const ArrayHeader* header,
+ ElementType* elements,
+ Message* message) {
+ return true;
+ }
+};
+
+template <>
+struct ArraySerializationHelper<Handle> {
+ typedef Handle ElementType;
+
+ static size_t ComputeSizeOfElements(const ArrayHeader* header,
+ const ElementType* elements) {
+ return 0;
+ }
+
+ static void CloneElements(const ArrayHeader* header,
+ ElementType* elements,
+ Buffer* buf) {
+ }
+
+ static void EncodePointersAndHandles(const ArrayHeader* header,
+ ElementType* elements,
+ std::vector<Handle>* handles);
+
+ static bool DecodePointersAndHandles(const ArrayHeader* header,
+ ElementType* elements,
+ Message* message);
+};
+
+template <typename P>
+struct ArraySerializationHelper<P*> {
+ typedef StructPointer<P> ElementType;
+
+ static size_t ComputeSizeOfElements(const ArrayHeader* header,
+ const ElementType* elements) {
+ size_t result = 0;
+ for (uint32_t i = 0; i < header->num_elements; ++i) {
+ if (elements[i].ptr)
+ result += elements[i].ptr->ComputeSize();
+ }
+ return result;
+ }
+
+ static void CloneElements(const ArrayHeader* header,
+ ElementType* elements,
+ Buffer* buf) {
+ for (uint32_t i = 0; i < header->num_elements; ++i) {
+ if (elements[i].ptr)
+ elements[i].ptr = elements[i].ptr->Clone(buf);
+ }
+ }
+
+ static void EncodePointersAndHandles(const ArrayHeader* header,
+ ElementType* elements,
+ std::vector<Handle>* handles) {
+ for (uint32_t i = 0; i < header->num_elements; ++i)
+ Encode(&elements[i], handles);
+ }
+
+ static bool DecodePointersAndHandles(const ArrayHeader* header,
+ ElementType* elements,
+ Message* message) {
+ for (uint32_t i = 0; i < header->num_elements; ++i) {
+ if (!Decode(&elements[i], message))
+ return false;
+ }
+ return true;
+ }
+};
+
+template <typename T>
+class Array_Data {
+ public:
+ typedef ArrayDataTraits<T> Traits;
+ typedef typename Traits::StorageType StorageType;
+ typedef typename Traits::Wrapper Wrapper;
+ typedef typename Traits::Ref Ref;
+ typedef typename Traits::ConstRef ConstRef;
+
+ static Array_Data<T>* New(size_t num_elements, Buffer* buf) {
+ size_t num_bytes = sizeof(Array_Data<T>) +
+ Traits::GetStorageSize(num_elements);
+ return new (buf->Allocate(num_bytes)) Array_Data<T>(num_bytes,
+ num_elements);
+ }
+
+ size_t size() const { return header_.num_elements; }
+
+ Ref at(size_t offset) {
+ assert(offset < static_cast<size_t>(header_.num_elements));
+ return Traits::ToRef(storage(), offset);
+ }
+
+ ConstRef at(size_t offset) const {
+ assert(offset < static_cast<size_t>(header_.num_elements));
+ return Traits::ToConstRef(storage(), offset);
+ }
+
+ StorageType* storage() {
+ return reinterpret_cast<StorageType*>(
+ reinterpret_cast<char*>(this) + sizeof(*this));
+ }
+
+ const StorageType* storage() const {
+ return reinterpret_cast<const StorageType*>(
+ reinterpret_cast<const char*>(this) + sizeof(*this));
+ }
+
+ size_t ComputeSize() const {
+ return Align(header_.num_bytes) +
+ ArraySerializationHelper<T>::ComputeSizeOfElements(&header_, storage());
+ }
+
+ Array_Data<T>* Clone(Buffer* buf) const {
+ Array_Data<T>* clone = New(header_.num_elements, buf);
+ memcpy(clone->storage(),
+ storage(),
+ header_.num_bytes - sizeof(Array_Data<T>));
+
+ ArraySerializationHelper<T>::CloneElements(&clone->header_,
+ clone->storage(), buf);
+ return clone;
+ }
+
+ void CloseHandles() {
+ // TODO(darin): Implement!
+ }
+
+ void EncodePointersAndHandles(std::vector<Handle>* handles) {
+ ArraySerializationHelper<T>::EncodePointersAndHandles(&header_, storage(),
+ handles);
+ }
+
+ bool DecodePointersAndHandles(Message* message) {
+ return ArraySerializationHelper<T>::DecodePointersAndHandles(&header_,
+ storage(),
+ message);
+ }
+
+ private:
+ Array_Data(size_t num_bytes, size_t num_elements) {
+ header_.num_bytes = static_cast<uint32_t>(num_bytes);
+ header_.num_elements = static_cast<uint32_t>(num_elements);
+ }
+ ~Array_Data() {}
+
+ internal::ArrayHeader header_;
+
+ // Elements of type internal::ArrayDataTraits<T>::StorageType follow.
+};
+MOJO_COMPILE_ASSERT(sizeof(Array_Data<char>) == 8, bad_sizeof_Array_Data);
+
+// UTF-8 encoded
+typedef Array_Data<char> String_Data;
+
+template <typename T, bool kIsObject> struct ArrayTraits {};
+
+template <typename T> struct ArrayTraits<T, true> {
+ typedef Array_Data<typename T::Data*> DataType;
+ typedef const T& ConstRef;
+ typedef T& Ref;
+ static typename T::Data* ToArrayElement(const T& value) {
+ return Unwrap(value);
+ }
+ // Something sketchy is indeed happening here...
+ static Ref ToRef(typename T::Data*& data) {
+ return *reinterpret_cast<T*>(&data);
+ }
+ static ConstRef ToConstRef(typename T::Data* const& data) {
+ return *reinterpret_cast<const T*>(&data);
+ }
+};
+
+template <typename T> struct ArrayTraits<T, false> {
+ typedef Array_Data<T> DataType;
+ typedef const T& ConstRef;
+ typedef T& Ref;
+ static T ToArrayElement(const T& value) {
+ return value;
+ }
+ static Ref ToRef(T& data) { return data; }
+ static ConstRef ToConstRef(const T& data) { return data; }
+};
+
+template <> struct ArrayTraits<bool, false> {
+ typedef Array_Data<bool> DataType;
+ typedef bool ConstRef;
+ typedef ArrayDataTraits<bool>::Ref Ref;
+ static bool ToArrayElement(const bool& value) {
+ return value;
+ }
+ static Ref ToRef(const Ref& data) { return data; }
+ static ConstRef ToConstRef(ConstRef data) { return data; }
+};
+
+template <> struct ArrayTraits<Handle, false> {
+ typedef Array_Data<Handle> DataType;
+ typedef Passable<Handle> ConstRef;
+ typedef AssignableAndPassable<Handle> Ref;
+ static Handle ToArrayElement(const Handle& value) {
+ return value;
+ }
+ static Ref ToRef(Handle& data) { return Ref(&data); }
+ static ConstRef ToConstRef(const Handle& data) {
+ return ConstRef(const_cast<Handle*>(&data));
+ }
+};
+
+template <> struct ArrayTraits<DataPipeConsumerHandle, false> {
+ typedef Array_Data<DataPipeConsumerHandle> DataType;
+ typedef Passable<DataPipeConsumerHandle> ConstRef;
+ typedef AssignableAndPassable<DataPipeConsumerHandle> Ref;
+ static DataPipeConsumerHandle ToArrayElement(
+ const DataPipeConsumerHandle& value) {
+ return value;
+ }
+ static Ref ToRef(DataPipeConsumerHandle& data) { return Ref(&data); }
+ static ConstRef ToConstRef(const DataPipeConsumerHandle& data) {
+ return ConstRef(const_cast<DataPipeConsumerHandle*>(&data));
+ }
+};
+
+template <> struct ArrayTraits<DataPipeProducerHandle, false> {
+ typedef Array_Data<DataPipeProducerHandle> DataType;
+ typedef Passable<DataPipeProducerHandle> ConstRef;
+ typedef AssignableAndPassable<DataPipeProducerHandle> Ref;
+ static DataPipeProducerHandle ToArrayElement(
+ const DataPipeProducerHandle& value) {
+ return value;
+ }
+ static Ref ToRef(DataPipeProducerHandle& data) { return Ref(&data); }
+ static ConstRef ToConstRef(const DataPipeProducerHandle& data) {
+ return ConstRef(const_cast<DataPipeProducerHandle*>(&data));
+ }
+};
+
+template <> struct ArrayTraits<MessagePipeHandle, false> {
+ typedef Array_Data<MessagePipeHandle> DataType;
+ typedef Passable<MessagePipeHandle> ConstRef;
+ typedef AssignableAndPassable<MessagePipeHandle> Ref;
+ static MessagePipeHandle ToArrayElement(const MessagePipeHandle& value) {
+ return value;
+ }
+ static Ref ToRef(MessagePipeHandle& data) { return Ref(&data); }
+ static ConstRef ToConstRef(const MessagePipeHandle& data) {
+ return ConstRef(const_cast<MessagePipeHandle*>(&data));
+ }
+};
+
+} // namespace internal
+} // namespace mojo
+
+#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_ARRAY_INTERNAL_H_
diff --git a/mojo/public/cpp/bindings/lib/bindings_internal.h b/mojo/public/cpp/bindings/lib/bindings_internal.h
new file mode 100644
index 0000000..ef6fc47
--- /dev/null
+++ b/mojo/public/cpp/bindings/lib/bindings_internal.h
@@ -0,0 +1,141 @@
+// 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_PUBLIC_CPP_BINDINGS_LIB_BINDINGS_INTERNAL_H_
+#define MOJO_PUBLIC_CPP_BINDINGS_LIB_BINDINGS_INTERNAL_H_
+
+#include "mojo/public/cpp/system/core.h"
+
+namespace mojo {
+namespace internal {
+template <typename T> class Array_Data;
+
+#pragma pack(push, 1)
+
+struct StructHeader {
+ uint32_t num_bytes;
+ uint32_t num_fields;
+};
+MOJO_COMPILE_ASSERT(sizeof(StructHeader) == 8, bad_sizeof_StructHeader);
+
+struct ArrayHeader {
+ uint32_t num_bytes;
+ uint32_t num_elements;
+};
+MOJO_COMPILE_ASSERT(sizeof(ArrayHeader) == 8, bad_sizeof_ArrayHeader);
+
+template <typename T>
+union StructPointer {
+ uint64_t offset;
+ T* ptr;
+};
+MOJO_COMPILE_ASSERT(sizeof(StructPointer<char>) == 8, bad_sizeof_StructPointer);
+
+template <typename T>
+union ArrayPointer {
+ uint64_t offset;
+ Array_Data<T>* ptr;
+};
+MOJO_COMPILE_ASSERT(sizeof(ArrayPointer<char>) == 8, bad_sizeof_ArrayPointer);
+
+union StringPointer {
+ uint64_t offset;
+ Array_Data<char>* ptr;
+};
+MOJO_COMPILE_ASSERT(sizeof(StringPointer) == 8, bad_sizeof_StringPointer);
+
+#pragma pack(pop)
+
+template <typename T>
+void ResetIfNonNull(T* ptr) {
+ if (ptr)
+ *ptr = T();
+}
+
+template <typename T>
+T FetchAndReset(T* ptr) {
+ T temp = *ptr;
+ *ptr = T();
+ return temp;
+}
+
+template <typename T>
+class WrapperHelper {
+ public:
+ static const T Wrap(const typename T::Data* data) {
+ return T(typename T::Wrap(), const_cast<typename T::Data*>(data));
+ }
+ static typename T::Data* Unwrap(const T& object) {
+ return const_cast<typename T::Data*>(object.data_);
+ }
+};
+
+template <typename Data>
+inline const typename Data::Wrapper Wrap(const Data* data) {
+ return WrapperHelper<typename Data::Wrapper>::Wrap(data);
+}
+
+template <typename T>
+inline typename T::Data* Unwrap(const T& object) {
+ return WrapperHelper<T>::Unwrap(object);
+}
+
+template <typename T> struct TypeTraits {
+ static const bool kIsObject = true;
+};
+template <> struct TypeTraits<bool> {
+ static const bool kIsObject = false;
+};
+template <> struct TypeTraits<char> {
+ static const bool kIsObject = false;
+};
+template <> struct TypeTraits<int8_t> {
+ static const bool kIsObject = false;
+};
+template <> struct TypeTraits<int16_t> {
+ static const bool kIsObject = false;
+};
+template <> struct TypeTraits<int32_t> {
+ static const bool kIsObject = false;
+};
+template <> struct TypeTraits<int64_t> {
+ static const bool kIsObject = false;
+};
+template <> struct TypeTraits<uint8_t> {
+ static const bool kIsObject = false;
+};
+template <> struct TypeTraits<uint16_t> {
+ static const bool kIsObject = false;
+};
+template <> struct TypeTraits<uint32_t> {
+ static const bool kIsObject = false;
+};
+template <> struct TypeTraits<uint64_t> {
+ static const bool kIsObject = false;
+};
+template <> struct TypeTraits<float> {
+ static const bool kIsObject = false;
+};
+template <> struct TypeTraits<double> {
+ static const bool kIsObject = false;
+};
+template <> struct TypeTraits<Handle> {
+ static const bool kIsObject = false;
+};
+template <> struct TypeTraits<DataPipeConsumerHandle> {
+ static const bool kIsObject = false;
+};
+template <> struct TypeTraits<DataPipeProducerHandle> {
+ static const bool kIsObject = false;
+};
+template <> struct TypeTraits<MessagePipeHandle> {
+ static const bool kIsObject = false;
+};
+
+template <typename T> class ObjectTraits {};
+
+} // namespace internal
+} // namespace mojo
+
+#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_BINDINGS_INTERNAL_H_
diff --git a/mojo/public/cpp/bindings/lib/bindings_serialization.cc b/mojo/public/cpp/bindings/lib/bindings_serialization.cc
new file mode 100644
index 0000000..ff06d95
--- /dev/null
+++ b/mojo/public/cpp/bindings/lib/bindings_serialization.cc
@@ -0,0 +1,73 @@
+// 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.
+
+#include "mojo/public/cpp/bindings/lib/bindings_serialization.h"
+
+#include <assert.h>
+
+#include "mojo/public/cpp/bindings/lib/bindings_internal.h"
+
+namespace mojo {
+namespace internal {
+
+size_t Align(size_t size) {
+ const size_t kAlignment = 8;
+ return size + (kAlignment - (size % kAlignment)) % kAlignment;
+}
+
+void EncodePointer(const void* ptr, uint64_t* offset) {
+ if (!ptr) {
+ *offset = 0;
+ return;
+ }
+
+ const char* p_obj = reinterpret_cast<const char*>(ptr);
+ const char* p_slot = reinterpret_cast<const char*>(offset);
+ assert(p_obj > p_slot);
+
+ *offset = static_cast<uint64_t>(p_obj - p_slot);
+}
+
+const void* DecodePointerRaw(const uint64_t* offset) {
+ if (!*offset)
+ return NULL;
+ return reinterpret_cast<const char*>(offset) + *offset;
+}
+
+bool ValidatePointer(const void* ptr, const Message& message) {
+ const uint8_t* data = static_cast<const uint8_t*>(ptr);
+ if (reinterpret_cast<ptrdiff_t>(data) % 8 != 0)
+ return false;
+
+ const uint8_t* data_start = message.data();
+ const uint8_t* data_end = data_start + message.data_num_bytes();
+
+ return data >= data_start && data < data_end;
+}
+
+void EncodeHandle(Handle* handle, std::vector<Handle>* handles) {
+ if (handle->is_valid()) {
+ handles->push_back(*handle);
+ handle->set_value(static_cast<MojoHandle>(handles->size() - 1));
+ } else {
+ // Encode -1 to mean the invalid handle.
+ handle->set_value(static_cast<MojoHandle>(-1));
+ }
+}
+
+bool DecodeHandle(Handle* handle, std::vector<Handle>* handles) {
+ // Decode -1 to mean the invalid handle.
+ if (handle->value() == static_cast<MojoHandle>(-1)) {
+ *handle = Handle();
+ return true;
+ }
+ if (handle->value() >= handles->size())
+ return false;
+ // Just leave holes in the vector so we don't screw up other indices.
+ *handle = FetchAndReset(&handles->at(handle->value()));
+ return true;
+}
+
+} // namespace internal
+} // namespace mojo
diff --git a/mojo/public/cpp/bindings/lib/bindings_serialization.h b/mojo/public/cpp/bindings/lib/bindings_serialization.h
new file mode 100644
index 0000000..a860b14
--- /dev/null
+++ b/mojo/public/cpp/bindings/lib/bindings_serialization.h
@@ -0,0 +1,67 @@
+// 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_PUBLIC_CPP_BINDINGS_LIB_BINDINGS_SERIALIZATION_H_
+#define MOJO_PUBLIC_CPP_BINDINGS_LIB_BINDINGS_SERIALIZATION_H_
+
+#include <vector>
+
+#include "mojo/public/cpp/bindings/buffer.h"
+#include "mojo/public/cpp/bindings/message.h"
+
+namespace mojo {
+namespace internal {
+
+size_t Align(size_t size);
+
+// Pointers are encoded as relative offsets. The offsets are relative to the
+// address of where the offset value is stored, such that the pointer may be
+// recovered with the expression:
+//
+// ptr = reinterpret_cast<char*>(offset) + *offset
+//
+// A null pointer is encoded as an offset value of 0.
+//
+void EncodePointer(const void* ptr, uint64_t* offset);
+const void* DecodePointerRaw(const uint64_t* offset);
+
+template <typename T>
+inline void DecodePointer(const uint64_t* offset, T** ptr) {
+ *ptr = reinterpret_cast<T*>(const_cast<void*>(DecodePointerRaw(offset)));
+}
+
+// Check that the given pointer references memory contained within the message.
+bool ValidatePointer(const void* ptr, const Message& message);
+
+// Handles are encoded as indices into a vector of handles. These functions
+// manipulate the value of |handle|, mapping it to and from an index.
+void EncodeHandle(Handle* handle, std::vector<Handle>* handles);
+bool DecodeHandle(Handle* handle, std::vector<Handle>* handles);
+
+// The following 2 functions are used to encode/decode all objects (structs and
+// arrays) in a consistent manner.
+
+template <typename T>
+inline void Encode(T* obj, std::vector<Handle>* handles) {
+ if (obj->ptr)
+ obj->ptr->EncodePointersAndHandles(handles);
+ EncodePointer(obj->ptr, &obj->offset);
+}
+
+template <typename T>
+inline bool Decode(T* obj, Message* message) {
+ DecodePointer(&obj->offset, &obj->ptr);
+ if (obj->ptr) {
+ if (!ValidatePointer(obj->ptr, *message))
+ return false;
+ if (!obj->ptr->DecodePointersAndHandles(message))
+ return false;
+ }
+ return true;
+}
+
+} // namespace internal
+} // namespace mojo
+
+#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_BINDINGS_SERIALIZATION_H_
diff --git a/mojo/public/cpp/bindings/lib/buffer.cc b/mojo/public/cpp/bindings/lib/buffer.cc
new file mode 100644
index 0000000..4404df8
--- /dev/null
+++ b/mojo/public/cpp/bindings/lib/buffer.cc
@@ -0,0 +1,27 @@
+// 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.
+
+#include "mojo/public/cpp/bindings/buffer.h"
+
+#include <assert.h>
+
+#include "mojo/public/cpp/environment/buffer_tls.h"
+#include "mojo/public/cpp/system/macros.h"
+
+namespace mojo {
+
+Buffer::Buffer() {
+ previous_ = internal::SetCurrentBuffer(this);
+}
+
+Buffer::~Buffer() {
+ Buffer* buf MOJO_ALLOW_UNUSED = internal::SetCurrentBuffer(previous_);
+ assert(buf == this);
+}
+
+Buffer* Buffer::current() {
+ return internal::GetCurrentBuffer();
+}
+
+} // namespace mojo
diff --git a/mojo/public/cpp/bindings/lib/callback_internal.h b/mojo/public/cpp/bindings/lib/callback_internal.h
new file mode 100644
index 0000000..4802e43
--- /dev/null
+++ b/mojo/public/cpp/bindings/lib/callback_internal.h
@@ -0,0 +1,55 @@
+// 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_PUBLIC_CPP_BINDINGS_LIB_CALLBACK_INTERNAL_H_
+#define MOJO_PUBLIC_CPP_BINDINGS_LIB_CALLBACK_INTERNAL_H_
+
+#include "mojo/public/cpp/bindings/lib/bindings_internal.h"
+
+namespace mojo {
+namespace internal {
+
+template <typename T, bool is_object_type = TypeTraits<T>::kIsObject>
+struct Callback_ParamTraits {};
+
+template <typename T>
+struct Callback_ParamTraits<T, true> {
+ typedef const T& ForwardType;
+ static const bool kIsScopedHandle = false;
+};
+
+template <typename T>
+struct Callback_ParamTraits<T, false> {
+ typedef T ForwardType;
+ static const bool kIsScopedHandle = false;
+};
+
+template <typename H>
+struct Callback_ParamTraits<ScopedHandleBase<H>, true> {
+ typedef ScopedHandleBase<H> ForwardType;
+ static const bool kIsScopedHandle = true;
+};
+
+template<bool B, typename T = void>
+struct EnableIf {};
+
+template<typename T>
+struct EnableIf<true, T> { typedef T type; };
+
+template <typename T>
+typename EnableIf<!Callback_ParamTraits<T>::kIsScopedHandle, T>::type&
+ Callback_Forward(T& t) {
+ return t;
+}
+
+template <typename T>
+typename EnableIf<Callback_ParamTraits<T>::kIsScopedHandle, T>::type
+ Callback_Forward(T& t) {
+ return t.Pass();
+}
+
+} // namespace internal
+} // namespace mojo
+
+#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_CALLBACK_INTERNAL_H_
diff --git a/mojo/public/cpp/bindings/lib/connector.cc b/mojo/public/cpp/bindings/lib/connector.cc
new file mode 100644
index 0000000..319631c
--- /dev/null
+++ b/mojo/public/cpp/bindings/lib/connector.cc
@@ -0,0 +1,130 @@
+// 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.
+
+#include "mojo/public/cpp/bindings/lib/connector.h"
+
+#include <assert.h>
+#include <stdlib.h>
+
+#include "mojo/public/cpp/bindings/error_handler.h"
+
+namespace mojo {
+namespace internal {
+
+// ----------------------------------------------------------------------------
+
+Connector::Connector(ScopedMessagePipeHandle message_pipe,
+ MojoAsyncWaiter* waiter)
+ : error_handler_(NULL),
+ waiter_(waiter),
+ message_pipe_(message_pipe.Pass()),
+ incoming_receiver_(NULL),
+ async_wait_id_(0),
+ error_(false),
+ drop_writes_(false) {
+ // Even though we don't have an incoming receiver, we still want to monitor
+ // the message pipe to know if is closed or encounters an error.
+ WaitToReadMore();
+}
+
+Connector::~Connector() {
+ if (async_wait_id_)
+ waiter_->CancelWait(waiter_, async_wait_id_);
+}
+
+void Connector::CloseMessagePipe() {
+ Close(message_pipe_.Pass());
+}
+
+bool Connector::Accept(Message* message) {
+ if (error_)
+ return false;
+
+ if (drop_writes_)
+ return true;
+
+ MojoResult rv = WriteMessageRaw(
+ message_pipe_.get(),
+ message->data(),
+ message->data_num_bytes(),
+ message->mutable_handles()->empty() ? NULL :
+ reinterpret_cast<const MojoHandle*>(
+ &message->mutable_handles()->front()),
+ static_cast<uint32_t>(message->mutable_handles()->size()),
+ MOJO_WRITE_MESSAGE_FLAG_NONE);
+
+ switch (rv) {
+ case MOJO_RESULT_OK:
+ // The handles were successfully transferred, so we don't need the message
+ // to track their lifetime any longer.
+ message->mutable_handles()->clear();
+ break;
+ case MOJO_RESULT_FAILED_PRECONDITION:
+ // There's no point in continuing to write to this pipe since the other
+ // end is gone. Avoid writing any future messages. Hide write failures
+ // from the caller since we'd like them to continue consuming any backlog
+ // of incoming messages before regarding the message pipe as closed.
+ drop_writes_ = true;
+ break;
+ default:
+ // This particular write was rejected, presumably because of bad input.
+ // The pipe is not necessarily in a bad state.
+ return false;
+ }
+ return true;
+}
+
+bool Connector::AcceptWithResponder(Message* message,
+ MessageReceiver* responder) {
+ // TODO(darin): Implement this!
+ assert(false);
+ return false;
+}
+
+// static
+void Connector::CallOnHandleReady(void* closure, MojoResult result) {
+ Connector* self = static_cast<Connector*>(closure);
+ self->OnHandleReady(result);
+}
+
+void Connector::OnHandleReady(MojoResult result) {
+ async_wait_id_ = 0;
+
+ if (result == MOJO_RESULT_OK) {
+ ReadMore();
+ } else {
+ error_ = true;
+ }
+
+ if (error_ && error_handler_)
+ error_handler_->OnError();
+}
+
+void Connector::WaitToReadMore() {
+ async_wait_id_ = waiter_->AsyncWait(waiter_,
+ message_pipe_.get().value(),
+ MOJO_WAIT_FLAG_READABLE,
+ MOJO_DEADLINE_INDEFINITE,
+ &Connector::CallOnHandleReady,
+ this);
+}
+
+void Connector::ReadMore() {
+ while (true) {
+ MojoResult rv;
+
+ rv = ReadAndDispatchMessage(message_pipe_.get(), incoming_receiver_, NULL);
+ if (rv == MOJO_RESULT_SHOULD_WAIT) {
+ WaitToReadMore();
+ break;
+ }
+ if (rv != MOJO_RESULT_OK) {
+ error_ = true;
+ break;
+ }
+ }
+}
+
+} // namespace internal
+} // namespace mojo
diff --git a/mojo/public/cpp/bindings/lib/connector.h b/mojo/public/cpp/bindings/lib/connector.h
new file mode 100644
index 0000000..21107d5
--- /dev/null
+++ b/mojo/public/cpp/bindings/lib/connector.h
@@ -0,0 +1,80 @@
+// 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_PUBLIC_CPP_BINDINGS_LIB_CONNECTOR_H_
+#define MOJO_PUBLIC_CPP_BINDINGS_LIB_CONNECTOR_H_
+
+#include "mojo/public/cpp/bindings/lib/message_queue.h"
+#include "mojo/public/cpp/bindings/message.h"
+#include "mojo/public/cpp/environment/default_async_waiter.h"
+#include "mojo/public/cpp/system/core.h"
+
+namespace mojo {
+class ErrorHandler;
+
+namespace internal {
+
+// The Connector class is responsible for performing read/write operations on a
+// MessagePipe. It writes messages it receives through the MessageReceiver
+// interface that it subclasses, and it forwards messages it reads through the
+// MessageReceiver interface assigned as its incoming receiver.
+//
+// NOTE: MessagePipe I/O is non-blocking.
+//
+class Connector : public MessageReceiver {
+ public:
+ // The Connector takes ownership of |message_pipe|.
+ explicit Connector(ScopedMessagePipeHandle message_pipe,
+ MojoAsyncWaiter* waiter = GetDefaultAsyncWaiter());
+ virtual ~Connector();
+
+ // Sets the receiver to handle messages read from the message pipe. The
+ // Connector will read messages from the pipe regardless of whether or not an
+ // incoming receiver has been set.
+ void set_incoming_receiver(MessageReceiver* receiver) {
+ incoming_receiver_ = receiver;
+ }
+
+ // Sets the error handler to receive notifications when an error is
+ // encountered while reading from the pipe or waiting to read from the pipe.
+ void set_error_handler(ErrorHandler* error_handler) {
+ error_handler_ = error_handler;
+ }
+
+ // Returns true if an error was encountered while reading from the pipe or
+ // waiting to read from the pipe.
+ bool encountered_error() const { return error_; }
+
+ // Closes the pipe, triggering the error state.
+ void CloseMessagePipe();
+
+ // MessageReceiver implementation:
+ virtual bool Accept(Message* message) MOJO_OVERRIDE;
+ virtual bool AcceptWithResponder(Message* message, MessageReceiver* responder)
+ MOJO_OVERRIDE;
+
+ private:
+ static void CallOnHandleReady(void* closure, MojoResult result);
+ void OnHandleReady(MojoResult result);
+
+ void WaitToReadMore();
+ void ReadMore();
+
+ ErrorHandler* error_handler_;
+ MojoAsyncWaiter* waiter_;
+
+ ScopedMessagePipeHandle message_pipe_;
+ MessageReceiver* incoming_receiver_;
+
+ MojoAsyncWaitID async_wait_id_;
+ bool error_;
+ bool drop_writes_;
+
+ MOJO_DISALLOW_COPY_AND_ASSIGN(Connector);
+};
+
+} // namespace internal
+} // namespace mojo
+
+#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_CONNECTOR_H_
diff --git a/mojo/public/cpp/bindings/lib/fixed_buffer.cc b/mojo/public/cpp/bindings/lib/fixed_buffer.cc
new file mode 100644
index 0000000..7e19ae2
--- /dev/null
+++ b/mojo/public/cpp/bindings/lib/fixed_buffer.cc
@@ -0,0 +1,54 @@
+// 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.
+
+#include "mojo/public/cpp/bindings/lib/fixed_buffer.h"
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <algorithm>
+
+#include "mojo/public/cpp/bindings/lib/bindings_serialization.h"
+
+namespace mojo {
+namespace internal {
+
+FixedBuffer::FixedBuffer(size_t size)
+ : ptr_(NULL),
+ cursor_(0),
+ size_(internal::Align(size)) {
+ ptr_ = static_cast<char*>(calloc(size_, 1));
+}
+
+FixedBuffer::~FixedBuffer() {
+ free(ptr_);
+}
+
+void* FixedBuffer::Allocate(size_t delta, Destructor dtor) {
+ assert(!dtor);
+
+ delta = internal::Align(delta);
+
+ if (delta == 0 || delta > size_ - cursor_) {
+ assert(false);
+ return NULL;
+ }
+
+ char* result = ptr_ + cursor_;
+ cursor_ += delta;
+
+ return result;
+}
+
+void* FixedBuffer::Leak() {
+ char* ptr = ptr_;
+ ptr_ = NULL;
+ cursor_ = 0;
+ size_ = 0;
+ return ptr;
+}
+
+} // namespace internal
+} // namespace mojo
diff --git a/mojo/public/cpp/bindings/lib/fixed_buffer.h b/mojo/public/cpp/bindings/lib/fixed_buffer.h
new file mode 100644
index 0000000..f4a9905
--- /dev/null
+++ b/mojo/public/cpp/bindings/lib/fixed_buffer.h
@@ -0,0 +1,68 @@
+// 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_PUBLIC_CPP_BINDINGS_LIB_FIXED_BUFFER_H_
+#define MOJO_PUBLIC_CPP_BINDINGS_LIB_FIXED_BUFFER_H_
+
+#include "mojo/public/cpp/bindings/buffer.h"
+#include "mojo/public/cpp/system/macros.h"
+
+namespace mojo {
+namespace internal {
+
+// FixedBuffer provides a simple way to allocate objects within a fixed chunk
+// of memory. Objects are allocated by calling the |Allocate| method, which
+// extends the buffer accordingly. Objects allocated in this way are not freed
+// explicitly. Instead, they remain valid so long as the FixedBuffer remains
+// valid. The Leak method may be used to steal the underlying memory from the
+// FixedBuffer.
+//
+// Typical usage:
+//
+// {
+// FixedBuffer buf(8 + 8);
+//
+// int* a = static_cast<int*>(buf->Allocate(sizeof(int)));
+// *a = 2;
+//
+// double* b = static_cast<double*>(buf->Allocate(sizeof(double)));
+// *b = 3.14f;
+//
+// void* data = buf.Leak();
+// Process(data);
+//
+// free(data);
+// }
+//
+class FixedBuffer : public Buffer {
+ public:
+ explicit FixedBuffer(size_t size);
+ virtual ~FixedBuffer();
+
+ // Grows the buffer by |num_bytes| and returns a pointer to the start of the
+ // addition. The resulting address is 8-byte aligned, and the content of the
+ // memory is zero-filled.
+ virtual void* Allocate(size_t num_bytes, Destructor func = NULL)
+ MOJO_OVERRIDE;
+
+ size_t size() const { return size_; }
+
+ // Returns the internal memory owned by the Buffer to the caller. The Buffer
+ // relinquishes its pointer, effectively resetting the state of the Buffer
+ // and leaving the caller responsible for freeing the returned memory address
+ // when no longer needed.
+ void* Leak();
+
+ private:
+ char* ptr_;
+ size_t cursor_;
+ size_t size_;
+
+ MOJO_DISALLOW_COPY_AND_ASSIGN(FixedBuffer);
+};
+
+} // namespace internal
+} // namespace mojo
+
+#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_FIXED_BUFFER_H_
diff --git a/mojo/public/cpp/bindings/lib/interface.cc b/mojo/public/cpp/bindings/lib/interface.cc
new file mode 100644
index 0000000..3b552be
--- /dev/null
+++ b/mojo/public/cpp/bindings/lib/interface.cc
@@ -0,0 +1,19 @@
+// 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.
+
+#include "mojo/public/cpp/bindings/interface.h"
+
+namespace mojo {
+
+bool NoInterfaceStub::Accept(Message* message) {
+ return false;
+}
+
+bool NoInterfaceStub::AcceptWithResponder(Message* message,
+ MessageReceiver* responder) {
+ return false;
+}
+
+} // namespace mojo
+
diff --git a/mojo/public/cpp/bindings/lib/message.cc b/mojo/public/cpp/bindings/lib/message.cc
new file mode 100644
index 0000000..8ec188e2
--- /dev/null
+++ b/mojo/public/cpp/bindings/lib/message.cc
@@ -0,0 +1,84 @@
+// 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.
+
+#include "mojo/public/cpp/bindings/message.h"
+
+#include <assert.h>
+#include <stdlib.h>
+
+#include <algorithm>
+
+namespace mojo {
+
+Message::Message()
+ : data_num_bytes_(0),
+ data_(NULL) {
+}
+
+Message::~Message() {
+ free(data_);
+
+ for (std::vector<Handle>::iterator it = handles_.begin();
+ it != handles_.end(); ++it) {
+ if (it->is_valid())
+ CloseRaw(*it);
+ }
+}
+
+void Message::AllocUninitializedData(uint32_t num_bytes) {
+ assert(!data_);
+ data_num_bytes_ = num_bytes;
+ data_ = static_cast<internal::MessageData*>(malloc(num_bytes));
+}
+
+void Message::AdoptData(uint32_t num_bytes, internal::MessageData* data) {
+ assert(!data_);
+ data_num_bytes_ = num_bytes;
+ data_ = data;
+}
+
+void Message::Swap(Message* other) {
+ std::swap(data_num_bytes_, other->data_num_bytes_);
+ std::swap(data_, other->data_);
+ std::swap(handles_, other->handles_);
+}
+
+MojoResult ReadAndDispatchMessage(MessagePipeHandle handle,
+ MessageReceiver* receiver,
+ bool* receiver_result) {
+ MojoResult rv;
+
+ uint32_t num_bytes = 0, num_handles = 0;
+ rv = ReadMessageRaw(handle,
+ NULL,
+ &num_bytes,
+ NULL,
+ &num_handles,
+ MOJO_READ_MESSAGE_FLAG_NONE);
+ if (rv != MOJO_RESULT_RESOURCE_EXHAUSTED)
+ return rv;
+
+ Message message;
+ message.AllocUninitializedData(num_bytes);
+ message.mutable_handles()->resize(num_handles);
+
+ rv = ReadMessageRaw(handle,
+ message.mutable_data(),
+ &num_bytes,
+ message.mutable_handles()->empty()
+ ? NULL
+ : reinterpret_cast<MojoHandle*>(
+ &message.mutable_handles()->front()),
+ &num_handles,
+ MOJO_READ_MESSAGE_FLAG_NONE);
+ if (receiver && rv == MOJO_RESULT_OK) {
+ bool result = receiver->Accept(&message);
+ if (receiver_result)
+ *receiver_result = result;
+ }
+
+ return rv;
+}
+
+} // namespace mojo
diff --git a/mojo/public/cpp/bindings/lib/message_builder.cc b/mojo/public/cpp/bindings/lib/message_builder.cc
new file mode 100644
index 0000000..c746644
--- /dev/null
+++ b/mojo/public/cpp/bindings/lib/message_builder.cc
@@ -0,0 +1,52 @@
+// 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.
+
+#include "mojo/public/cpp/bindings/lib/message_builder.h"
+
+#include "mojo/public/cpp/bindings/message.h"
+
+namespace mojo {
+namespace internal {
+
+template <typename Header>
+void Allocate(Buffer* buf, Header** header) {
+ *header = static_cast<Header*>(buf->Allocate(sizeof(Header)));
+ (*header)->num_bytes = sizeof(Header);
+}
+
+MessageBuilder::MessageBuilder(uint32_t name, size_t payload_size)
+ : buf_(sizeof(MessageHeader) + payload_size) {
+ MessageHeader* header;
+ Allocate(&buf_, &header);
+ header->num_fields = 2;
+ header->name = name;
+}
+
+MessageBuilder::~MessageBuilder() {
+}
+
+void MessageBuilder::Finish(Message* message) {
+ uint32_t num_bytes = static_cast<uint32_t>(buf_.size());
+ message->AdoptData(num_bytes, static_cast<MessageData*>(buf_.Leak()));
+}
+
+MessageBuilder::MessageBuilder(size_t size)
+ : buf_(size) {
+}
+
+MessageWithRequestIDBuilder::MessageWithRequestIDBuilder(uint32_t name,
+ size_t payload_size,
+ uint32_t flags,
+ uint64_t request_id)
+ : MessageBuilder(sizeof(MessageHeaderWithRequestID) + payload_size) {
+ MessageHeaderWithRequestID* header;
+ Allocate(&buf_, &header);
+ header->num_fields = 3;
+ header->name = name;
+ header->flags = flags;
+ header->request_id = request_id;
+}
+
+} // namespace internal
+} // namespace mojo
diff --git a/mojo/public/cpp/bindings/lib/message_builder.h b/mojo/public/cpp/bindings/lib/message_builder.h
new file mode 100644
index 0000000..b4988ff9
--- /dev/null
+++ b/mojo/public/cpp/bindings/lib/message_builder.h
@@ -0,0 +1,63 @@
+// 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_PUBLIC_CPP_BINDINGS_LIB_MESSAGE_BUILDER_H_
+#define MOJO_PUBLIC_CPP_BINDINGS_LIB_MESSAGE_BUILDER_H_
+
+#include <stdint.h>
+
+#include "mojo/public/cpp/bindings/lib/fixed_buffer.h"
+#include "mojo/public/cpp/bindings/lib/message_internal.h"
+
+namespace mojo {
+class Message;
+
+namespace internal {
+
+class MessageBuilder {
+ public:
+ MessageBuilder(uint32_t name, size_t payload_size);
+ ~MessageBuilder();
+
+ Buffer* buffer() { return &buf_; }
+
+ // Call Finish when done making allocations in |buffer()|. Upon return,
+ // |message| will contain the message data, and |buffer()| will no longer be
+ // valid to reference.
+ void Finish(Message* message);
+
+ protected:
+ explicit MessageBuilder(size_t size);
+ FixedBuffer buf_;
+
+ MOJO_DISALLOW_COPY_AND_ASSIGN(MessageBuilder);
+};
+
+class MessageWithRequestIDBuilder : public MessageBuilder {
+ public:
+ MessageWithRequestIDBuilder(uint32_t name, size_t payload_size,
+ uint32_t flags, uint64_t request_id);
+};
+
+class RequestMessageBuilder : public MessageWithRequestIDBuilder {
+ public:
+ RequestMessageBuilder(uint32_t name, size_t payload_size)
+ : MessageWithRequestIDBuilder(name, payload_size, kMessageExpectsResponse,
+ 0) {
+ }
+};
+
+class ResponseMessageBuilder : public MessageWithRequestIDBuilder {
+ public:
+ ResponseMessageBuilder(uint32_t name, size_t payload_size,
+ uint64_t request_id)
+ : MessageWithRequestIDBuilder(name, payload_size, kMessageIsResponse,
+ request_id) {
+ }
+};
+
+} // namespace internal
+} // namespace mojo
+
+#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_MESSAGE_BUILDER_H_
diff --git a/mojo/public/cpp/bindings/lib/message_internal.h b/mojo/public/cpp/bindings/lib/message_internal.h
new file mode 100644
index 0000000..3c67902
--- /dev/null
+++ b/mojo/public/cpp/bindings/lib/message_internal.h
@@ -0,0 +1,44 @@
+// 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_PUBLIC_CPP_BINDINGS_LIB_MESSAGE_INTERNAL_H_
+#define MOJO_PUBLIC_CPP_BINDINGS_LIB_MESSAGE_INTERNAL_H_
+
+#include "mojo/public/cpp/bindings/lib/bindings_internal.h"
+
+namespace mojo {
+namespace internal {
+
+#pragma pack(push, 1)
+
+enum {
+ kMessageExpectsResponse = 1 << 0,
+ kMessageIsResponse = 1 << 1
+};
+
+struct MessageHeader : internal::StructHeader {
+ uint32_t name;
+ uint32_t flags;
+};
+MOJO_COMPILE_ASSERT(sizeof(MessageHeader) == 16, bad_sizeof_MessageHeader);
+
+struct MessageHeaderWithRequestID : MessageHeader {
+ uint64_t request_id;
+};
+MOJO_COMPILE_ASSERT(sizeof(MessageHeaderWithRequestID) == 24,
+ bad_sizeof_MessageHeaderWithRequestID);
+
+struct MessageData {
+ MessageHeader header;
+};
+
+MOJO_COMPILE_ASSERT(sizeof(MessageData) == sizeof(MessageHeader),
+ bad_sizeof_MessageData);
+
+#pragma pack(pop)
+
+} // namespace internal
+} // namespace mojo
+
+#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_MESSAGE_INTERNAL_H_
diff --git a/mojo/public/cpp/bindings/lib/message_queue.cc b/mojo/public/cpp/bindings/lib/message_queue.cc
new file mode 100644
index 0000000..1982ccb
--- /dev/null
+++ b/mojo/public/cpp/bindings/lib/message_queue.cc
@@ -0,0 +1,50 @@
+// 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.
+
+#include "mojo/public/cpp/bindings/lib/message_queue.h"
+
+#include <assert.h>
+#include <stddef.h>
+
+#include "mojo/public/cpp/bindings/message.h"
+
+namespace mojo {
+namespace internal {
+
+MessageQueue::MessageQueue() {
+}
+
+MessageQueue::~MessageQueue() {
+ while (!queue_.empty())
+ Pop();
+}
+
+bool MessageQueue::IsEmpty() const {
+ return queue_.empty();
+}
+
+Message* MessageQueue::Peek() {
+ assert(!queue_.empty());
+ return queue_.front();
+}
+
+void MessageQueue::Push(Message* message) {
+ queue_.push(new Message());
+ queue_.back()->Swap(message);
+}
+
+void MessageQueue::Pop(Message* message) {
+ assert(!queue_.empty());
+ queue_.front()->Swap(message);
+ Pop();
+}
+
+void MessageQueue::Pop() {
+ assert(!queue_.empty());
+ delete queue_.front();
+ queue_.pop();
+}
+
+} // namespace internal
+} // namespace mojo
diff --git a/mojo/public/cpp/bindings/lib/message_queue.h b/mojo/public/cpp/bindings/lib/message_queue.h
new file mode 100644
index 0000000..4e46b54
--- /dev/null
+++ b/mojo/public/cpp/bindings/lib/message_queue.h
@@ -0,0 +1,47 @@
+// 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_PUBLIC_CPP_BINDINGS_LIB_MESSAGE_QUEUE_H_
+#define MOJO_PUBLIC_CPP_BINDINGS_LIB_MESSAGE_QUEUE_H_
+
+#include <queue>
+
+#include "mojo/public/cpp/system/macros.h"
+
+namespace mojo {
+class Message;
+
+namespace internal {
+
+// A queue for Message objects.
+class MessageQueue {
+ public:
+ MessageQueue();
+ ~MessageQueue();
+
+ bool IsEmpty() const;
+ Message* Peek();
+
+ // This method transfers ownership of |message->data| and |message->handles|
+ // to the message queue, resetting |message| in the process.
+ void Push(Message* message);
+
+ // Removes the next message from the queue, transferring ownership of its
+ // data and handles to the given |message|.
+ void Pop(Message* message);
+
+ // Removes the next message from the queue, discarding its data and handles.
+ // This is meant to be used in conjunction with |Peek|.
+ void Pop();
+
+ private:
+ std::queue<Message*> queue_;
+
+ MOJO_DISALLOW_COPY_AND_ASSIGN(MessageQueue);
+};
+
+} // namespace internal
+} // namespace mojo
+
+#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_MESSAGE_QUEUE_H_
diff --git a/mojo/public/cpp/bindings/lib/router.cc b/mojo/public/cpp/bindings/lib/router.cc
new file mode 100644
index 0000000..594addc
--- /dev/null
+++ b/mojo/public/cpp/bindings/lib/router.cc
@@ -0,0 +1,137 @@
+// 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.
+
+#include "mojo/public/cpp/bindings/lib/router.h"
+
+namespace mojo {
+namespace internal {
+
+// ----------------------------------------------------------------------------
+
+class ResponderThunk : public MessageReceiver {
+ public:
+ explicit ResponderThunk(const SharedData<Router*>& router)
+ : router_(router) {
+ }
+ virtual ~ResponderThunk() {
+ }
+
+ // MessageReceiver implementation:
+ virtual bool Accept(Message* message) MOJO_OVERRIDE {
+ assert(message->has_flag(kMessageIsResponse));
+
+ bool result = false;
+
+ Router* router = router_.value();
+ if (router)
+ result = router->Accept(message);
+
+ return result;
+ }
+
+ virtual bool AcceptWithResponder(Message* message,
+ MessageReceiver* responder) MOJO_OVERRIDE {
+ assert(false); // not reached!
+ return false;
+ }
+
+ private:
+ SharedData<Router*> router_;
+};
+
+// ----------------------------------------------------------------------------
+
+Router::HandleIncomingMessageThunk::HandleIncomingMessageThunk(Router* router)
+ : router_(router) {
+}
+
+Router::HandleIncomingMessageThunk::~HandleIncomingMessageThunk() {
+}
+
+bool Router::HandleIncomingMessageThunk::Accept(Message* message) {
+ return router_->HandleIncomingMessage(message);
+}
+
+bool Router::HandleIncomingMessageThunk::AcceptWithResponder(
+ Message* message,
+ MessageReceiver* responder) {
+ assert(false); // not reached!
+ return false;
+}
+
+// ----------------------------------------------------------------------------
+
+Router::Router(ScopedMessagePipeHandle message_pipe, MojoAsyncWaiter* waiter)
+ : connector_(message_pipe.Pass(), waiter),
+ weak_self_(this),
+ incoming_receiver_(NULL),
+ thunk_(this),
+ next_request_id_(0) {
+ connector_.set_incoming_receiver(&thunk_);
+}
+
+Router::~Router() {
+ weak_self_.set_value(NULL);
+}
+
+bool Router::Accept(Message* message) {
+ assert(!message->has_flag(kMessageExpectsResponse));
+ return connector_.Accept(message);
+}
+
+bool Router::AcceptWithResponder(Message* message,
+ MessageReceiver* responder) {
+ assert(message->has_flag(kMessageExpectsResponse));
+
+ // Reserve 0 in case we want it to convey special meaning in the future.
+ uint64_t request_id = next_request_id_++;
+ if (request_id == 0)
+ request_id = next_request_id_++;
+
+ message->set_request_id(request_id);
+ if (!connector_.Accept(message))
+ return false;
+
+ // We assume ownership of |responder|.
+ responders_[request_id] = responder;
+ return true;
+}
+
+bool Router::HandleIncomingMessage(Message* message) {
+ if (message->has_flag(kMessageExpectsResponse)) {
+ if (incoming_receiver_) {
+ MessageReceiver* responder = new ResponderThunk(weak_self_);
+ bool ok = incoming_receiver_->AcceptWithResponder(message, responder);
+ if (!ok)
+ delete responder;
+ return ok;
+ }
+
+ // If we receive a request expecting a response when the client is not
+ // listening, then we have no choice but to tear down the pipe.
+ connector_.CloseMessagePipe();
+ } else if (message->has_flag(kMessageIsResponse)) {
+ uint64_t request_id = message->request_id();
+ ResponderMap::iterator it = responders_.find(request_id);
+ if (it == responders_.end()) {
+ assert(false);
+ return false;
+ }
+ MessageReceiver* responder = it->second;
+ responders_.erase(it);
+ responder->Accept(message);
+ delete responder;
+ } else {
+ if (incoming_receiver_)
+ return incoming_receiver_->Accept(message);
+ // OK to drop message on the floor.
+ }
+
+ return false;
+}
+
+// ----------------------------------------------------------------------------
+
+} // namespace internal
+} // namespace mojo
diff --git a/mojo/public/cpp/bindings/lib/router.h b/mojo/public/cpp/bindings/lib/router.h
new file mode 100644
index 0000000..31c05f6
--- /dev/null
+++ b/mojo/public/cpp/bindings/lib/router.h
@@ -0,0 +1,73 @@
+// 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_PUBLIC_CPP_BINDINGS_LIB_ROUTER_H_
+#define MOJO_PUBLIC_CPP_BINDINGS_LIB_ROUTER_H_
+
+#include <map>
+
+#include "mojo/public/cpp/bindings/lib/connector.h"
+#include "mojo/public/cpp/bindings/lib/shared_data.h"
+
+namespace mojo {
+namespace internal {
+
+class Router : public MessageReceiver {
+ public:
+ // The Router takes ownership of |message_pipe|.
+ explicit Router(ScopedMessagePipeHandle message_pipe,
+ MojoAsyncWaiter* waiter = GetDefaultAsyncWaiter());
+ virtual ~Router();
+
+ // Sets the receiver to handle messages read from the message pipe that do
+ // not have the kMessageIsResponse flag set.
+ void set_incoming_receiver(MessageReceiver* receiver) {
+ incoming_receiver_ = receiver;
+ }
+
+ // Sets the error handler to receive notifications when an error is
+ // encountered while reading from the pipe or waiting to read from the pipe.
+ void set_error_handler(ErrorHandler* error_handler) {
+ connector_.set_error_handler(error_handler);
+ }
+
+ // Returns true if an error was encountered while reading from the pipe or
+ // waiting to read from the pipe.
+ bool encountered_error() const { return connector_.encountered_error(); }
+
+ // MessageReceiver implementation:
+ virtual bool Accept(Message* message) MOJO_OVERRIDE;
+ virtual bool AcceptWithResponder(Message* message, MessageReceiver* responder)
+ MOJO_OVERRIDE;
+
+ private:
+ typedef std::map<uint64_t, MessageReceiver*> ResponderMap;
+
+ class HandleIncomingMessageThunk : public MessageReceiver {
+ public:
+ HandleIncomingMessageThunk(Router* router);
+ virtual ~HandleIncomingMessageThunk();
+
+ // MessageReceiver implementation:
+ virtual bool Accept(Message* message) MOJO_OVERRIDE;
+ virtual bool AcceptWithResponder(Message* message,
+ MessageReceiver* responder) MOJO_OVERRIDE;
+ private:
+ Router* router_;
+ };
+
+ bool HandleIncomingMessage(Message* message);
+
+ Connector connector_;
+ SharedData<Router*> weak_self_;
+ MessageReceiver* incoming_receiver_;
+ HandleIncomingMessageThunk thunk_;
+ ResponderMap responders_;
+ uint64_t next_request_id_;
+};
+
+} // namespace internal
+} // namespace mojo
+
+#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_ROUTER_H_
diff --git a/mojo/public/cpp/bindings/lib/scratch_buffer.cc b/mojo/public/cpp/bindings/lib/scratch_buffer.cc
new file mode 100644
index 0000000..cb894e3
--- /dev/null
+++ b/mojo/public/cpp/bindings/lib/scratch_buffer.cc
@@ -0,0 +1,98 @@
+// 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.
+
+#include "mojo/public/cpp/bindings/lib/scratch_buffer.h"
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <algorithm>
+
+#include "mojo/public/cpp/bindings/lib/bindings_serialization.h"
+
+// Scrub memory in debug builds to help catch use-after-free bugs.
+#ifdef NDEBUG
+#define DEBUG_SCRUB(address, size) (void) (address), (void) (size)
+#else
+#define DEBUG_SCRUB(address, size) memset(address, 0xCD, size)
+#endif
+
+namespace mojo {
+namespace internal {
+
+ScratchBuffer::ScratchBuffer()
+ : overflow_(NULL) {
+ fixed_.next = NULL;
+ fixed_.cursor = fixed_data_;
+ fixed_.end = fixed_data_ + kMinSegmentSize;
+}
+
+ScratchBuffer::~ScratchBuffer() {
+ // Invoke destructors in reverse order to mirror allocation order.
+ std::deque<PendingDestructor>::reverse_iterator it;
+ for (it = pending_dtors_.rbegin(); it != pending_dtors_.rend(); ++it)
+ it->func(it->address);
+
+ while (overflow_) {
+ Segment* doomed = overflow_;
+ overflow_ = overflow_->next;
+ DEBUG_SCRUB(doomed, doomed->end - reinterpret_cast<char*>(doomed));
+ free(doomed);
+ }
+ DEBUG_SCRUB(fixed_data_, sizeof(fixed_data_));
+}
+
+void* ScratchBuffer::Allocate(size_t delta, Destructor func) {
+ delta = internal::Align(delta);
+
+ void* result = AllocateInSegment(&fixed_, delta);
+ if (!result) {
+ if (overflow_)
+ result = AllocateInSegment(overflow_, delta);
+
+ if (!result) {
+ AddOverflowSegment(delta);
+ result = AllocateInSegment(overflow_, delta);
+ }
+ }
+
+ if (func) {
+ PendingDestructor dtor;
+ dtor.func = func;
+ dtor.address = result;
+ pending_dtors_.push_back(dtor);
+ }
+ return result;
+}
+
+void* ScratchBuffer::AllocateInSegment(Segment* segment, size_t delta) {
+ void* result;
+ if (static_cast<size_t>(segment->end - segment->cursor) >= delta) {
+ result = segment->cursor;
+ memset(result, 0, delta);
+ segment->cursor += delta;
+ } else {
+ result = NULL;
+ }
+ return result;
+}
+
+void ScratchBuffer::AddOverflowSegment(size_t delta) {
+ if (delta < kMinSegmentSize)
+ delta = kMinSegmentSize;
+
+ // Ensure segment buffer is aligned.
+ size_t segment_size = internal::Align(sizeof(Segment)) + delta;
+
+ Segment* segment = static_cast<Segment*>(malloc(segment_size));
+ segment->next = overflow_;
+ segment->cursor = reinterpret_cast<char*>(segment + 1);
+ segment->end = segment->cursor + delta;
+
+ overflow_ = segment;
+}
+
+} // namespace internal
+} // namespace mojo
diff --git a/mojo/public/cpp/bindings/lib/scratch_buffer.h b/mojo/public/cpp/bindings/lib/scratch_buffer.h
new file mode 100644
index 0000000..462c6fe
--- /dev/null
+++ b/mojo/public/cpp/bindings/lib/scratch_buffer.h
@@ -0,0 +1,54 @@
+// 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_PUBLIC_CPP_BINDINGS_LIB_SCRATCH_BUFFER_H_
+#define MOJO_PUBLIC_CPP_BINDINGS_LIB_SCRATCH_BUFFER_H_
+
+#include <deque>
+
+#include "mojo/public/cpp/bindings/buffer.h"
+#include "mojo/public/cpp/system/macros.h"
+
+namespace mojo {
+namespace internal {
+
+// The following class is designed to be allocated on the stack. If necessary,
+// it will failover to allocating objects on the heap.
+class ScratchBuffer : public Buffer {
+ public:
+ ScratchBuffer();
+ virtual ~ScratchBuffer();
+
+ virtual void* Allocate(size_t num_bytes, Destructor func = NULL)
+ MOJO_OVERRIDE;
+
+ private:
+ enum { kMinSegmentSize = 512 };
+
+ struct Segment {
+ Segment* next;
+ char* cursor;
+ char* end;
+ };
+
+ void* AllocateInSegment(Segment* segment, size_t num_bytes);
+ void AddOverflowSegment(size_t delta);
+
+ char fixed_data_[kMinSegmentSize];
+ Segment fixed_;
+ Segment* overflow_;
+
+ struct PendingDestructor {
+ Destructor func;
+ void* address;
+ };
+ std::deque<PendingDestructor> pending_dtors_;
+
+ MOJO_DISALLOW_COPY_AND_ASSIGN(ScratchBuffer);
+};
+
+} // namespace internal
+} // namespace mojo
+
+#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_SCRATCH_BUFFER_H_
diff --git a/mojo/public/cpp/bindings/lib/shared_data.h b/mojo/public/cpp/bindings/lib/shared_data.h
new file mode 100644
index 0000000..e396b0d
--- /dev/null
+++ b/mojo/public/cpp/bindings/lib/shared_data.h
@@ -0,0 +1,81 @@
+// 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_PUBLIC_CPP_BINDINGS_LIB_SHARED_DATA_H_
+#define MOJO_PUBLIC_CPP_BINDINGS_LIB_SHARED_DATA_H_
+
+namespace mojo {
+namespace internal {
+
+// Used to allocate an instance of T that can be shared via reference counting.
+template <typename T>
+class SharedData {
+ public:
+ ~SharedData() {
+ holder_->Release();
+ }
+
+ SharedData() : holder_(new Holder()) {
+ }
+
+ explicit SharedData(const T& value) : holder_(new Holder(value)) {
+ }
+
+ SharedData(const SharedData<T>& other) : holder_(other.holder_) {
+ holder_->Retain();
+ }
+
+ SharedData<T>& operator=(const SharedData<T>& other) {
+ if (other.holder_ == holder_)
+ return *this;
+ holder_->Release();
+ holder_ = other.holder_;
+ holder_->Retain();
+ }
+
+ void reset() {
+ holder_->Release();
+ holder_ = new Holder();
+ }
+
+ void reset(const T& value) {
+ holder_->Release();
+ holder_ = new Holder(value);
+ }
+
+ void set_value(const T& value) {
+ holder_->value = value;
+ }
+ T* mutable_value() {
+ return &holder_->value;
+ }
+ const T& value() const {
+ return holder_->value;
+ }
+
+ private:
+ class Holder {
+ public:
+ Holder() : value(), ref_count_(1) {
+ }
+ Holder(const T& value) : value(value), ref_count_(1) {
+ }
+
+ void Retain() { ++ref_count_; }
+ void Release() { if (--ref_count_ == 0) delete this; }
+
+ T value;
+
+ private:
+ int ref_count_;
+ MOJO_DISALLOW_COPY_AND_ASSIGN(Holder);
+ };
+
+ Holder* holder_;
+};
+
+} // namespace internal
+} // namespace mojo
+
+#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_SHARED_DATA_H_
diff --git a/mojo/public/cpp/bindings/lib/shared_ptr.h b/mojo/public/cpp/bindings/lib/shared_ptr.h
new file mode 100644
index 0000000..6ae53a5
--- /dev/null
+++ b/mojo/public/cpp/bindings/lib/shared_ptr.h
@@ -0,0 +1,63 @@
+// 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_PUBLIC_CPP_BINDINGS_LIB_SHARED_PTR_H_
+#define MOJO_PUBLIC_CPP_BINDINGS_LIB_SHARED_PTR_H_
+
+#include "mojo/public/cpp/bindings/lib/shared_data.h"
+
+namespace mojo {
+namespace internal {
+
+// Used to manage a heap-allocated instance of P that can be shared via
+// reference counting. When the last reference is dropped, the instance is
+// deleted.
+template <typename P>
+class SharedPtr {
+ public:
+ SharedPtr() {}
+
+ explicit SharedPtr(P* ptr) {
+ impl_.mutable_value()->ptr = ptr;
+ }
+
+ // Default copy-constructor and assignment operator are OK.
+
+ P* get() {
+ return impl_.value().ptr;
+ }
+ const P* get() const {
+ return impl_.value().ptr;
+ }
+
+ P* operator->() { return get(); }
+ const P* operator->() const { return get(); }
+
+ private:
+ class Impl {
+ public:
+ ~Impl() {
+ if (ptr)
+ delete ptr;
+ }
+
+ Impl() : ptr(NULL) {
+ }
+
+ Impl(P* ptr) : ptr(ptr) {
+ }
+
+ P* ptr;
+
+ private:
+ MOJO_DISALLOW_COPY_AND_ASSIGN(Impl);
+ };
+
+ SharedData<Impl> impl_;
+};
+
+} // namespace mojo
+} // namespace internal
+
+#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_SHARED_PTR_H_
diff --git a/mojo/public/cpp/bindings/lib/sync_dispatcher.cc b/mojo/public/cpp/bindings/lib/sync_dispatcher.cc
new file mode 100644
index 0000000..acb537e
--- /dev/null
+++ b/mojo/public/cpp/bindings/lib/sync_dispatcher.cc
@@ -0,0 +1,27 @@
+// 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.
+
+#include "mojo/public/cpp/bindings/sync_dispatcher.h"
+
+#include <stdlib.h>
+
+#include "mojo/public/cpp/bindings/message.h"
+
+namespace mojo {
+
+bool WaitForMessageAndDispatch(MessagePipeHandle handle,
+ MessageReceiver* receiver) {
+ while (true) {
+ bool result;
+ MojoResult rv = ReadAndDispatchMessage(handle, receiver, &result);
+ if (rv == MOJO_RESULT_OK)
+ return result;
+ if (rv == MOJO_RESULT_SHOULD_WAIT)
+ rv = Wait(handle, MOJO_WAIT_FLAG_READABLE, MOJO_DEADLINE_INDEFINITE);
+ if (rv != MOJO_RESULT_OK)
+ return false;
+ }
+}
+
+} // namespace mojo
diff --git a/mojo/public/cpp/bindings/message.h b/mojo/public/cpp/bindings/message.h
index 8df1ce0..58001c6 100644
--- a/mojo/public/cpp/bindings/message.h
+++ b/mojo/public/cpp/bindings/message.h
@@ -9,7 +9,7 @@
#include <vector>
-#include "mojo/public/bindings/lib/message_internal.h"
+#include "mojo/public/cpp/bindings/lib/message_internal.h"
namespace mojo {
diff --git a/mojo/public/cpp/bindings/passable.h b/mojo/public/cpp/bindings/passable.h
index 3d5c2ca..0e109d6 100644
--- a/mojo/public/cpp/bindings/passable.h
+++ b/mojo/public/cpp/bindings/passable.h
@@ -5,7 +5,7 @@
#ifndef MOJO_PUBLIC_CPP_BINDINGS_PASSABLE_H_
#define MOJO_PUBLIC_CPP_BINDINGS_PASSABLE_H_
-#include "mojo/public/bindings/lib/bindings_internal.h"
+#include "mojo/public/cpp/bindings/lib/bindings_internal.h"
#include "mojo/public/cpp/system/core.h"
namespace mojo {
diff --git a/mojo/public/cpp/bindings/remote_ptr.h b/mojo/public/cpp/bindings/remote_ptr.h
index 9bc629f..63ee719 100644
--- a/mojo/public/cpp/bindings/remote_ptr.h
+++ b/mojo/public/cpp/bindings/remote_ptr.h
@@ -7,8 +7,8 @@
#include <assert.h>
-#include "mojo/public/bindings/lib/router.h"
#include "mojo/public/cpp/bindings/interface.h"
+#include "mojo/public/cpp/bindings/lib/router.h"
#include "mojo/public/cpp/system/macros.h"
namespace mojo {