Enums, bitfields and wl_arrays

Nils Chr. Brause nilschrbrause at gmail.com
Fri Oct 9 04:11:32 PDT 2015


Hi,

On Thu, Oct 8, 2015 at 10:13 PM, Daniel Stone <daniel at fooishbar.org> wrote:
> Hi,
>
> On 5 October 2015 at 21:31, Victor Berger <victor.berger at m4x.org> wrote:
>> Le 2015-10-05 21:53, Nils Chr. Brause a écrit :
>>> Since a language binding should support unknown values anyway, I don't
>>> quite
>>> see the benefit of an 'open' flag.
>>
>> It depends. In some case, it could be valid to support unknown values by
>> simply ignoring them.
>>
>> Consider a program written against a certain version of the protocol. Then,
>> it is used on a compositor with a newer version of the protocol, where one
>> of the enums have one more possible value.
>>
>> What can the client do if it receives this value ? It has no possible way to
>> give it a proper meaning, so it can either ignore it, or trigger a fatal
>> error. Are there other options ?
>>
>> In this case, for a "closed" enum, the binding can decide to ignore any
>> value received on the wire that is not described in the XML, as anyway, the
>> client would not know what to do with it (and if they knew, they should be
>> using a more recent version of the binding).
>
> This should never happen. The compositor is responsible for tracking
> which version the client has bound, and not sending it values it
> doesn't know what to do with.
>
> I've heard mention that xdg-shell allows this, but I also can't see it
> anywhere in the spec. Jasper?
>
>> This can be useful in some languages to allow such a thing. For example in
>> Rust, handling an "open" enum would require some overhead in terms of
>> usability of the API, to gracefully handle unknown values. While simply
>> ignoring them would lead to a much simpler design. Unless it is not a good
>> idea to ignore unkown values, in which case I'd gladly read an explanation
>> of why it is and which problems I missed.
>>
>> Without this flag, I have to choices: either consider enums as uints/ints
>> and a set of constants to compare against (like C), of put this overhead on
>> every single enum. To be honest, none of these possibilities feel
>> satisfying. But They are still possible outcomes, hence the bindings _can_
>> live without this indication.
>
> My main concern was what I raised on IRC and Pekka in email:
>> > There is a paradox: if the new attributes affect codegen for some
>> > languages in a way that will break the build (which is exactly the
>> > reason why they are wanted: to enforce type-safety), we cannot add
>> > these attributes to the existing protocols, most importantly
>> > wayland.xml, because it would "break existing code". You might escape
>> > that paradox once, by claiming that there is no "existing code", after
>> > all the generators for these languages will be new. But this escape
>> > hatch will only work once. When these generators get into use, we can
>> > no longer add the attributes to stable protocols without breaking
>> > things. Not even if the generators had a "legacy mode" that ignores the
>> > new attributes, because they would then regress on arguments that
>> > already had the new attributes set.
>
> The exact scenario being:
>   - protocol v1 ships an enum with two possible values
>   - protocol v2 adds another possible value for that enum
>   - a client built against v1 will only ever speak v1 to the
> compositor, but at runtime the library may support v2
>   - a client built against v2 may also speak to a v1 compositor
>
> For Rust, the answer here appears to be that the packages will all be
> tightly bounded in versioning between build and runtime, so this
> scenario is irrelevant.
>
> For other bindings though, what happens here? Is ProtocolEnum
> type-compatible, such that a client built against v1 bindings can pass
> those values into a library which also supports v2? Does every bump
> give you a new type, such that ProtocolEnumV1, ProtocolEnumV2, etc,
> are all different types? If so, do you generate new call signatures
> for every request/event which takes that enum?

I can only speak for the C++ bindings here. I just added a a new entry
to the wl_seat::capability bitfield, recompiled the library and ran a client
without rebuilding it and it worked just fine. Therefore it doesn't seem to
be an issue here. :)

> This seems like it could get hairy. But if the answer from
> Java/Haskell/etc is that the types are compatible, or there's some
> other way to work around this such that it is possible to add new enum
> values without breaking all existing users of rich bindings, then
> great!
>
>> I hope this was a clear explanation of why I think these values can be
>> useful. Without then, I cannot really make use of the new attribute linking
>> an argument to its enum, apart from writing it in the documentation and
>> using (u)ints everywhere.
>
> It has been very helpful, thanks.
>
> Seems like, with this question resolved, we've finally arrived at a
> conclusion here.
>
> Cheers,
> Daniel


More information about the wayland-devel mailing list