Jump to content

Talking to text based programmers


Recommended Posts

Is there a LabVIEW jargon to text based translation guide out there?

I'd like to know what other developers call things like:

  • (non)Reentrant
  • Single element queue
  • Data value reference
  • Functional global

I think there are some concepts I'm OK on:

  • We call them clusters, they call them structs right?
  • We have reasonable agreement on concepts like enums and global variables

 

Link to comment
  • Reentrant: Roughly also "Reentrant", although...
    • LabVIEW VIs are non-reentrant by default, C/C++ functions are reentrant by default.
    • Unlike LabVIEW, there is no setting to force C/C++ functions to become non-reentrant -- you simply code them in a way that makes them reentrant.
    • In LabVIEW, non-reentrant VIs are impossible to run multiple instances simultaneously. In C/C++, non-reentrant functions are unsafe to run multiple instances simultaneously (it's possible; you'll just break things).
       
  • Single element queue: Depends on how you use it. I often use it as a nicer form of Data Value Reference (see below).
     
  • Data value reference: "Pointer" (as per the Wiki) or "Reference"
     
  • Functional global: Doesn't really exist in textual languages. They were invented to fill the role of Global Variables, back in LabVIEW 2 when Global Variables didn't exist.

 

10 hours ago, infinitenothing said:

I think there are some concepts I'm OK on:

  • We call them clusters, they call them structs right?
  • We have reasonable agreement on concepts like enums and global variables

Sounds good to me. However, note that a LabVIEW "variable" is quite different from a textual "variable". A textual variable is more like a LabVIEW wire.

  • Like 1
Link to comment

What about the "in place" structure for a data value reference. What's the equivalent text based concept for a mutex wrapping some operation (for example increment by one) to make something "thread safe"

For single element queues, how do I explain what dequeuing does? That it makes the other dequeuers and preview queures wait or timeout and that no two dequeuers can access at the same time. Is there a term or a simple code snippet that shows this behavior?

Link to comment
On 6/5/2021 at 7:29 AM, infinitenothing said:

What about the "in place" structure for a data value reference. What's the equivalent text based concept for a mutex wrapping some operation (for example increment by one) to make something "thread safe"

For single element queues, how do I explain what dequeuing does? That it makes the other dequeuers and preview queures wait or timeout and that no two dequeuers can access at the same time. Is there a term or a simple code snippet that shows this behavior?

Functionally, dequeueing a SEQ is analogous to reading the DVR in "In Place Element" and analogous to locking a mutex.

seq-dvr-analogy.png.96dd851d1b6806b97b97b8440f5c9d96.png

 

The 2 LabVIEW code paths above are analogous to this C++ code snippet:

// Global variable and mutex
std::mutex mtx;
int* globalvar = new int; // 1a. Initialize shared resource ("Obtain Queue")

int main()
{
	// 1b. Initialize shared resource ("Enqueue Element")
	*globalvar = 0;
	
	// 2. Lock shared resource ("Dequeue Element")
	mtx.lock();
	
	// 3. Modify shared resource ("Increment")
	*globalvar += 1;
	
	// 4. Unlock shared resource ("Enqueue Element")
	mtx.unlock();
	
	// 5. Free/Delete shared resource ("Release Queue")
	delete globalvar;
}

 

Notes:

  • It doesn't make much sense to use a global pointer-to-integer in C++; we would just use a global integer directly (or find ways to avoid globals altogether).
    • The code above is to show equivalence to LabVIEW nodes; you'll get funny looks if you present C++ code like this.
       
  • Using a SEQ like this is unintuitive. Using Queue concepts to share data and lock/unlock access is borderline API abuse.
    • Likewise, using a non-reentrant VI's internal state to act as a global variable (i.e. Functional Globals) is borderline API abuse.
    • Therefore, I would not introduce SEQs and FGVs to newcomers until they are comfortable with other basic concepts of LabVIEW. I would not use them as a starting point for discussions.
    • Nonetheless, we accept/embrace SEQs because they are useful (FGVs are less useful since proper Global Variables exist now).
    • I consider DVRs more intuitive than SEQs, but I prefer SEQs on a block diagram as they don't require the huge rectangular frame.
Edited by JKSH
  • Thanks 1
Link to comment
8 hours ago, JKSH said:

Functionally, dequeueing a SEQ is analogous to reading the DVR in "In Place Element" and analogous to locking a mutex.

seq-dvr-analogy.png.96dd851d1b6806b97b97b8440f5c9d96.png

 

The 2 LabVIEW code paths above are analogous to this C++ code snippet:






// Global variable and mutex
std::mutex mtx;
int* globalvar = new int; // 1a. Initialize shared resource ("Obtain Queue")

int main()
{
	// 1b. Initialize shared resource ("Enqueue Element")
	*globalvar = 0;
	
	// 2. Lock shared resource ("Dequeue Element")
	mtx.lock();
	
	// 3. Modify shared resource ("Increment")
	*globalvar += 1;
	
	// 4. Unlock shared resource ("Enqueue Element")
	mtx.unlock();
	
	// 5. Free/Delete shared resource ("Release Queue")
	delete globalvar;
}

 

Notes:

  • It doesn't make much sense to use a global pointer-to-integer in C++; we would just use a global integer directly (or find ways to avoid globals altogether).
    • The code above is to show equivalence to LabVIEW nodes; you'll get funny looks if you present C++ code like this.
       
  • Using a SEQ like this is unintuitive. Using Queue concepts to share data and lock/unlock access is borderline API abuse.
    • Likewise, using a non-reentrant VI's internal state to act as a global variable (i.e. Functional Globals) is borderline API abuse.
    • Therefore, I would not introduce SEQs and FGVs to newcomers until they are comfortable with other basic concepts of LabVIEW. I would not use them as a starting point for discussions.
    • Nonetheless, we accept/embrace SEQs because they are useful (FGVs are less useful since proper Global Variables exist now).
    • I consider DVRs more intuitive than SEQs, but I prefer SEQs on a block diagram as they don't require the huge rectangular frame.

That's not why most of us use single element queues. It is used mainly for synchronisation between concurrent operations. In that respect it is akin to pipelining or events and is an edge case of a queued state machine. In fact. I used a single element queue to make a "named events" VIM. A watchdog timer is a good example of when to use a SEQ and the data  - value or type - is irrelevant.

Edited by ShaunR
Link to comment
19 hours ago, ShaunR said:

That's not why most of us use single element queues. It is used mainly for synchronisation between concurrent operations. In that respect it is akin to pipelining or events and is an edge case of a queued state machine. In fact. I used a single element queue to make a "named events" VIM. A watchdog timer is a good example of when to use a SEQ and the data  - value or type - is irrelevant.

Acknowledged.

Nonetheless, I still contend that all of these use-cases are still borderline abuse of the queue API -- @infinitenothing will be fighting an uphill battle trying to explain to text-based programmers why we use SEQs, no matter which use case he picked. It would be cleaner if LabVIEW had proper language constructs for these use cases (even if it's just syntactic sugar that wraps a SEQ behind the scenes)

Link to comment
7 minutes ago, JKSH said:

Acknowledged.

Nonetheless, I still contend that all of these use-cases are still borderline abuse of the queue API -- @infinitenothing will be fighting an uphill battle trying to explain to text-based programmers why we use SEQs, no matter which use case he picked. It would be cleaner if LabVIEW had proper language constructs for these use cases (even if it's just syntactic sugar that wraps a SEQ behind the scenes)

Queue's provide a feature that is not present with other methods such as notifiers and events. They provide a "back-pressure" in that the server can detect when when the queue is full. So any situation where server thottling or ordered, buffered synchronisation is required is a natural candidate to use a queue, even if the queue size is one.

My point though is that a single element queue is not generally used as an alternative to a DVR and is used for a completely different reason.

 

WD example.vi

Link to comment
1 hour ago, ShaunR said:

My point though is that a single element queue is not generally used as an alternative to a DVR and is used for a completely different reason.

It is my, perhaps mistaken, belief that SEQs were quite often used to fill the gap before DVRs were invented.  I'm sure I saw several examples in other people's APIs, and I used them mostly that way.  

I've used the "back pressure" of a queue, too, but then it's an N-element queue, were N might be set at one, but doesn't have to be, unlike the DVR-like use case where it must be single-element.

Link to comment
6 hours ago, drjdpowell said:

It is my, perhaps mistaken, belief that SEQs were quite often used to fill the gap before DVRs were invented.  I'm sure I saw several examples in other people's APIs, and I used them mostly that way.  

I've used the "back pressure" of a queue, too, but then it's an N-element queue, were N might be set at one, but doesn't have to be, unlike the DVR-like use case where it must be single-element.

Functional globals were used in lieu of DVR's before DVR's were invented. Maybe they were used inside classes to produce singletons before DVR's but there are lots of tricks to get around Labview POOP. I've always seen SEQ's used as a synchronisation method as demonstrated with the watchdog.

Edited by ShaunR
Link to comment
20 hours ago, ShaunR said:

Functional globals were used in lieu of DVR's before DVR's were invented. 

Ah, you guys are talking about use of SEQs now, after DVRs were available.  I'm thinking about before DVRs existed, where SEQs were often used to get DVR-like functionality.  Most of that use of SEQs will have been replaced by DVRs now.

Link to comment

I had a look at your watchdog example.  I note that, in my mind, "SEQ" stands for a pattern of using of a one-element Queue like a DVR, rather than any use of a Queue with only one element.  I changed your example to use a Queue of 10 elements, and it ran fine, so the single-element nature is not a meaningful characteristic.   Even in cases where I use Queues that have to have one element, such as my "Future Tokens" in "Messenger Library", I don't think of them as "SEQs", even though they are literally single-element queues.

Edited by drjdpowell
Link to comment
1 hour ago, drjdpowell said:

 I changed your example to use a Queue of 10 elements, and it ran fine, so the single-element nature is not a meaningful characteristic. 

If you do that with the example then the detection time for "doggie died" is 9 times more which is why you use a single element queue.

In an actual Watchdog rather than the example (where the wait is inline in the example rather than a timed event) the detection time is just the kicker's timeout. With your modification it would be 10 "kicks". If this were kicking every 10 minutes, that's a watchdog failure detection of 2 secs with an SEQ vs 100 minutes with your change. 

1 hour ago, drjdpowell said:

Even in cases where I use Queues that have to have one element, such as my "Future Tokens" in "Messenger Library", I don't think of them as "SEQs", even though they are literally single-element queues.

It seems you have proven my point with another practical example but are hung up on terminology.

On 6/6/2021 at 11:18 AM, ShaunR said:

That's not why most of us use single element queues. It is used mainly for synchronisation between concurrent operations

Edited by ShaunR
Link to comment
46 minutes ago, ShaunR said:

If you do that with the example then the detection time for "doggie died" is 9 times more which is why you use a single element queue.

Oh, sorry, I misread it.  Your timing out on an Enqueue of a full Queue, while I have always built "watchdogs" using timeout on Dequeuing from an empty Queue..  In your case you do need to set a single element so as to define "full".

Link to comment
50 minutes ago, ShaunR said:

It seems you have proven my point with another practical example but are hung up on terminology.

Terminology is an aid to communication among multiple people, so I'll stick with how I have seen "SEQ" generally used, unless I see multiple people use it differently.   There are lots of terms that are not exactly literal; your "watchdogs" aren't actually canines, for example, but I understood the software concept you actually meant.

Link to comment
35 minutes ago, drjdpowell said:

Terminology is an aid to communication among multiple people, so I'll stick with how I have seen "SEQ" generally used, unless I see multiple people use it differently.   There are lots of terms that are not exactly literal; your "watchdogs" aren't actually canines, for example, but I understood the software concept you actually meant.

Well. not exactly horses for courses and "generally used" brings us back to square one. Your experience is demonstrably the same as mine and many others yet cling to a specific use case (that i would agree with JKSH as an abuse) that you admit is obsolete. But you do you.

I guess it's one of those differences between a Systems Engineer and a Programmer. Macro vs micro scale.

Edited by ShaunR
Link to comment
On 6/6/2021 at 5:18 AM, ShaunR said:

That's not why most of us use single element queues. It is used mainly for synchronisation between concurrent operations. In that respect it is akin to pipelining or events and is an edge case of a queued state machine. In fact. I used a single element queue to make a "named events" VIM. A watchdog timer is a good example of when to use a SEQ and the data  - value or type - is irrelevant.

A bold statement. I've certainly used it in this way before for synchronization, de-queueing until something is available, en-queueing when space allows, etc.

However, I've also used it in what I believe drjdpowell is referring to with DVR functionality. I would even say more often than the other use case. Lossy enqueue + preview queue element is a useful mechanism for providing a latest updated value to any place with the queue reference.

Link to comment
5 hours ago, Jordan Kuehn said:

Lossy enqueue + preview queue element is a useful mechanism for providing a latest updated value to any place with the queue reference.

Why wouldn't you use a notifier for this? It seems the only reason you have chosen this method is because it doesn't poll data (advantage over a global or local variable) or you have more than one element and expect the consumer(s?) to eventually catch up.

A queue is a many-to-one construction whereas a notfier is a one-to-many so it seems a strange choice if you have multiple consumers.

Edited by ShaunR
Link to comment
20 hours ago, ShaunR said:

Why wouldn't you use a notifier for this? It seems the only reason you have chosen this method is because it doesn't poll data (advantage over a global or local variable) or you have more than one element and expect the consumer(s?) to eventually catch up.

A queue is a many-to-one construction whereas a notfier is a one-to-many so it seems a strange choice if you have multiple consumers.

A fair question. I've used notifiers with the wait on notification, but not with the get status. It's two sides of the same coin as far as I'm concerned, and what is the underlying transport mechanism for the notifier anyway? My point however, is that while the SEQ is a special use case of a Queue there are ways to use it other than how you typically do. 

I'm also not entirely sold on the N:1 definition you are placing on a Queue. Sure in a typical use case 1:1 or N:1 is common, but there are use cases where you may not care about order and have multiple consumers dequeueing which could be 1:N or N:N. It's just a tool that is used how you configure it and decide to use it.

Now we can switch over to user events and if those are N:N :D 

Link to comment
On 6/9/2021 at 9:13 PM, Jordan Kuehn said:

A fair question. I've used notifiers with the wait on notification, but not with the get status. It's two sides of the same coin as far as I'm concerned, and what is the underlying transport mechanism for the notifier anyway? My point however, is that while the SEQ is a special use case of a Queue there are ways to use it other than how you typically do. 

I'm also not entirely sold on the N:1 definition you are placing on a Queue. Sure in a typical use case 1:1 or N:1 is common, but there are use cases where you may not care about order and have multiple consumers dequeueing which could be 1:N or N:N. It's just a tool that is used how you configure it and decide to use it.

Now we can switch over to user events and if those are N:N :D 

Well. It seems my response to this was deleted. Presumably the hyperbole I used angered the Lavagods.

Link to comment

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.