On Thu, Apr 21, 2016 at 8:41 PM, Martin Thomson <[email protected]> wrote:
>
>> - I suspect that in some heap-allocated objects it will be hard to do
>> the fallible parts without having an object of the relevant type. I
>> don't have specific examples, just a hunch.
>
> I'm not aware of any way that necessary state can't be fully
> established before constructing an object. If you find a way in which
> this is possible, please let me know.
I just tried this pattern in three classes I've been experimenting
with and hit problems in all three.
In bug 1265965 I wrote patches to convert nsThread+Init style to the
nsThread+outparam style, which worked well. So I tried the style
Nicolas and you are advocating, which I'll calls
"falllible-then-infallible". Here is the Init() function, from the
current trunk code:
nsresult
nsThread::Init()
{
// spawn thread and wait until it is fully setup
RefPtr<nsThreadStartupEvent> startup = new nsThreadStartupEvent();
NS_ADDREF_THIS();
mShutdownRequired = true;
// ThreadFunc is responsible for setting mThread
PRThread* thr = PR_CreateThread(PR_USER_THREAD, ThreadFunc, this,
PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD,
PR_JOINABLE_THREAD, mStackSize);
if (!thr) {
NS_RELEASE_THIS();
return NS_ERROR_OUT_OF_MEMORY;
}
// ThreadFunc will wait for this event to be run before it tries to access
// mThread. By delaying insertion of this event into the queue, we ensure
// that mThread is set properly.
{
MutexAutoLock lock(mLock);
mEventsRoot.PutEvent(startup, lock); // retain a reference
}
// Wait for thread to call ThreadManager::SetupCurrentThread, which completes
// initialization of ThreadFunc.
startup->Wait();
return NS_OK;
}
So this is the code that must run before we construct an actual
nsThread object, right? The PR_CreateThread() call is the main
problem. It takes |this| as a parameter and proceeds to do all sorts
of stuff with it. It's probably not *impossible* to rewrite this as
fallible-then-infallible, but I'm struggling to see what it would look
like.
The second example I looked at was nsScriptSecurityManager. The
constructor+outparam style worked well there, but
fallible-then-infallible again hits a problem -- InitPrefs() is called
in the fallible section of initialization, and it calls
ScriptSecurityPrefChanged(), which touches lots of class members.
Maybe InitPrefs() could be moved out of the fallible section, but I
don't know this code well enough to say one way or the other.
The third example I looked at was CycleCollectedJSRuntime. Again
problems, specifically this line in Init():
mOwningThread->SetScriptObserver(this);
So, for all three examples I looked at fallible-then-infallible had
problems ranging from moderate to severe. My conclusion is that
partially initializing an object when the object doesn't exist is
difficult, and, as a result, fallible-then-infallible is not a
reliable general-purpose pattern.
Nick
_______________________________________________
dev-platform mailing list
[email protected]
https://lists.mozilla.org/listinfo/dev-platform