flipper-io / flipper

Flipper is a development platform that can be controlled from any programming language.
https://www.flipper.io/
Apache License 2.0
70 stars 15 forks source link

Determine the role of Flipper attach/detach in OO languages. #52

Closed nicholastmosher closed 7 years ago

nicholastmosher commented 8 years ago

@TravisWhitaker mentioned in a previous PR that he noticed that Java's bindings, while there was support for attaching to named Flipper devices, there was no support for selecting or detaching them. To favor creating a rough but wide first implementation of the language wrapper, I'd left that issue unaddressed, but I think that it's time that we have a thorough discussion on how we expect object-oriented languages to approach the problem of managing multiple Flipper devices.

Ideally, I'd imagine that in an OO language, we would want for users to construct a unique Flipper object for each Flipper device connected to the computer, and the system (being the underlying language-libflipper mechanisms) would handle the multiplexing opaquely.

With the current libflipper API for attaching to Flippers, only one Flipper device may be in an "attached" state at a time, during which all other libflipper calls are directed to that device. There are several ways that this may be made workable in an OO language. For example (from the perspective of Java): whenever a new Flipper object is constructed, it may register itself with a static/global hashmap, storing the Flipper object as the key and the Flipper's name (recognizable to libflipper's attach_name/select/detach methods) as the value (Map flippers = new HashMap<Flipper, String>). Then, every time a Flipper object wants to call a method, it would perform a routine where it would call select(flippers.get(this)) in order to ensure that the following calls would be directed to the correct Flipper device. However, this seems like a very inefficient and unsafe way to solve this problem. I can easily foresee problems with multithreading, and if multiple Flipper objects are alternating calls frequently then it may incur a lot of time lost to switching.

I'd like to hear your suggestions to this problem. I don't know if the solution I just described is a desirable one or if there are solutions I haven't thought of, or if some slight changes to the Flipper API of libflipper might make this problem more manageable.

georgemorgan commented 8 years ago

Let's discuss this in the meeting tonight. Let's also be sure to document our discussion and create a formal guide for our strategy.

nicholastmosher commented 8 years ago

At last Wednesday's meeting, we decided that it would be a good idea to add a function to Flipper's attachment API that would simply return information regarding the currently-selected device (whether that needs to simply be the Flipper's name or if there is some unique handle for each attached Flipper I can't recall). This will allow for language wrappers to query libflipper for the active device at each function call, providing fast and truthful insight to libflipper's state. The object-oriented languages can then use that state information to properly coordinate function calls originating from distinct Flipper "objects" which may be destined for different physical Flippers.

@georgemorgan could you define and briefly document a function to return some identifying information regarding the active Flipper device, including what type of information (i.e. simple name or some unique handle) that is?

georgemorgan commented 8 years ago

Definitely, @nicholastmosher. You should take a look at some of the implementation brewing around struct _lf_device in the experimental branch. Feel free to offer any feedback regarding your thoughts on its structure; but once full implemented, it should be the answer to what you propose.

The way the current API works, however, is similar. There's a structure also called _lf_device in flipper.h that has an identifier, the property that you're after. If you're referring about how to dynamically get that property from a device that hasn't yet been attached, that's achieved by calling config_read(CONFIG_NAME). Hope that answers your question. Let me know if you need anything else.

nicholastmosher commented 8 years ago

@georgemorgan okay, I think I do remember seeing that previously.

I'm starting to think that we're now depending on design decisions that have been implemented in the experimental branch, but which haven't made any presence in master. We wanted to have a dedicated meeting as a semi-formal review session about these changes, but I think that meeting should be separate than our normal weekly ones. I'm wondering if it'd be possible to do that meeting before this Wednesday's meeting so that we can start incorporating the experimental features into the master branch as quickly as possible so that dependent development (such as language bindings) can continue at full speed.

@georgemorgan and @TravisWhitaker is there a good time for you to do the review meeting before this Wednesday or if not, what day would work best for you?

TravisWhitaker commented 8 years ago

I'm free tomorrow after 5PM EST.

Also, you want to use the name field instead of the identifier field of lf_device, since that's what select() uses. IIRC the full name isn't stored in the on-device configuration.

@georgemorgan config_read calls device.invoke() in libflipper, so I'm not sure what you mean by "dynamically get that property from a device that hasn't yet been attached".

georgemorgan commented 8 years ago

@TravisWhitaker, you can select an endpoint without formally attaching. Attaching just means that the device at the other end has been verified to have the same name (and identifier) as the one you requested to be attached to. You can, however, blindly send FMR packets over a bus checking to see if you get a valid header and response. That's how we check the configuration anyway - temporarily send packets out a given endpoint, if we get back an identifier that matches the one we're looking for, then we set the global endpoint.

georgemorgan commented 7 years ago

The attach functions now return a single _lf_device pointer that contains all the information needed to forward it calls. This pointer will be catalogued by OO languages in an object that encapsulates the attached device. When OO modules are executed, they will reference this object (to which they will all have a reference) and it will pass the pointer mentioned earlier to lf_select to ensure the subsequent message runtime calls go to the appropriate device.

harlanhaskins commented 7 years ago

This makes bindings trivial. Kudos!