| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent 9891811 commit 56fe9ba
2 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -515,19 +515,8 @@ void Message::MemoryInfo(MemoryTracker* tracker) const { | |||
| 515 | 515 | tracker->TrackField("transferables", transferables_); | |
| 516 | 516 | } | |
| 517 | 517 | ||
| 518 | - // TODO(@jasnell): The name here will be an empty string if the | ||
| 519 | - // one-to-one MessageChannel is used. In such cases, | ||
| 520 | - // SiblingGroup::Get() will return nothing and group_ will be | ||
| 521 | - // an empty pointer. @addaleax suggests that the code here | ||
| 522 | - // could be clearer if attaching the SiblingGroup were a | ||
| 523 | - // separate step rather than part of the constructor here. | ||
| 524 | - MessagePortData::MessagePortData( | ||
| 525 | - MessagePort* owner, | ||
| 526 | - const std::string& name) | ||
| 527 | - : owner_(owner), | ||
| 528 | - group_(SiblingGroup::Get(name)) { | ||
| 529 | - if (group_) | ||
| 530 | - group_->Entangle(this); | ||
| 518 | + MessagePortData::MessagePortData(MessagePort* owner) | ||
| 519 | + : owner_(owner) { | ||
| 531 | 520 | } | |
| 532 | 521 | ||
| 533 | 522 | MessagePortData::~MessagePortData() { | |
@@ -552,17 +541,13 @@ void MessagePortData::AddToIncomingQueue(std::shared_ptr<Message> message) { | |||
| 552 | 541 | } | |
| 553 | 542 | ||
| 554 | 543 | void MessagePortData::Entangle(MessagePortData* a, MessagePortData* b) { | |
| 555 | - CHECK(!a->group_); | ||
| 556 | - CHECK(!b->group_); | ||
| 557 | - b->group_ = a->group_ = std::make_shared<SiblingGroup>(); | ||
| 558 | - a->group_->Entangle(a); | ||
| 559 | - a->group_->Entangle(b); | ||
| 544 | + auto group = std::make_shared<SiblingGroup>(); | ||
| 545 | + group->Entangle({a, b}); | ||
| 560 | 546 | } | |
| 561 | 547 | ||
| 562 | 548 | void MessagePortData::Disentangle() { | |
| 563 | 549 | if (group_) { | |
| 564 | 550 | group_->Disentangle(this); | |
| 565 | - group_.reset(); | ||
| 566 | 551 | } | |
| 567 | 552 | } | |
| 568 | 553 | ||
@@ -572,13 +557,12 @@ MessagePort::~MessagePort() { | |||
| 572 | 557 | ||
| 573 | 558 | MessagePort::MessagePort(Environment* env, | |
| 574 | 559 | Local<Context> context, | |
| 575 | - Local<Object> wrap, | ||
| 576 | - const std::string& name) | ||
| 560 | + Local<Object> wrap) | ||
| 577 | 561 | : HandleWrap(env, | |
| 578 | 562 | wrap, | |
| 579 | 563 | reinterpret_cast<uv_handle_t*>(&async_), | |
| 580 | 564 | AsyncWrap::PROVIDER_MESSAGEPORT), | |
| 581 | - data_(new MessagePortData(this, name)) { | ||
| 565 | + data_(new MessagePortData(this)) { | ||
| 582 | 566 | auto onmessage = [](uv_async_t* handle) { | |
| 583 | 567 | // Called when data has been put into the queue. | |
| 584 | 568 | MessagePort* channel = ContainerOf(&MessagePort::async_, handle); | |
@@ -645,7 +629,7 @@ MessagePort* MessagePort::New( | |||
| 645 | 629 | Environment* env, | |
| 646 | 630 | Local<Context> context, | |
| 647 | 631 | std::unique_ptr<MessagePortData> data, | |
| 648 | - const std::string& name) { | ||
| 632 | + std::shared_ptr<SiblingGroup> sibling_group) { | ||
| 649 | 633 | Context::Scope context_scope(context); | |
| 650 | 634 | Local<FunctionTemplate> ctor_templ = GetMessagePortConstructorTemplate(env); | |
| 651 | 635 | ||
@@ -654,14 +638,15 @@ MessagePort* MessagePort::New( | |||
| 654 | 638 | Local<Object> instance; | |
| 655 | 639 | if (!ctor_templ->InstanceTemplate()->NewInstance(context).ToLocal(&instance)) | |
| 656 | 640 | return nullptr; | |
| 657 | - MessagePort* port = new MessagePort(env, context, instance, name); | ||
| 641 | + MessagePort* port = new MessagePort(env, context, instance); | ||
| 658 | 642 | CHECK_NOT_NULL(port); | |
| 659 | 643 | if (port->IsHandleClosing()) { | |
| 660 | 644 | // Construction failed with an exception. | |
| 661 | 645 | return nullptr; | |
| 662 | 646 | } | |
| 663 | 647 | ||
| 664 | 648 | if (data) { | |
| 649 | + CHECK(!sibling_group); | ||
| 665 | 650 | port->Detach(); | |
| 666 | 651 | port->data_ = std::move(data); | |
| 667 | 652 | ||
@@ -673,6 +658,8 @@ MessagePort* MessagePort::New( | |||
| 673 | 658 | // If the existing MessagePortData object had pending messages, this is | |
| 674 | 659 | // the easiest way to run that queue. | |
| 675 | 660 | port->TriggerAsync(); | |
| 661 | + } else if (sibling_group) { | ||
| 662 | + sibling_group->Entangle(port->data_.get()); | ||
| 676 | 663 | } | |
| 677 | 664 | return port; | |
| 678 | 665 | } | |
@@ -1067,7 +1054,7 @@ void MessagePort::MoveToContext(const FunctionCallbackInfo<Value>& args) { | |||
| 1067 | 1054 | } | |
| 1068 | 1055 | ||
| 1069 | 1056 | void MessagePort::Entangle(MessagePort* a, MessagePort* b) { | |
| 1070 | - Entangle(a, b->data_.get()); | ||
| 1057 | + MessagePortData::Entangle(a->data_.get(), b->data_.get()); | ||
| 1071 | 1058 | } | |
| 1072 | 1059 | ||
| 1073 | 1060 | void MessagePort::Entangle(MessagePort* a, MessagePortData* b) { | |
@@ -1274,7 +1261,6 @@ Maybe<bool> JSTransferable::Data::FinalizeTransferWrite( | |||
| 1274 | 1261 | } | |
| 1275 | 1262 | ||
| 1276 | 1263 | std::shared_ptr<SiblingGroup> SiblingGroup::Get(const std::string& name) { | |
| 1277 | - if (name.empty()) return {}; | ||
| 1278 | 1264 | Mutex::ScopedLock lock(SiblingGroup::groups_mutex_); | |
| 1279 | 1265 | std::shared_ptr<SiblingGroup> group; | |
| 1280 | 1266 | auto i = groups_.find(name); | |
@@ -1348,14 +1334,24 @@ Maybe<bool> SiblingGroup::Dispatch( | |||
| 1348 | 1334 | return Just(true); | |
| 1349 | 1335 | } | |
| 1350 | 1336 | ||
| 1351 | - void SiblingGroup::Entangle(MessagePortData* data) { | ||
| 1337 | + void SiblingGroup::Entangle(MessagePortData* port) { | ||
| 1338 | + Entangle({ port }); | ||
| 1339 | + } | ||
| 1340 | + | ||
| 1341 | + void SiblingGroup::Entangle(std::initializer_list<MessagePortData*> ports) { | ||
| 1352 | 1342 | Mutex::ScopedLock lock(group_mutex_); | |
| 1353 | - ports_.insert(data); | ||
| 1343 | + for (MessagePortData* data : ports) { | ||
| 1344 | + ports_.insert(data); | ||
| 1345 | + CHECK(!data->group_); | ||
| 1346 | + data->group_ = shared_from_this(); | ||
| 1347 | + } | ||
| 1354 | 1348 | } | |
| 1355 | 1349 | ||
| 1356 | 1350 | void SiblingGroup::Disentangle(MessagePortData* data) { | |
| 1351 | + auto self = shared_from_this(); // Keep alive until end of function. | ||
| 1357 | 1352 | Mutex::ScopedLock lock(group_mutex_); | |
| 1358 | 1353 | ports_.erase(data); | |
| 1354 | + data->group_.reset(); | ||
| 1359 | 1355 | ||
| 1360 | 1356 | data->AddToIncomingQueue(std::make_shared<Message>()); | |
| 1361 | 1357 | // If this is an anonymous group and there's another port, close it. | |
@@ -1407,8 +1403,10 @@ static void BroadcastChannel(const FunctionCallbackInfo<Value>& args) { | |||
| 1407 | 1403 | Context::Scope context_scope(env->context()); | |
| 1408 | 1404 | Utf8Value name(env->isolate(), args[0]); | |
| 1409 | 1405 | MessagePort* port = | |
| 1410 | - MessagePort::New(env, env->context(), nullptr, std::string(*name)); | ||
| 1411 | - args.GetReturnValue().Set(port->object()); | ||
| 1406 | + MessagePort::New(env, env->context(), {}, SiblingGroup::Get(*name)); | ||
| 1407 | + if (port != nullptr) { | ||
| 1408 | + args.GetReturnValue().Set(port->object()); | ||
| 1409 | + } | ||
| 1412 | 1410 | } | |
| 1413 | 1411 | ||
| 1414 | 1412 | static void InitMessaging(Local<Object> target, | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -110,7 +110,7 @@ class Message : public MemoryRetainer { | |||
| 110 | 110 | friend class MessagePort; | |
| 111 | 111 | }; | |
| 112 | 112 | ||
| 113 | - class SiblingGroup { | ||
| 113 | + class SiblingGroup final : public std::enable_shared_from_this<SiblingGroup> { | ||
| 114 | 114 | public: | |
| 115 | 115 | // Named SiblingGroup, Used for one-to-many BroadcastChannels. | |
| 116 | 116 | static std::shared_ptr<SiblingGroup> Get(const std::string& name); | |
@@ -134,7 +134,7 @@ class SiblingGroup { | |||
| 134 | 134 | std::string* error = nullptr); | |
| 135 | 135 | ||
| 136 | 136 | void Entangle(MessagePortData* data); | |
| 137 | - | ||
| 137 | + void Entangle(std::initializer_list<MessagePortData*> data); | ||
| 138 | 138 | void Disentangle(MessagePortData* data); | |
| 139 | 139 | ||
| 140 | 140 | const std::string& name() const { return name_; } | |
@@ -159,9 +159,7 @@ class SiblingGroup { | |||
| 159 | 159 | // a specific Environment/Isolate/event loop, for easier transfer between those. | |
| 160 | 160 | class MessagePortData : public TransferData { | |
| 161 | 161 | public: | |
| 162 | - explicit MessagePortData( | ||
| 163 | - MessagePort* owner, | ||
| 164 | - const std::string& name = std::string()); | ||
| 162 | + explicit MessagePortData(MessagePort* owner); | ||
| 165 | 163 | ~MessagePortData() override; | |
| 166 | 164 | ||
| 167 | 165 | MessagePortData(MessagePortData&& other) = delete; | |
@@ -203,6 +201,7 @@ class MessagePortData : public TransferData { | |||
| 203 | 201 | MessagePort* owner_ = nullptr; | |
| 204 | 202 | std::shared_ptr<SiblingGroup> group_; | |
| 205 | 203 | friend class MessagePort; | |
| 204 | + friend class SiblingGroup; | ||
| 206 | 205 | }; | |
| 207 | 206 | ||
| 208 | 207 | // A message port that receives messages from other threads, including | |
@@ -216,8 +215,7 @@ class MessagePort : public HandleWrap { | |||
| 216 | 215 | // creating MessagePort instances. | |
| 217 | 216 | MessagePort(Environment* env, | |
| 218 | 217 | v8::Local<v8::Context> context, | |
| 219 | - v8::Local<v8::Object> wrap, | ||
| 220 | - const std::string& name = std::string()); | ||
| 218 | + v8::Local<v8::Object> wrap); | ||
| 221 | 219 | ||
| 222 | 220 | public: | |
| 223 | 221 | ~MessagePort() override; | |
@@ -226,8 +224,8 @@ class MessagePort : public HandleWrap { | |||
| 226 | 224 | // `MessagePortData` object. | |
| 227 | 225 | static MessagePort* New(Environment* env, | |
| 228 | 226 | v8::Local<v8::Context> context, | |
| 229 | - std::unique_ptr<MessagePortData> data = nullptr, | ||
| 230 | - const std::string& name = std::string()); | ||
| 227 | + std::unique_ptr<MessagePortData> data = {}, | ||
| 228 | + std::shared_ptr<SiblingGroup> sibling_group = {}); | ||
| 231 | 229 | ||
| 232 | 230 | // Send a message, i.e. deliver it into the sibling's incoming queue. | |
| 233 | 231 | // If this port is closed, or if there is no sibling, this message is | |
| Back | FazBrowse Home | New Git URL |
0 commit comments