Bug 1157803 - Support connect-during-initialization for mirrors. r=jww

The MDSM is constructed and destroyed on the main thread, but runs most
everything else on the task queue. So we need to bend the rules a bit here
to conveniently connect its mirrors during construction.
This commit is contained in:
Bobby Holley 2015-04-24 20:23:04 -07:00
Родитель 7bf0120925
Коммит 913a82dcb8
1 изменённых файлов: 19 добавлений и 4 удалений

Просмотреть файл

@ -268,10 +268,15 @@ class Mirror : public AbstractMirror<T>, public WatchTarget
public: public:
using AbstractMirror<T>::OwnerThread; using AbstractMirror<T>::OwnerThread;
Mirror(AbstractThread* aThread, const T& aInitialValue, const char* aName) Mirror(AbstractThread* aThread, const T& aInitialValue, const char* aName,
AbstractCanonical<T>* aCanonical)
: AbstractMirror<T>(aThread), WatchTarget(aName), mValue(aInitialValue) : AbstractMirror<T>(aThread), WatchTarget(aName), mValue(aInitialValue)
{ {
MIRROR_LOG("%s [%p] initialized", mName, this); MIRROR_LOG("%s [%p] initialized", mName, this);
if (aCanonical) {
ConnectInternal(aCanonical);
}
} }
operator const T&() operator const T&()
@ -300,8 +305,16 @@ public:
void Connect(AbstractCanonical<T>* aCanonical) void Connect(AbstractCanonical<T>* aCanonical)
{ {
MIRROR_LOG("%s [%p] Connecting to %p", mName, this, aCanonical);
MOZ_ASSERT(OwnerThread()->IsCurrentThreadIn()); MOZ_ASSERT(OwnerThread()->IsCurrentThreadIn());
ConnectInternal(aCanonical);
}
private:
// We separate the guts of Connect into a helper so that we can call it from
// initialization while not necessarily on the owner thread.
void ConnectInternal(AbstractCanonical<T>* aCanonical)
{
MIRROR_LOG("%s [%p] Connecting to %p", mName, this, aCanonical);
MOZ_ASSERT(!IsConnected()); MOZ_ASSERT(!IsConnected());
nsCOMPtr<nsIRunnable> r = NS_NewRunnableMethodWithArg<StorensRefPtrPassByPtr<AbstractMirror<T>>> nsCOMPtr<nsIRunnable> r = NS_NewRunnableMethodWithArg<StorensRefPtrPassByPtr<AbstractMirror<T>>>
@ -309,6 +322,7 @@ public:
aCanonical->OwnerThread()->Dispatch(r.forget(), AbstractThread::DontAssertDispatchSuccess); aCanonical->OwnerThread()->Dispatch(r.forget(), AbstractThread::DontAssertDispatchSuccess);
mCanonical = aCanonical; mCanonical = aCanonical;
} }
public:
void DisconnectIfConnected() void DisconnectIfConnected()
{ {
@ -336,9 +350,10 @@ public:
// NB: Because mirror-initiated disconnection can race with canonical- // NB: Because mirror-initiated disconnection can race with canonical-
// initiated disconnection, a mirror should never be reinitialized. // initiated disconnection, a mirror should never be reinitialized.
void Init(AbstractThread* aThread, const T& aInitialValue, const char* aName) void Init(AbstractThread* aThread, const T& aInitialValue, const char* aName,
AbstractCanonical<T>* aCanonical = nullptr)
{ {
mMirror = new Mirror<T>(aThread, aInitialValue, aName); mMirror = new Mirror<T>(aThread, aInitialValue, aName, aCanonical);
} }
// Forward control operations to the Mirror<T>. // Forward control operations to the Mirror<T>.