Jump to content


Photo
- - - - -

[CR] By Ref Active Object Framework


  • Please log in to reply
4 replies to this topic

#1 SciWare

SciWare

    Very Active

  • Members
  • PipPipPip
  • 244 posts
  • Location:Sydney NSW
  • Version:LabVIEW 8.6
  • Since:1996

Posted 14 September 2009 - 03:43 AM

Posted Image

Name: By Ref Active Object Framework
Submitter: SciWare
Submitted: 14 Sep 2009
File Updated: 14 Sep 2009
Category: LabVIEW OOP
Version: 1.0.0
LabVIEW Version: 2009
License Type: BSD (Most common)

By Ref Active Object Framework

Copyright 2009, Kurt Friday
All rights reserved.

Author: Kurt Friday
LAVA Name: SciWare
Contact Info: Contact via PM on lavag.org

LabVIEW Versions: 2009

Dependencies: None

Description:

This is an OOP Framework that allows the development of By Reference Objects
with the capability to also be Active Objects.

By Reference capability is achieved by wrapping a DVR of the Data Members in a LVOOP Object.
An Active Object is one that has its own background process which is launched when the object
is instantiated. Active Objects are useful if your object requires time dependent characteristics.


Examples:

By Reference Object Demo

Demos\BikeDemo\Src\BikeDemo.vi

By Reference Active Object Demo

Demos\PumpDemo\Src\PumpDemo.vi

Version History:
v1.0.0: Initial release of the code.

License:
### BSD License (http://www.opensourc...bsd-license.php) Begin ###

Copyright 2009, SciWare <http://www.sciware.com.au>, Author: Kurt Friday

All rights reserved.

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of SciWare,nor the names of its contributors may be used to endorse or promote products derived
from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

### BSD License End ###

Support:
If you have any problems with this code or want to suggest features:
please go to lavag.org and Navigate to LAVA > Resources > Code Repository (Certified) and
search for the "By Ref Active Object Framework" support page.

Distribution:
This code was downloaded from the LAVA Code Repository found at lavag.org

Click here to download this file
Cheers

Kurt Friday
SciWare

#2 Daklu

Daklu

    Bringing the Fu to you

  • Premium Member
  • 1,830 posts
  • Location:Seattle
  • Version:LabVIEW 2009
  • Since:2006

Posted 24 December 2009 - 05:00 PM

Kurt,

I think I'll finally get some time to implement some of my own active objects based on your example, but I wanted to toss out some questions to make sure I'm understanding it correctly and only change what I need to.


  • All the vis/controls in the private folder should remain untouched, except DataRef, which I customize with my own data, and Process, in which I delete all the cases (except "shutdown") and add cases to handle my object's commands. Create and Destroy are the only public methods that are part of the framework; the others are unique to the example. Correct?
  • There is both a command queue and a message queue. I couldn't find the message queue used anywhere. Is this an artifact of the development process or is there an intended use for it?
  • I'm a little confused about the occurrence you use in LaunchProcess and CloseProcess. Both vis have a "Wait on Occurrence" before exiting with a 1 sec timeout, but there's no action based on whether or not the occurrence was set. Is this just a placeholder to show where to put code that does need the occurrence?
  • I see you've set up the methods and controls with dynamic dispatching and protected scope. Have you tried creating a generalized ActiveObject for the core functionality and deriving child objects for specific implementations?

Certified LabVIEW Architect
Dak's First Law of Problem Solving: If the solution looks simple, I don't know enough about the problem.

Yes, the QSM is flexible. So is Jello. That doesn't make it good construction material.

There are two secrets to success:
Secret #1 - Never tell everything you know.


#3 IBerg

IBerg

    3 more posts to go.

  • Members
  • 7 posts
  • Location:Gibsonia, PA
  • Version:LabVIEW 8.6
  • Since:2001

Posted 23 January 2011 - 03:59 AM

As one who has grown to love endevo's GOOP tookit and recently disappointed after re-acquainting myself with LabVIEW's native oop features (which still seems like illegitimate OOP to me, but I am biased due to coming to OOP from C++ background), To put it mildly I was dismayed by the native default by-value behavior but like teh by reference capabilities of this DVR Active Object architecture much better. Thank you for posting it!

One thing I noticed about the pump example is if you follow commanding the pump to pump a volume by any other action on the front panel which invokes another command being sent before the pump finishes, the timeout set in Process.vi won't have time to expire. Not having had time to expire is maybe ok if the next action was turn pump on, or turn pump off, but problematic if the user had simply hit 'Pump volume" again. Did you really intend for a double-use of either pump's "Pump volume' button to effectively turn the pump on indefinitely?

If not, we get to the real question i am wondering about... what is the best way to fix it and yet preserve the elegant simplicity of this example? Handshaking (: i.e. disable and grey the "pump volume" button until a message comes back to say the time out has been reached sounds ... I guess within "process.vi" if the most recently executed command was "Pump volume" then the return message that triggers the re-enable would need to be sent as soon as the dequeue times out or returns any newly sent command (getting another "pump volume' would then be ruled out).

#4 Daklu

Daklu

    Bringing the Fu to you

  • Premium Member
  • 1,830 posts
  • Location:Seattle
  • Version:LabVIEW 2009
  • Since:2006

Posted 29 January 2011 - 06:58 PM

Kurt has been MIA for quite some time, so while I wouldn't presume to speak for him I'll take a stab at answering your questions.

Did you really intend for a double-use of either pump's "Pump volume' button to effectively turn the pump on indefinitely?

Probably not, but for the sake of simplicity lots of error checking and whatnot is usually left out of code when the purpose is to illustrate a specific concept.


If not, we get to the real question i am wondering about... what is the best way to fix it and yet preserve the elegant simplicity of this example?

Hmm... can't really answer that without defining what the system behavior should be when the Pump Volume button is pressed while the pump is running. Should the button tell the system that regardless of where it is or what it's doing now, it should pump x additional volume then stop (restarting the process with the new endpoint), or should it overwrite the current Volume to Pump value (continuing the same process but replacing the endpoint), or should it ignore the message altogether?

You can get part of the way towards the first definition by removing the state boolean check inside the 'pumpvol' case, though that single change causes the Volume Pumped indicator to reset, so there's more work that needs to be done. I didn't explore implementing the other definitions.

In general terms your question is 'how do we make sure the system remains robust when it receives unexpected messages?' Disabling front panel controls to prevent messages from being sent is one way to approach it, though I don't particularly like that technique. IMO it's much better to build message filtering into the system itself rather than require the clients to pre-filter the messages before sending them. But this question is not really related to Kurt's framework, so if you want to discuss it more it would be better to start a new topic.

Certified LabVIEW Architect
Dak's First Law of Problem Solving: If the solution looks simple, I don't know enough about the problem.

Yes, the QSM is flexible. So is Jello. That doesn't make it good construction material.

There are two secrets to success:
Secret #1 - Never tell everything you know.


#5 SciWare

SciWare

    Very Active

  • Members
  • PipPipPip
  • 244 posts
  • Location:Sydney NSW
  • Version:LabVIEW 8.6
  • Since:1996

Posted 26 April 2011 - 12:41 AM

Hi All

Apologies for not replying I didn't realise that there were posts here.

Regarding the Pump example, its just a simple demo of the capability of the framework. Probably the best way to handle not pushing another pump volume command while it is already pumping is to have a busy state in the datamembers and don't allow any new pump volume commands to be placed in the queue until it is not busy.

All the vis/controls in the private folder should remain untouched, except DataRef, which I customize with my own data, and Process, in which I delete all the cases (except "shutdown") and add cases to handle my object's commands. Create and Destroy are the only public methods that are part of the framework; the others are unique to the example. Correct?


Spot on!

There is both a command queue and a message queue. I couldn't find the message queue used anywhere. Is this an artifact of the development process or is there an intended use for it?


In most cases all you need is the command queue to send commands into the process, however there are situations where you would want the process to message up to the public level.


I'm a little confused about the occurrence you use in LaunchProcess and CloseProcess. Both vis have a "Wait on Occurrence" before exiting with a 1 sec timeout, but there's no action based on whether or not the occurrence was set. Is this just a placeholder to show where to put code that does need the occurrence?


In the launcher there is a wait on occurrence, and that occurrence is the 1st thing that is set when the process is launched. We want a situation that when the launcher has completed execution the process is confirmed to be up and running. So the launcher waits until the process is live. The same is true for the close process, it waits until the occurrence is set when the process shuts down.


I see you've set up the methods and controls with dynamic dispatching and protected scope. Have you tried creating a generalized ActiveObject for the core functionality and deriving child objects for specific implementations?


I've tested inheritance and all works as expected, you can have parent active object and call its constructor within a child and the parent process is launched. Take a look at the Bike example, although the Bike is not active you could make the Bike active and the Racer would inherit the active capabilities of the Bike. A good example where you could use this is to make a general server class and the child is protocol specific.
Cheers

Kurt Friday
SciWare