Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 /* | |
| 2 // HYPOTHETICAL IDL: | |
| 3 | |
| 4 struct Bar { | |
| 5 alpha @0 :uint8; | |
| 6 beta @1 :uint8; | |
| 7 gamma @2 :uint8; | |
| 8 }; | |
| 9 | |
| 10 struct Foo { | |
| 11 x @0 :int32; | |
| 12 y @1 :int32; | |
| 13 a @2 :bool; | |
| 14 b @3 :bool; | |
| 15 c @4 :bool; | |
| 16 bar @5 :Bar; | |
| 17 extra_bars @7 :array(Bar) [optional]; | |
| 18 data @6 :array(uint8); | |
| 19 }; | |
| 20 | |
| 21 interface Blah { | |
| 22 Frobinate @0 (foo @0 :Foo, baz @1 :bool); | |
| 23 }; | |
| 24 | |
| 25 */ | |
| 26 | |
| 27 #include <assert.h> | |
| 28 #include <stddef.h> | |
| 29 #include <stdint.h> | |
| 30 #include <stdio.h> | |
| 31 #include <stdlib.h> | |
| 32 #include <string.h> | |
| 33 | |
| 34 #include <new> | |
| 35 #include <vector> | |
| 36 | |
| 37 // This would be part of some header file we'd provide. | |
| 38 | |
| 39 typedef uint32_t Handle; | |
| 40 | |
| 41 struct Message { | |
| 42 uint32_t name; | |
| 43 uint8_t* data_start; | |
| 44 uint8_t* data_end; | |
| 45 Handle* handles_start; | |
| 46 Handle* handles_end; | |
| 47 }; | |
| 48 | |
| 49 struct MessageHeader { | |
| 50 uint32_t num_bytes; | |
| 51 uint32_t name; | |
| 52 }; | |
| 53 | |
| 54 struct StructHeader { | |
| 55 uint32_t num_bytes; | |
| 56 uint32_t num_fields; | |
| 57 }; | |
| 58 | |
| 59 struct ArrayHeader { | |
| 60 uint32_t num_bytes; | |
| 61 uint32_t num_elements; | |
| 62 }; | |
| 63 | |
| 64 template <typename T> class Array; | |
| 65 | |
| 66 template <typename T> | |
| 67 union StructPointer { | |
| 68 uint64_t offset; | |
| 69 T* ptr; | |
| 70 }; | |
| 71 | |
| 72 template <typename T> | |
| 73 union ArrayPointer { | |
| 74 uint64_t offset; | |
| 75 Array<T>* ptr; | |
| 76 }; | |
| 77 | |
| 78 inline void EncodePointer(void* address, uint64_t* offset) { | |
| 79 if (!address) { | |
| 80 *offset = 0; | |
| 81 return; | |
| 82 } | |
| 83 uint8_t* p_obj = reinterpret_cast<uint8_t*>(address); | |
| 84 uint8_t* p_slot = reinterpret_cast<uint8_t*>(offset); | |
| 85 assert(p_obj > p_slot); | |
| 86 *offset = p_obj - p_slot; | |
| 87 } | |
| 88 | |
| 89 template <typename T> | |
| 90 inline void DecodePointer(uint64_t* offset, T** ptr) { | |
| 91 if (!*offset) { | |
| 92 *ptr = NULL; | |
| 93 return; | |
| 94 } | |
| 95 uint8_t* p_slot = reinterpret_cast<uint8_t*>(offset); | |
| 96 *ptr = reinterpret_cast<T*>(p_slot + *offset); | |
|
piman
2013/09/25 17:26:25
Note: strict aliasing rules only allow reinterpret
| |
| 97 } | |
| 98 | |
| 99 template <typename T> | |
| 100 struct ArrayTraits { | |
| 101 typedef T ElementType; | |
| 102 | |
| 103 static T& ToElementRef(ElementType& e) { return e; } | |
| 104 static T const& ToElementConstRef(const ElementType& e) { return e; } | |
| 105 | |
| 106 template <typename Allocator> | |
| 107 static void CloneElements(Allocator* allocator, | |
| 108 ArrayHeader* header, | |
| 109 ElementType* elements) { | |
| 110 } | |
| 111 | |
| 112 static void EncodePointersAndHandles(ArrayHeader* header, | |
| 113 ElementType* elements, | |
| 114 std::vector<Handle>* handles) { | |
| 115 } | |
| 116 static bool DecodePointersAndHandles(ArrayHeader* header, | |
| 117 ElementType* elements, | |
| 118 const Message& message) { | |
| 119 return true; | |
| 120 } | |
| 121 }; | |
| 122 | |
| 123 template <typename P> | |
| 124 struct ArrayTraits<P*> { | |
| 125 typedef StructPointer<P> ElementType; | |
| 126 | |
| 127 static P*& ToElementRef(ElementType& e) { return e.ptr; } | |
| 128 static P* const& ToElementConstRef(const ElementType& e) { return e.ptr; } | |
| 129 | |
| 130 template <typename Allocator> | |
| 131 static void CloneElements(Allocator* allocator, | |
| 132 ArrayHeader* header, | |
| 133 ElementType* elements) { | |
| 134 for (uint32_t i = 0; i < header->num_elements; ++i) { | |
| 135 if (elements[i].ptr) | |
| 136 elements[i].ptr = elements[i].ptr->Clone(allocator); | |
| 137 } | |
| 138 } | |
| 139 | |
| 140 static void EncodePointersAndHandles(ArrayHeader* header, | |
| 141 ElementType* elements, | |
| 142 std::vector<Handle>* handles) { | |
| 143 for (uint32_t i = 0; i < header->num_elements; ++i) { | |
| 144 if (elements[i].ptr) | |
| 145 elements[i].ptr->EncodePointersAndHandles(handles); | |
| 146 EncodePointer(elements[i].ptr, &elements[i].offset); | |
| 147 } | |
| 148 } | |
| 149 static bool DecodePointersAndHandles(ArrayHeader* header, | |
| 150 ElementType* elements, | |
| 151 const Message& message) { | |
| 152 for (uint32_t i = 0; i < header->num_elements; ++i) { | |
| 153 DecodePointer(&elements[i].offset, &elements[i].ptr); | |
| 154 if (elements[i].ptr) | |
| 155 elements[i].ptr->DecodePointersAndHandles(message); | |
| 156 } | |
| 157 return true; | |
| 158 } | |
| 159 }; | |
| 160 | |
| 161 template <typename T> | |
| 162 class Array { | |
| 163 public: | |
| 164 explicit Array(size_t num_elements) { | |
| 165 // TODO: bools should get packed to a single bit? | |
| 166 header_.num_bytes = | |
| 167 sizeof(typename ArrayTraits<T>::ElementType) * num_elements + | |
| 168 sizeof(ArrayHeader); | |
| 169 header_.num_elements = num_elements; | |
| 170 } | |
| 171 | |
| 172 template <typename Allocator> | |
| 173 Array<T>* Clone(Allocator* allocator) const { | |
| 174 Array<T>* array = | |
| 175 reinterpret_cast<Array<T>*>(allocator->AllocBytes(header_.num_bytes)); | |
| 176 memcpy(array, this, header_.num_bytes); | |
| 177 | |
| 178 ArrayTraits<T>::CloneElements(allocator, &array->header_, array->elements_); | |
| 179 return array; | |
| 180 } | |
| 181 | |
| 182 void EncodePointersAndHandles(std::vector<Handle>* handles) { | |
| 183 ArrayTraits<T>::EncodePointersAndHandles(&header_, elements_, handles); | |
| 184 } | |
| 185 bool DecodePointersAndHandles(const Message& message) { | |
| 186 return ArrayTraits<T>::DecodePointersAndHandles(&header_, elements_, | |
| 187 message); | |
| 188 } | |
| 189 | |
| 190 size_t size() const { return header_.num_elements; } | |
| 191 | |
| 192 T& at(size_t offset) { | |
| 193 return ArrayTraits<T>::ToElementRef(elements_[offset]); | |
| 194 } | |
| 195 | |
| 196 const T& at(size_t offset) const { | |
| 197 return ArrayTraits<T>::ToElementConstRef(elements_[offset]); | |
| 198 } | |
| 199 | |
| 200 T& operator[](size_t offset) { | |
| 201 return ArrayTraits<T>::ToElementRef(elements_[offset]); | |
| 202 } | |
| 203 | |
| 204 const T& operator[](size_t offset) const { | |
| 205 return ArrayTraits<T>::ToElementConstRef(elements_[offset]); | |
| 206 } | |
| 207 | |
| 208 private: | |
| 209 ArrayHeader header_; | |
| 210 typename ArrayTraits<T>::ElementType elements_[1]; // Extra elements follow. | |
| 211 }; | |
| 212 | |
| 213 // The following is a cheezy arena allocator. | |
| 214 class Buffer { | |
| 215 public: | |
| 216 Buffer() : ptr_(NULL), size_(0) { | |
| 217 } | |
| 218 ~Buffer() { free(ptr_); } | |
| 219 | |
| 220 const uint8_t* data() const { return ptr_; } | |
| 221 uint8_t* data() { return ptr_; } | |
| 222 | |
| 223 size_t size() const { return size_; } | |
| 224 | |
| 225 uint8_t* AllocBytes(size_t size) { | |
| 226 return Grow(size); | |
| 227 } | |
| 228 | |
| 229 template <typename T> | |
| 230 T* Alloc() { | |
| 231 size_t size = sizeof(T); | |
| 232 return new (Grow(size)) T(); | |
| 233 } | |
| 234 | |
| 235 template <typename T> | |
| 236 Array<T>* AllocArray(size_t count) { | |
| 237 // (count - 1) because Array<T> has reserved space for the first element. | |
| 238 size_t size = sizeof(Array<T>) + sizeof(T) * (count - 1); | |
| 239 return new (Grow(size)) Array<T>(count); | |
| 240 } | |
| 241 | |
| 242 private: | |
| 243 uint8_t* Grow(size_t delta) { | |
| 244 // TODO: Align allocations | |
| 245 size_t old_size = size_; | |
| 246 size_t new_size = old_size + delta; | |
| 247 ptr_ = static_cast<uint8_t*>(realloc(ptr_, old_size + delta)); | |
| 248 size_ = new_size; | |
| 249 uint8_t* result = ptr_ + old_size; | |
| 250 memset(result, 0, delta); | |
| 251 return result; | |
| 252 } | |
| 253 | |
| 254 uint8_t* ptr_; | |
| 255 size_t size_; | |
| 256 | |
| 257 // NOT IMPLEMENTED | |
| 258 Buffer(const Buffer&); | |
| 259 void operator=(const Buffer&); | |
| 260 }; | |
| 261 | |
| 262 //---- | |
| 263 // Begin generated code. | |
| 264 | |
| 265 // What follows is class definitions corresponding to the structures indicated | |
| 266 // by the IDL. | |
| 267 | |
| 268 class Bar { | |
| 269 public: | |
| 270 Bar() { | |
| 271 header_.num_bytes = sizeof(*this) + sizeof(StructHeader); | |
| 272 header_.num_fields = 3; | |
| 273 } | |
| 274 | |
| 275 Bar* Clone(Buffer* buf) const { | |
| 276 Bar* bar = buf->Alloc<Bar>(); | |
| 277 memcpy(bar, this, sizeof(*this)); | |
| 278 return bar; | |
| 279 } | |
| 280 | |
| 281 void EncodePointersAndHandles(std::vector<Handle>* handles) { | |
| 282 } | |
| 283 bool DecodePointersAndHandles(const Message& message) { | |
| 284 return true; | |
| 285 } | |
| 286 | |
| 287 void set_alpha(uint8_t alpha) { d_.alpha = alpha; } | |
| 288 void set_beta(uint8_t beta) { d_.beta = beta; } | |
| 289 void set_gamma(uint8_t gamma) { d_.gamma = gamma; } | |
| 290 | |
| 291 uint8_t alpha() const { return d_.alpha; } | |
| 292 uint8_t beta() const { return d_.beta; } | |
| 293 uint8_t gamma() const { return d_.gamma; } | |
| 294 | |
| 295 private: | |
| 296 StructHeader header_; | |
|
Hajime Morrita
2013/09/25 20:03:55
One possible alternative is to keep the message cl
| |
| 297 struct { | |
| 298 uint8_t alpha; | |
| 299 uint8_t beta; | |
| 300 uint8_t gamma; | |
| 301 } d_; | |
| 302 | |
| 303 ~Bar(); // NOT IMPLEMENTED | |
| 304 }; | |
| 305 | |
| 306 class Foo { | |
| 307 public: | |
| 308 Foo() { | |
| 309 header_.num_bytes = sizeof(*this) + sizeof(StructHeader); | |
| 310 header_.num_fields = 8; | |
| 311 } | |
| 312 | |
| 313 Foo* Clone(Buffer* buf) const { | |
| 314 Foo* foo = buf->Alloc<Foo>(); | |
| 315 memcpy(foo, this, sizeof(*this)); | |
| 316 | |
| 317 foo->set_bar(foo->bar()->Clone(buf)); | |
| 318 foo->set_data(foo->data()->Clone(buf)); | |
| 319 foo->set_extra_bars(foo->extra_bars()->Clone(buf)); | |
| 320 | |
| 321 return foo; | |
| 322 } | |
| 323 | |
| 324 void EncodePointersAndHandles(std::vector<Handle>* handles) { | |
| 325 if (d_.bar.ptr) | |
| 326 d_.bar.ptr->EncodePointersAndHandles(handles); | |
| 327 EncodePointer(d_.bar.ptr, &d_.bar.offset); | |
| 328 | |
| 329 if (d_.data.ptr) | |
| 330 d_.data.ptr->EncodePointersAndHandles(handles); | |
| 331 EncodePointer(d_.data.ptr, &d_.data.offset); | |
| 332 | |
| 333 if (d_.extra_bars.ptr) | |
| 334 d_.extra_bars.ptr->EncodePointersAndHandles(handles); | |
| 335 EncodePointer(d_.extra_bars.ptr, &d_.extra_bars.offset); | |
| 336 } | |
| 337 | |
| 338 bool DecodePointersAndHandles(const Message& message) { | |
| 339 DecodePointer(&d_.bar.offset, &d_.bar.ptr); | |
| 340 if (d_.bar.ptr) { | |
| 341 if (!d_.bar.ptr->DecodePointersAndHandles(message)) | |
| 342 return false; | |
| 343 } | |
| 344 | |
| 345 DecodePointer(&d_.data.offset, &d_.data.ptr); | |
| 346 if (d_.data.ptr) { | |
| 347 if (!d_.data.ptr->DecodePointersAndHandles(message)) | |
| 348 return false; | |
| 349 } | |
| 350 | |
| 351 if (header_.num_fields >= 8) { | |
| 352 DecodePointer(&d_.extra_bars.offset, &d_.extra_bars.ptr); | |
| 353 if (d_.extra_bars.ptr) { | |
| 354 if (!d_.extra_bars.ptr->DecodePointersAndHandles(message)) | |
| 355 return false; | |
| 356 } | |
| 357 } | |
| 358 | |
| 359 // TODO: validate | |
| 360 return true; | |
| 361 } | |
| 362 | |
| 363 void set_x(int32_t x) { d_.x = x; } | |
| 364 void set_y(int32_t y) { d_.y = y; } | |
| 365 void set_a(bool a) { d_.a = a; } | |
| 366 void set_b(bool b) { d_.b = b; } | |
| 367 void set_c(bool c) { d_.c = c; } | |
| 368 void set_bar(Bar* bar) { d_.bar.ptr = bar; } | |
| 369 void set_data(Array<uint8_t>* data) { d_.data.ptr = data; } | |
| 370 void set_extra_bars(Array<Bar*>* extra_bars) { | |
| 371 d_.extra_bars.ptr = extra_bars; | |
| 372 } | |
| 373 | |
| 374 int32_t x() const { return d_.x; } | |
| 375 int32_t y() const { return d_.y; } | |
| 376 bool a() const { return d_.a; } | |
| 377 bool b() const { return d_.b; } | |
| 378 bool c() const { return d_.c; } | |
| 379 const Bar* bar() const { return d_.bar.ptr; } | |
| 380 const Array<uint8_t>* data() const { return d_.data.ptr; } | |
| 381 const Array<Bar*>* extra_bars() const { | |
| 382 // NOTE: extra_bars is an optional field! | |
| 383 return header_.num_fields >= 8 ? d_.extra_bars.ptr : NULL; | |
| 384 } | |
| 385 | |
| 386 private: | |
| 387 StructHeader header_; | |
| 388 struct { | |
| 389 int32_t x; | |
| 390 int32_t y; | |
| 391 uint32_t a : 1; | |
| 392 uint32_t b : 1; | |
| 393 uint32_t c : 1; | |
| 394 StructPointer<Bar> bar; | |
| 395 ArrayPointer<uint8_t> data; | |
| 396 ArrayPointer<Bar*> extra_bars; | |
| 397 } d_; | |
| 398 | |
| 399 ~Foo(); // NOT IMPLEMENTED | |
| 400 }; | |
| 401 | |
| 402 class Frobinate_Params { | |
| 403 public: | |
| 404 Frobinate_Params() { | |
| 405 header_.num_bytes = sizeof(*this) + sizeof(StructHeader); | |
| 406 header_.num_fields = 2; | |
| 407 } | |
| 408 | |
| 409 void EncodePointersAndHandles(std::vector<Handle>* handles) { | |
| 410 if (d_.foo.ptr) | |
| 411 d_.foo.ptr->EncodePointersAndHandles(handles); | |
| 412 EncodePointer(d_.foo.ptr, &d_.foo.offset); | |
| 413 } | |
| 414 bool DecodePointersAndHandles(const Message& message) { | |
| 415 DecodePointer(&d_.foo.offset, &d_.foo.ptr); | |
| 416 if (d_.foo.ptr) { | |
| 417 if (!d_.foo.ptr->DecodePointersAndHandles(message)) | |
| 418 return false; | |
| 419 } | |
| 420 // TODO: validate | |
| 421 return true; | |
| 422 } | |
| 423 | |
| 424 void set_foo(Foo* foo) { d_.foo.ptr = foo; } | |
| 425 void set_baz(bool baz) { d_.baz = baz; } | |
| 426 | |
| 427 const Foo* foo() const { return d_.foo.ptr; } | |
| 428 bool baz() const { return d_.baz; } | |
| 429 | |
| 430 private: | |
| 431 StructHeader header_; | |
| 432 struct { | |
| 433 StructPointer<Foo> foo; | |
| 434 uint32_t baz : 1; | |
| 435 } d_; | |
| 436 | |
| 437 ~Frobinate_Params(); // NOT IMPLEMENTED | |
| 438 }; | |
| 439 | |
| 440 const uint32_t kMessageID_Frobinate = 1; | |
| 441 | |
| 442 //---- | |
| 443 // The following code would also be generated by our bindings system. | |
| 444 | |
| 445 class Blah { | |
| 446 public: | |
| 447 virtual void Frobinate(const Foo* foo, bool baz) = 0; | |
| 448 }; | |
| 449 | |
| 450 class BlahStub : public Blah { | |
| 451 public: | |
| 452 bool OnMessageReceived(const Message& message) { | |
| 453 switch (message.name) { | |
| 454 case kMessageID_Frobinate: { | |
| 455 Frobinate_Params* params = | |
| 456 reinterpret_cast<Frobinate_Params*>(message.data_start); | |
| 457 if (!params->DecodePointersAndHandles(message)) | |
| 458 return false; | |
| 459 Frobinate(params->foo(), params->baz()); | |
| 460 break; | |
| 461 } | |
| 462 } | |
| 463 return true; | |
| 464 } | |
| 465 }; | |
| 466 | |
| 467 class BlahProxy : public Blah { | |
| 468 public: | |
| 469 virtual void SendMessage(const Message& message) = 0; | |
| 470 | |
| 471 virtual void Frobinate(const Foo* foo, bool baz) { | |
| 472 Buffer buf; | |
| 473 | |
| 474 // TODO: We should allocate the MessageHeader here to reserve space. | |
| 475 //MessageHeader* header = buf.Alloc<MessageHeader>(); | |
| 476 | |
| 477 // We now go about allocating the anonymous Frobinate_Params struct. It | |
| 478 // holds the parameters to the Frobinate message. | |
| 479 // | |
| 480 // Notice how foo is cloned. This causes a copy of foo to be generated | |
| 481 // within the same buffer as the Frobinate_Params struct. That's what we | |
| 482 // need in order to generate a continguous blob of message data. | |
| 483 | |
| 484 Frobinate_Params* params = buf.Alloc<Frobinate_Params>(); | |
| 485 params->set_foo(foo->Clone(&buf)); | |
| 486 params->set_baz(baz); | |
| 487 | |
| 488 // NOTE: If foo happened to be a graph with cycles, then Clone would not | |
| 489 // have returned. | |
| 490 | |
| 491 // Last step before sending the message is to encode pointers and handles | |
| 492 // so that messages become hermetic. Pointers become offsets and handles | |
| 493 // becomes indices into the handles array. | |
| 494 | |
| 495 std::vector<Handle> handles; | |
| 496 params->EncodePointersAndHandles(&handles); | |
| 497 | |
| 498 Message message; | |
| 499 message.name = kMessageID_Frobinate; | |
| 500 message.data_start = buf.data(); | |
| 501 message.data_end = buf.data() + buf.size(); | |
| 502 message.handles_start = &handles[0]; | |
| 503 message.handles_end = &handles[0] + handles.size(); | |
| 504 | |
| 505 SendMessage(message); | |
| 506 } | |
| 507 }; | |
| 508 | |
| 509 //---- | |
| 510 // User code goes here: | |
| 511 | |
| 512 static void PrintSpacer(int depth) { | |
| 513 for (int i = 0; i < depth; ++i) | |
| 514 printf(" "); | |
| 515 } | |
| 516 | |
| 517 static void Print(int depth, const char* name, bool value) { | |
| 518 PrintSpacer(depth); | |
| 519 printf("%s: %s\n", name, value ? "true" : "false"); | |
| 520 } | |
| 521 | |
| 522 static void Print(int depth, const char* name, int32_t value) { | |
| 523 PrintSpacer(depth); | |
| 524 printf("%s: %d\n", name, value); | |
| 525 } | |
| 526 | |
| 527 static void Print(int depth, const char* name, uint8_t value) { | |
| 528 PrintSpacer(depth); | |
| 529 printf("%s: %u\n", name, value); | |
| 530 } | |
| 531 | |
| 532 template <typename T> | |
| 533 static void Print(int depth, const char* name, const Array<T>* array) { | |
| 534 PrintSpacer(depth); | |
| 535 printf("%s: %p\n", name, array); | |
| 536 if (array) { | |
| 537 ++depth; | |
| 538 for (size_t i = 0; i < array->size(); ++i) { | |
| 539 char buf[32]; | |
| 540 sprintf(buf, "%lu", i); | |
| 541 Print(depth, buf, array->at(i)); | |
| 542 } | |
| 543 --depth; | |
| 544 } | |
| 545 } | |
| 546 | |
| 547 static void Print(int depth, const char* name, const Bar* bar) { | |
| 548 PrintSpacer(depth); | |
| 549 printf("%s: %p\n", name, bar); | |
| 550 if (bar) { | |
| 551 ++depth; | |
| 552 Print(depth, "alpha", bar->alpha()); | |
| 553 Print(depth, "beta", bar->beta()); | |
| 554 Print(depth, "gamma", bar->gamma()); | |
| 555 --depth; | |
| 556 } | |
| 557 } | |
| 558 | |
| 559 static void Print(int depth, const char* name, const Foo* foo) { | |
| 560 PrintSpacer(depth); | |
| 561 printf("%s: %p\n", name, foo); | |
| 562 if (foo) { | |
| 563 ++depth; | |
| 564 Print(depth, "x", foo->x()); | |
| 565 Print(depth, "y", foo->y()); | |
| 566 Print(depth, "a", foo->a()); | |
| 567 Print(depth, "b", foo->b()); | |
| 568 Print(depth, "c", foo->c()); | |
| 569 Print(depth, "bar", foo->bar()); | |
| 570 Print(depth, "data", foo->data()); | |
| 571 Print(depth, "extra_bars", foo->extra_bars()); | |
| 572 --depth; | |
| 573 } | |
| 574 } | |
| 575 | |
| 576 class BlahImpl : public BlahStub { | |
| 577 public: | |
| 578 virtual void Frobinate(const Foo* foo, bool baz) { | |
| 579 // Users code goes here to handle the incoming Frobinate message. | |
| 580 // We'll just dump the Foo structure and all of its members. | |
| 581 | |
| 582 printf("Frobinate:\n"); | |
| 583 | |
| 584 int depth = 1; | |
| 585 Print(depth, "foo", foo); | |
| 586 Print(depth, "baz", baz); | |
| 587 } | |
| 588 }; | |
| 589 | |
| 590 //---- | |
| 591 | |
| 592 class BlahProxyImpl : public BlahProxy { | |
| 593 public: | |
| 594 virtual void SendMessage(const Message& message) { | |
| 595 // Imagine some IPC happened here. | |
| 596 | |
| 597 // In the receiving process, an implementation of BlahStub is known to the | |
| 598 // system. It receives the incoming message. | |
| 599 BlahImpl impl; | |
| 600 BlahStub* stub = &impl; | |
| 601 | |
| 602 stub->OnMessageReceived(message); | |
| 603 } | |
| 604 }; | |
| 605 | |
| 606 int main() { | |
| 607 // User has a proxy to a Blah somehow. | |
| 608 Blah* blah = new BlahProxyImpl(); | |
| 609 | |
| 610 // User constructs a message to send. | |
| 611 | |
| 612 // Notice that it doesn't matter in what order the structs / arrays are | |
| 613 // allocated. Here, the various members of Foo are allocated before Foo is | |
| 614 // allocated. | |
| 615 | |
| 616 Buffer buf; | |
| 617 | |
| 618 Bar* bar = buf.Alloc<Bar>(); | |
| 619 bar->set_alpha(20); | |
| 620 bar->set_beta(40); | |
| 621 bar->set_gamma(60); | |
| 622 | |
| 623 const size_t kNumDataElements = 10; | |
| 624 Array<uint8_t>* data = buf.AllocArray<uint8_t>(kNumDataElements); | |
| 625 for (size_t i = 0; i < kNumDataElements; ++i) | |
| 626 (*data)[i] = static_cast<uint8_t>(kNumDataElements - i); | |
| 627 | |
| 628 const size_t kNumExtraBarsElements = 3; | |
| 629 Array<Bar*>* extra_bars = buf.AllocArray<Bar*>(kNumExtraBarsElements); | |
| 630 for (size_t i = 0; i < kNumExtraBarsElements; ++i) { | |
| 631 Bar* bar = buf.Alloc<Bar>(); | |
| 632 bar->set_alpha(i * 100); | |
| 633 bar->set_beta(i * 100 + 20); | |
| 634 bar->set_gamma(i * 100 + 40); | |
| 635 (*extra_bars)[i] = bar; | |
| 636 } | |
| 637 | |
| 638 Foo* foo = buf.Alloc<Foo>(); | |
| 639 foo->set_x(1); | |
| 640 foo->set_y(2); | |
| 641 foo->set_a(false); | |
| 642 foo->set_b(true); | |
| 643 foo->set_c(false); | |
| 644 foo->set_bar(bar); | |
| 645 foo->set_data(data); | |
| 646 foo->set_extra_bars(extra_bars); | |
| 647 | |
| 648 blah->Frobinate(foo, true); | |
| 649 | |
| 650 return 0; | |
| 651 } | |
| OLD | NEW |