On 6/19/13 2:47 AM, Adam Bergkvist wrote:
> On 2013-06-18 23:02, Jan-Ivar Bruaroey wrote:
>> I can think of no cases, thankfully. My understanding is that the queue
>> is there to make the API deterministic, rather than encourage enqueuing.
>> E.g.:
>
> Thank you for clarifying this. But is this new approach any easier
> than classical states?
We may disagree on the classifications "new" and "classical" here. We
have a state machine affected by operations that may fail. The classical
approach, to me, is to transition state not until operational steps
succeed, to preserve a sane state transition diagram. [1] - This means
that, since our operations are asynchronous, state must transition at
the completion of our async calls, not at the beginning.
Introducing additional state(s) at the beginning (lets call it "the time
of intention"), as you're suggesting, I would call new.
>> // Bad code. state=have_local_offer
>> pc.setRemoteDescription(answer1, success, mayfail);
>> pc.setRemoteDescription(answer2, success, mayfail);
>>
>> Without a queue, the second call could succeed or fail based on whether
>> the first call has completed. With a queue in place it becomes
>> deterministic: If call 1 succeeds, then call 2 always fails
>> (state=stable). If call 1 fails, then call 2 has the same starting point
>> (state=have_local_offer), always.
>>
>> Why care? Non-deterministic behavior would be bad for
>> documentation-reasons alone (having to mention useless edge-cases like
>> this).
>>
>
> With a processing state, the second call would always fail. That's
> deterministic and observable from JS (compared to a queue in the
> background).
>
>>> Wouldn't it be simpler to have a model where the PeerConnection enters
>>> a "processing" state when, for example, setLocalDescription() is
>>> called, and the state is updated in the task that fires the methods
>>> success or error callback? The "single operation at a time" rule would
>>> then be enforced by the PeerConnection signaling state.
>>
>> Yes, we could have done that. It would let you throw on bad state, but
>> at the cost of doubling the number of states in the state machine. I'm
>> not sure it is simpler.
>>
>
> A single processing state would be enough to start with, and it could
> be expanded if developers asked for more.
You want to do this for every operation, right? Then I think you mean a
flag, i.e. a doubling of states effectively. Otherwise, please draw me
the new state transition diagram.
If you change state at the "time of intention", then you have to handle
backing out to the previous state if/when the operation fails. With only
a single "processing" state there's not enough info in the state model
itself to know the previous state, so that's not a state. And
signalingstatechange returning "processing" isn't very informative.
I believe you effectively have this in your suggestion:
enum RTCSignalingState {
"processing-stable",
"stable",
"processing-have-local-offer",
"have-local-offer",
"processing-have-remote-offer",
"have-remote-offer",
"processing-have-local-pranswer",
"have-local-pranswer",
"processing-have-remote-pranswer",
"have-remote-pranswer",
"processing-closed",
"closed"
};
That doesn't seem simpler to me.
[1] Our diagram
http://dev.w3.org/2011/webrtc/editor/webrtc.html#rtcpeerstate-enum
.: Jan-Ivar :.
>
> /Adam
>