Beijer Electronics (formerly QSI Corporation)

Manufacturer of Mobile Data and Human Machine Interface Terminals.
It is currently Sun Nov 19, 2017 8:40 am

All times are UTC - 7 hours




Post new topic Reply to topic  [ 5 posts ] 
Author Message
 Post subject: User messages
PostPosted: Fri Nov 21, 2008 3:40 pm 
Offline
User avatar

Joined: Fri Feb 01, 2008 4:50 pm
Posts: 101
I am looking into implementing a logging system for certain system events and errors. To do this, I originally intended to use user messages to send out a broadcast message with logging information. I looked into this and realized that only a single integer can be passed with a user message, unlike like some of the built in messages that contain strings. Is there any way to actually sent more than an integer with a user message? Are there any tips on how something similar might have been implemented in the past? Mostly I want to avoid coupling portions of my code with a certain object name or function.

Thanks.


Top
 Profile  
 
 Post subject: Re: User messages
PostPosted: Fri Nov 21, 2008 3:56 pm 
Offline
QSI Support
QSI Support
User avatar

Joined: Wed Mar 08, 2006 12:25 pm
Posts: 881
Location: Salt Lake City, Utah
To preface things: System event logging is something I frequently do. Nearly always I create an object called "log" and expose at least one method that looks a bit like: "func message(msgType as logTypes, msg as string)"

In my case, obviously, I do couple my code to a particular object name. In fact, I cannot think of any way to completely decouple a logging system from some sort of globally known identifier.

To directly answer your question: User messages only support a single integer parameter. Allowing user messages to support arbitrary function signatures is not something that can easily be supported.

When I *do* need behavior like you describe -- and I occasionally do, I store the parameters to the message function in global variables.
Code:
func CallBroadcastMessage()
    BCastMsgParm1 = "Hello"
    BCastMsgParm2 = "World"
    UserBroadcastMsg(default, _MSG_MY_BROADCAST, 2, true)
endfunc

func BCastHandler(parm as integer) returns boolean
    handles _MSG_MY_BROADCAST

    _print ("Parm1=" + BCastMsgParm1 + ", Parm2=" + BCastMsgParm2)
 
    return false
endfunc


One thing -- in general, I avoid using broadcasts unless I really need the message to go to every object -- the system has to search through every object to see if it has a handler which can get expensive if you are doing this a log.

In closing, one technique that I do frequently use with objects where I know I will have at least one instance of Log, but I don't know in advance what the name of Log will be (for instance the template Log is defined in a library and will be reused throughout many workspaces). Is this

Code:
'This is a snippet of the library entry defining the object Log:

'Global variable declaration
#doc prop logObj as objref LogObj
~Use the message method of this object to store any log data
#hidden dim logObj as objref LogObj
init logObj := empty

define Object type LogObj
func Startup()
    handles MSG_INIT

    if logObj <> empty then
        throw (str(me) + ".Startup", "Error, more than one LogObj is defined!"
    endif

    logObj := me
endfunc

func message (data as string)
    dim timeStampStr as string
    timeStampStr := _FormatTime (<parms as appropriate>)


   DoLog (timeStampStr + ":  " + data + "\n")
endfunc


I am currently giving a lot of thought to formalizing an event log type object so that I don't have to rewrite it each time I start a significant workspace.

_________________
Jeremy
http://www.beijerinc.com


Top
 Profile  
 
 Post subject: Re: User messages
PostPosted: Fri Nov 21, 2008 4:16 pm 
Offline
User avatar

Joined: Fri Feb 01, 2008 4:50 pm
Posts: 101
Thanks for the thorough response Jeremy.

As far as the coupling, yes, it probably is pointless to worry about it when comparing messages vs. a global object simply because if messages were to be used they would need to be declared globally. I will likely be implementing a log object like you mentioned to take care of all of my logging needs.

One other question I have relates to messages. I haven't figured out a way to have an arbitrary template support a certain function. For instance, if I wanted a certain set of objects to support a certain function, I would only be able to do this by having them all extend from a certain object (AFAIK). But, if I needed them to extend from different templates, I wouldn't be able to accomplish my goal. For instance, in C++ classes can extend from multiple classes, and in Java a class can implement an interface. I had an idea to just use user direct messages, but again I run into a problem of not being able to have custom function signatures. Do you have any ideas here? Is there any way to accomplish what I am asking?


Top
 Profile  
 
 Post subject: Re: User messages
PostPosted: Mon Nov 24, 2008 8:11 am 
Offline
QSI Support
QSI Support
User avatar

Joined: Wed Mar 08, 2006 12:25 pm
Posts: 881
Location: Salt Lake City, Utah
Unfortunately, Qlarity does not support multiple inheritance or java style interfaces. This is an active research topic because, as you can imagine, it would be extremely useful for the object set we support.

I assume that you are in a situation like this:

Code:
define object type Base1
    dim base1Prop as integer
enddef

define object type Derived1 extends Base1
    func CallMe(data as string)
    endfunc
enddef

define object type Base2
    dim base2Prop as integer
enddef

define object type Derived2 extends Base2
    func CallMe(data as string)
    endfunc
enddef

'This could hold a reference to a Derived1 or a Derived2
dim objHolder as objref


I assume that you wish to invoke the function objHolder.CallMe -- which since objHolder is untyped you cannot directly do. You have 3 basic options which I will illustrate here.

Code:
'Option 1: explicitly downcast objHolder. 
'Note: downcasting only works to the exact type of the object,
'not subclasses.

'Same templates as the original example

dim objHolder as objref
func CallCallMe()
    dim oref1 as objref Derived1
    dim oref2 as objref Derived2
    dim name as string
   
    name = str(obj)
    check error
        val(oref1, name)
        oref1.CallMe()
        return
    on error
        _ClearException()
    enderr
   
    check error
        val(oref2, name)
        oref2.CallMe()
        return
    on error
        _ClearException()
    enderr
   
    throw ("CallCallMe", "objHolder is not of type Derived1 or Derived2")
endfunc


Code:
'Option 2: Use validation function
'This only works for single parameter functions whose parameter is not
'an enum or a resource type

'Same base templates as the original example

define object type Derived1 extends Base1
    dim CallMe as string
    func CallMe(data as string)
    endfunc
enddef

define object type Derived2 extends Base1
    dim CallMe as string
    func CallMe(data as string)
    endfunc
enddef

dim objHolder as objref
func CallCallMe()
    'This calls the validation function when setting the property
    SetObjProp(objHolder, "CallMe", str("Call with this string")) 'Note that I am stringifying the string
endfunc


Code:
'Option 3: Message

'Same base templates as the original example

define object type Derived1 extends Base1
    func CallMe(parm as integer) returns boolean
        handles MSG_CallMe
        'Use global Parm1Str here as if it were a parameter
    endfunc
enddef

define object type Derived2 extends Base1
    func CallMe(parm as integer) returns boolean
        handles MSG_CallMe
        'Use global Parm1Str here as if it were a parameter
    endfunc
enddef

const message MSG_CallMe
dim Parm1Str as string
dim objHolder as objref
func CallCallMe()
    Parm1Str := "Hello there"
    UserDirectMsg (objHolder, MSG_CallMe, 0, true)
endfunc

_________________
Jeremy
http://www.beijerinc.com


Top
 Profile  
 
 Post subject: Re: User messages
PostPosted: Tue Nov 25, 2008 11:25 am 
Offline
User avatar

Joined: Fri Feb 01, 2008 4:50 pm
Posts: 101
Thanks for the help Jeremy.

I think we will see if we can have the templates that need a particular function to just extend from the same base class. If there is a conflict, option 2 seems to be the best option, assuming we can manage with only one parameter.

Thanks again!


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 5 posts ] 

All times are UTC - 7 hours


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
cron
Powered by phpBB® Forum Software © phpBB Group