12-20-2018 08:58 AM
Here's a somewhat finished chat client/server app I'm working on to test all the features:
The Server does not forward received messages back out to other connected clients yet and the client doesn't have read capability yet but every bit of the library is here. Servers spawn instances of the same exact client code that client side connections use. Clients provide an underlying stream object that wrap reading/writing functionality. The idea is to very rarely use this library directly; instead it will have additional layers that fulfill layer 6/7 of the OSI network model for use by applications. (Simple messaging, Serializable object streaming, etc)
Still waiting to hear back about being able to post code but at the pace things move here it won't be well into the new year until I hear back
12-21-2018 08:36 AM
@DerrickB wrote:
The idea is to very rarely use this library directly; instead it will have additional layers ...
Hopefully, the added layers will (through specialisation) present a simpler API. As an exercise, I wrote a Chat implementation in Messenger Library (which is specialised to messaging patterns only). Here's the Server block diagram:
There is a lot going on behind these high-level API calls of course, but it is important that the complexity is abstracted into something simple.
06-02-2024 04:35 AM - edited 06-02-2024 04:41 AM
Dear tyk007,
I have been trying to understand this lately and my observations agree with your description, with one subtle difference:
you say "As far as I am aware LabVIEW clean-ups references automatically when a VI Hierarchy goes idle (as a result of the top-level VI ending)"
if the top-level VI is spawned by a "Start Asynchronous Call primitive" the lifetime is not bound to the VI execution lifetime (VI ending) but to the VI reference lifetime. If the VI ends and you don't close the VI reference the references created within the VI hierarchy are not destroyed, they will be as soon as you call the "Close Reference" primitive.
I am pretty confident about this as I banged my head for a full this when writing a library adding async call functionality to the actor framework.
Cheers
Andrea
06-02-2024 08:02 AM
@lsi wrote:
if the top-level VI is spawned by a "Start Asynchronous Call primitive" the lifetime is not bound to the VI execution lifetime (VI ending) but to the VI reference lifetime. If the VI ends and you don't close the VI reference the references created within the VI hierarchy are not destroyed, they will be as soon as you call the "Close Reference" primitive.
I am pretty confident about this as I banged my head for a full this when writing a library adding async call functionality to the actor framework.
That's quite possible but I never use the Start Async in such a way. Either I'm caching the original refnum from the Open VI refnum and use the Open VI flag 0x08 to spawn a new reentrant instance of the VI on every Async Start or I immediately close the refnum after the Async Start was successful. Anything else only makes the refnum management more complicated.
The reason to do the caching is that the Open VI is a blocking operation that runs in the UI thread and that takes some significant time so if you need to instantiate a VI regularly such as an executor in a class for a background processing task. This can add up for larger applications with many such classes. By caching the original refnum and creating a new instance everytime you need one this can speed up starting up such an executor system with many classes quite a bit.