On 22.01.2024 22:46, Rick McGuire wrote:
The part about the variable dictionary doesn't make any sense at all. The context where the line is being traced doesn't really provide any useful information. The guard start is a combination of the guard state of all the stack frames for a given activity. Since methods are guarded by default, for any call stack, there are going to be many frames in a guarded state on potentially many objects and scopes, including nesting. This does NOT belong as part of tracing. It seriously clutters stuff up and doesn't really provide information that is needed on a statement-by-statement basis.

The scenario where this information becomes helpful, if not important is in debugging complex, large multithreaded applications. The variable dictionary number will allow for filtering all traces of a specific object in that scope. Also, for scenarios where many instances of the same class exist and get dispatched (maybe partially depending on context) on different threads, then one can study (by writing a program for analyzing and filtering the produced trace log ex post) the behaviour (the sequence of executing methods where context may influence that sequence) of specific instances of a specific scope, attempting to find out whether irregularities exist and if so analyze how they became to be going up the mtPrefix'ed trace log.

This information may not be so important for rather simple multithreaded traces, but in complex situations this should serve as a big time saver for humans and for the programs they write for analyzing huge mtPrefix trace logs ex post.

---

One idea that came up while thinking about your comment (not wanting to clutter which is important) would be the following: define the class attribute mtPrefix to allow for the following values instead of .true/.false as suggested so far (only the option's first letter mandatory):

 * "None" ... no mtPrefix gets generated (default)

 * "Full" ... the full mtPrefix will be generated by makeString, i.e. "[R1   T1   I5 
  G V1   L2   *] "

 * "Standard" ... an mtPrefix will be generated by makeString, that leaves out 
the Rexx interpreter
   instance and the variable dictionary number, i.e. "[T1   I5   G L2   *] "

The default value would be "None", no mtPrefix gets created in the trace message. Otherwise the programmer can chose whether he wishes a full or a standard mtPrefix to be created by LogObject. This might cover most use cases.

In addition the programmer will be free to use the LogObject information freely to create whatever he thinks will be helpful for debugging the multithreaded program in hand. Therefore if any information in mtPrefix is seen as clutter or uninteresting for a programmer he can easily change that for his mtPrefix trace logs. The same if he wishes to add additional information, e.g. adding timestamps (maybe for profiling) to mtPrefix etc.

---

It would be most helpful if it became possible to indicate in the last character a blocking/waiting state, such that '*' (indicating method is currently guarded and has the object lock) and ' ' (then only if the method is currently unguarded) indicate executing, 'B' (or 'W') indicate blocking/waiting (indicating a method currently guarded and waiting on the object's lock). This would ease analyzing the trace log considerably, if interested to find the blocked statements in a multithreaded program in case of deadlocks.

---rony



On Mon, Jan 22, 2024 at 11:32 AM Rony G. Flatscher <rony.flatsc...@wu.ac.at> 
wrote:

    Here an ooRexx implementation of the proposed TraceObject class in today's 
"Proposal for
    multithreaded trace prefix" class:

        /* 
========================================================================= */ 
::class
        "TraceObject" subclass StringTable public /*
        
------------------------------------------------------------------------- */ 
::attribute
        mtPrefix class -- if .true causes the mtPrefix to be created /*
        
------------------------------------------------------------------------- */ 
::method
        MAKESTRING if self~class~mtPrefix<>.true then -- do not show 
multithreaded prefix return
        self["TRACELINE"] -- return standard trace line mb = .MutableBuffer~new 
-- for performance
        reasons mb~append("[") mb~append("R", adjLeft(self["INSTANCE"] ,3), " 
") -- R_exx
        interpreter instance mb~append("T", adjLeft(self["THREAD"] ,3), " ") -- 
T_hread/activity
        mb~append("I", adjLeft(self["INVOCATION"],3) ) -- I_nvocation/activation
        vd=self["VARIABLEDICTIONARY"] if vd<>0 then -- an object's variable 
dictionary in hand, we
        are in a method do mb~append(" ") mb~append(self["ISGUARDED"]~?("G","U") , " 
") --
        G_uarded or U_unguarded mb~append("V", adjLeft(vd ,3), " ") -- 
V_ariable dictionary pool
        mb~append("L", adjLeft(self["LOCKCOUNT"],3), " ") -- L ... lock reserve 
count
        mb~append(self["ISLOCKED"]~?("*"," ")) -- asterisk to indicate holding 
object lock (can
        execute) end mb~append("] ", self["TRACELINE"]) return mb~string -- 
return trace line with
        mtPrefix adjLeft: procedure -- left adjust, but make sure we show all 
chars use arg value,
        width if value~length>=width then -- no left adjustment return value 
return
        value~left(width) -- left adjust with given width

    ---rony

_______________________________________________
Oorexx-devel mailing list
Oorexx-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/oorexx-devel

Reply via email to