Introduction
     GUTS (Global UnThreaded
      object Store) is a low-level class which can be used by
      other classes. By itself it does nothing and adds no value to a program.
      However it allows other objects to communicate with each other, across
      threads, even when the object is not the topmost window on the thread.
      This is a required layer for some other CapeSoft Accessories, and is
      provided free of charge. 
    ClarionLive
     An introduction to this class, and the way in which it
      works, was described in 
ClarionLive session #234 , recorded on 1 November
      2013.
      
      During this webinar a small example class, LeftRight was created. The
      LeftRight class is included in the GUTS install. The LeftRight class is
      not documented here, for more discussion on this class see the webinar.
 
    Installation
     Run the supplied installation file: 
    Jump Start
     Add the global extension to your app file. 
    Support
     Your questions, comments and suggestions are welcome.
      Check our web page (
www.capesoft.com)
      for new versions. You can also contact us in one of the following ways:
      
      
        
          
            | CapeSoft Support | 
          
          
            | Support Page | 
            Find support page with various options here | 
          
          
            | Email | 
              | 
          
          
            | Telephone | 
            +27 87 828 0123 | 
          
        
      
     
     Distribution
     No additional files are required for shipping.
    
     Basic Description
     A single GUTS object, called ThisGuts
        is added to the application. This object is unthreaded, and thus
      is available to other objects on all threads. 
      
      The object maintains a queue of Interfaces. Other objects can add or
      remove themselves to this queue. Objects can Post an Event to other
      objects in the queue. Events are just a number, and any number can be
      used. It is envisaged that a number of "common events" may be added to
      GUTS at some point in the future, so it is recommended that custom events
      are equal to  Guts:User or more.
      
      Each object in the queue has a family name, the number of the thread it is
      on and an ID. Messages can be posted to all objects in a family, all
      objects on a thread, or a single object (if you know its ID).
      
      Classes implement the Interface, and when an event is posted into ThisGuts
        it is passed on to the class via this interface. What the class
      does with the event is entirely up to the class.
    
    How to use GUTS in a class
    
      Implement the Interface in the
        Class
      
        
          - In INC file: Add Include('Guts.inc'),Once
            near the top of the file.
 
          - In INC file: Add ,IMPLEMENTS(GutsInterface)
            to the Class declaration
 
          - In INC file: Add two new properties;
            Guts &Guts
              GutsId Long
             
          - In CLW File: Add classname.GutsInterface.TakeEvent
            method. For Example;
            
            something.GutsInterface.TakeEvent
              PROCEDURE(Long pEvent, <Long Param1>, <Long Param2>,
              <Long Param3>, <Long Param4>, <String Param5>,
              <String Param6>, <String Param7>, <String
              Param8>)
                CODE
                case pEvent
                of Guts:User+1          Self.Refresh()      End
             
          - In CLW File: In DESTRUCT method add
            
            If not self.Guts &= Null and Self.GutsId
              <> 0
                self.Guts.Delete(self.GutsId)
              End 
          - In CLW File: Change the  INIT method
            declaration, adding the Guts parameter
            (Guts pGuts)  
           
          - In the CLW file: In the INIT method
            set the new properties as follows;
            
            self.Guts &= pGuts
              self.GutsId = self.Guts.Add('familyName',self.GutsInterface) 
            The first parameter in the call above is the "familyname" for the
            object. The Post (as described below) will usually limit events to
            objects in the same family. The family name can be anything you
            like, although name clashes with other classes are undesirable. 
        
       
      Post an Event
       The PostEvent method of the GUTS Class takes a
        number of parameters. The first parameter is the event number. The next
        3 allow the scope of the Post to be restricted, and the following 8 are
        optional parameters that are passed to the interface. The method returns
        the number of interfaces which received the event.
        
        The parameters to this method are as follows;
        
          
            
              | Parameter | 
              Description | 
            
            
              | Event Long | 
              The event number that is passed to the interfaces. Any number
                can be used, but for future compatibility use numbers equal to
                or more than Guts:User | 
            
            
              | Family String(20) | 
              Limit the Post to all objects of this family | 
            
            
              | Thread Long (optional) | 
              Limit the Post to all objects on this thread. (This can be
                combined with the previous parameter to limit to objects of a
                specific family, on a specific thread) | 
            
            
              | ID Long (optional) | 
              Limit the post only to the object with this ID. If this
                parameter is set then the previous two parameters are ignored. | 
            
            
              | Param1..Param4 Long (optional) | 
              Four optional parameters of type LONG which will be passed
                unaltered to the Interfaces. | 
            
            
              | Param5..Param8 String (optional) | 
              Four optional parameters of type STRING which will be passed
                unaltered to the Interfaces. | 
            
          
        
        The method can be called from wherever you like in your code. Here are
        some possible calls;
        
        
ThisGuts.PostEvent(Guts:User+1,'familyname') 
        ThisGuts.PostEvent(Guts:User+1,'familyname',thread())
          
          ThisGuts.PostEvent(Guts:EventRefresh,'') ThisGuts.PostEvent(Guts:User+1,'',0,x) ThisGuts.PostEvent(Guts:User+1,'familyname',0,0,x,y,z)
          
        
       
      Care with Pointers
       An object which hooks into GUTS in the above way has
        one characteristic which is different from a normal class, and needs to
        be allowed for.
        
        By passing a pointer to its interface to GUTS, you are implicitly
        implying that the object can be accessed from thread 1. In other words,
        your object code can run on thread 1 even though your object is
        instantiated on thread 2.
        
        This is not a problem, unless your object in turn contains a pointer to
        a global THREADED variable, like a file handle. There may be cases where
        this access of "thread 2" memory, from thread 1 may(*) cause a problem.
        Fortunately there is a solution.
        
        Ideally your class should store two pointers when dealing with a global,
        threaded, variables. The "INSTANCE 0" of that variable, and the "current
        thread" INSTANCE for general use. The following example shows this in
        action.
        
        FirstRecord Class()
          MyFile0       &file
          MyFile        &file
          Init          Procedure(File pFile)
          Get           Procedure()
                      end
          
          FirstRecord.Init Procedure(File pFile)
            Code
            self.Myfile0 &= INSTANCE(pFile,0)
          
          FirstRecord.Get Procedure()
            Code
            self.MyFile &= INSTANCE(self.Myfile0,Thread()) 
            Get(self.MyFile,1)
        
        In the above code the class is making sure the "Instance 0" pointer is
        stored by the Init method, and then the "Current Instance" is set before
        the pointer is used. 
        
        (*) In our experience of using GUTS so far, pointers to memory fields
        are not a problem in this context (outside of normal memory
        syncronisation). The problem is when you are pointing to data structures
        (like Files) which are then used by code (File Drivers) which do not
        support this context switch.
     
    Getting a GPF?
     The most likely reason for a GPF when POSTing an Event
      is if an object has added itself to the Interface Queue, but not removed
      itself from the queue when it goes out of scope. 
      In other words the line of code
      
      
self.Guts.Delete(self.GutsId)
      
      has not been added to the DESTRUCT method of the class. 
      
      A second common reason for a GPF when POSTing an event is if the object
      contains File handling code, and that code does not take sufficient care
      over the thread change. See the section
 Care with
        Pointers for more information on this.
 
    Examples
     There are four examples included with the Install.
      They show how to apply the template an ABC or Legacy app, as a simple Exe
      or in a Multi-DLL setup. 
      
      The single EXE, ABC demo app has an additional bit of code showing how the
      GUTS Object might be called - in this case by a very small class called
      LeftRight. An example of posting events is in the Main procedure, and an
      instance of the LeftRight class has been added (manually) to each window.
      You can see the LeftRight class in action in this example by using the
      items in the Tools menu.
      
      This example, with LeftRight added completely by hand is a good example of
      adding any class to an app by hand. there are a few things to take note
      of;
      
        - Global Embeds, After Global Includes, is the line
          include('leftright.inc'),Once
          This makes the class visible to the application. 
        - Project Defines include;
          LeftRightLinkMode=>1
            LeftRightDLLMode=>0
          This is important so that the application does not GPF when it
          encounters the class. these settings will change in a multi-dll
          situation, if in doubt set the values the same as the GUTSLinkMode and
          the GUTSDllMode. 
        - In a procedure an instance of the class is created with the line
          LR LeftRight
          LR is the name of the Object. LeftRight
            is the name of the class. 
        - After the window is opened the LR Object is initialized with
          LR.Init(ThisGuts) 
      
      A Post is set to all the objects from the MAIN procedure, and looks
      something like this;
      
ThisGuts.PostEvent(guts:user,'lefttoright',0,0,1) 
     
    Template Reference
    
      Global Extension
       This template adds the Global ThisGuts object to the
        application.
        
General Tab
        
          Disable All GUTS Features
          If this is ticked on the object will not be generated. 
 
        Multi-DLL Tab
        
          This is part of a Multi-DLL program
          Tick this on if this app is part of a multiple-app system. This is
          turned on for all the DLL's and the EXE's.
          
Export Class from this DLL
          Tick this on in the app which will export the class. This is almost
          always the Data DLL app. In all other apps, DLLs and EXE's, leave this
          off. 
 
        Classes Tab
        
          Class Version
          The last date when the class was parsed from the LibSrc folder. Used
          internally. Do not change.
          
Object Name
          The name of the object to create, usually 
ThisGuts.
          
Class Name
          The name of the class to use, usually 
Guts.
        
 
       
     
    Object Reference
    
      
      Purpose
       The Guts class maintains a Queue of interfaces.
        Other objects can add or remove themselves from this queue. A method is
        provided so that notifications can be sent to all the interfaces in the
        queue.
      GUTS Interface
      
        TakeEvent
         TakeEvent(Long
            pEvent, <Long Param1>, <Long Param2>, <Long
            Param3>, <Long Param4>, <String Param5>, <String
            Param6>, <String Param7>, <String Param8>)
          
          Description
          
          Receives an event posted by the Guts class. How an object processes
          the event is completely up to the class implementing the interface.
          
          Note that this isn't a Clarion or Windows event, but rather just a
          notification to the interface. 
          
          
Parameters
          
          
            
              
                | Parameter | 
                Description | 
              
              
                | pEvent | 
                An event number that has meaning to the receiving object. | 
              
              
                | Param1...Param4 | 
                Four optional LONG parameters containing additional
                  information for the object. | 
              
              
                | Param5...Param8  | 
                Four optional STRING parameters containing additional
                  information for the object. | 
              
            
          
          
          Return Value
          
          none
          
          
Example
          
          Leftright.GutsInterface.TakeEvent Procedure(Long
            pEvent, <Long Param1>, <Long Param2>, <Long
            Param3>, <Long Param4>, <String Param5>, <String
            Param6>, <String Param7>, <String Param8>)
              CODE
              case pEvent
              of Guts:User
                Self.SetDirection(Param1)
              End
          
         
       
      Properties
      
        
          
            
              | Property | 
              Description | 
            
            
              | iQueue   &GutsQueueType | 
              A queue of interfaces. | 
            
            
              | LastId   Long | 
              As each item is added to the queue it is given a unique id.
                This property contains the number of the last id issued. | 
            
            
              | cs   &ICriticalSection | 
              A critical section to manage access to the global, unthreaded
                queue safely. | 
            
          
        
       
      Methods
      
        
        Add
         Add(String
            pFamily, GutsInterface pInterface)
          
          Description
          
          Adds an interface to the queue. Generally called by a class which
          implements the interface when it wishes to add itself to the global
          queue.
          
          
Parameters
          
          
            
              
                | Parameter | 
                Description | 
              
              
                | pFamily | 
                A short string containing a unique family name for the class
                  which is registering itself. Events can be posted by family,
                  so this allows an object to post events only to objects of the
                  same family. | 
              
              
                | pInterface | 
                The GutsInterface as implemented in the calling class. | 
              
            
          
          
          Return Value
          
          Long. The unique ID of the object in the Guts Queue is returned. The
          calling object should store this, and use it as the parameter to the
          Delete method when the calling object goes out of scope.
          
          
Example
          
          Leftright.Init Procedure(Guts pGuts)
              CODE
              If not pGuts &= Null
                self.Guts &= pGuts
                self.GutsId = self.Guts.Add(family:leftright,self.GutsInterface)
              End
          
          See Also
          
          Delete 
          
         
        Construct
         Construct()
          
          Description
          
          Automatically called when the Guts object comes into scope. Does some
          basic initialization of the object.
          
          Parameters
          
          None 
          
          Return Value
          
          None
          
          
        
        Delete
         Delete(long pId)
          
          Description
          
          Allows an object to delete itself from the Interface queue. It's very
          important that an object does this when it goes out of scope, as
          leaving it in the queue, once the object has gone out of scope, will
          lead to a GPF the next time an event is posted.
          
          
Parameters
          
          
            
              
                | Parameter | 
                Description | 
              
              
                | pID | 
                The Unique ID of the object to delete. The unique ID was
                  returned to the object when the Add method was called. | 
              
            
          
          
          Return Value
          
          None
          
          
Example
          
          Leftright.Destruct Procedure()
              CODE
              If not self.guts &= Null
                self.Guts.Delete(self.GutsId)
              End
          
          See Also
          
          Add 
          
         
        Destruct
         Destruct()
          
          Description
          
          Automatically called when the Guts object goes out of scope. Does some
          basic clean up of the object.
          
          Parameters
          
          None 
          
          Return Value
          
          None
          
          
        
        PostEvent
         PostEvent(long
            pEvent, String pFamily, Long pThread=0,Long pId=0, <Long
            Param1>, <Long Param2>, <Long Param3>, <Long
            Param4>, <String Param5>, <String Param6>, <String
            Param7>, <String Param8>)
          
          Description
          
          Used to post a notification to one or more items in the interface
          queue. 
          
          The items being posted to can be identified by ID, or alternatively by
          a combination of Family and Thread. If the Family is set then only
          objects of this family will receive the event. Likewise if the Thread
          is set then only objects on that thread will receive the event. If
          both Family and Thread are set then only objects of that family, on
          that one specific thread, will receive the event.
          
          
Parameters
          
          
            
              
                | Parameter | 
                Description | 
              
              
                | pEvent | 
                The number of the event to send to the objects. Note this is
                  not a Clarion EVENT - you can use any number you like. Numbers
                  >= Guts:User are recommended for future-compatibility. | 
              
              
                | pFamily | 
                If this parameter is set, then only objects in this family
                  will receive the event. An object sets its family when calling
                  the Add method. | 
              
              
                | pThread | 
                If this parameter is 0 then the event is sent to all the
                  threads. If it contains a thread number, then the event will
                  only be sent to that specific thread.  | 
              
              
                | pId | 
                If this parameter is set then only this object will receive
                  the event, regardless of the Thread or Family parameters. | 
              
              
                | Param1...Param8 | 
                Additional optional parameters that will be passed on to the
                  receiving object. | 
              
            
          
          
          Return Value
          
          The number of objects that received the event is returned.
          
          
Example
          
          ThisGuts.PostEvent(guts:user,family:leftright,0,0,1)
          
          See Also
          
          Post An Event 
          
         
        Release
         Release(Long
            pId)
          
          Description
          
          Releases the CriticalSection. Calls to Release MUST be paired with a
          call to the 
WAIT method. Each WAIT requires 1,
          and only 1, RELEASE. Failure to balance WAIT and RELEASE calls will
          cause bugs in your program that are extremely difficult to find.
          This method is used inside the class itself, and is not normally
          called from outside the class.
          
          
Parameters
          
          
            
              
                | Parameter | 
                Description | 
              
              
                | pId | 
                Used for debugging purposes. If each call to Wait and
                  Release has a unique pId, then it's easier to detect
                  mismatched Wait/Release pairs.  | 
              
            
          
          
          Return Value
          
          None
          
          
Example
          
          self.Release(3)
          
          See Also
          
          Wait 
          
         
        Trace
         Trace(string
            pStr)
          
          Description
          
          Sends a string to the Windows Debug Output, where it can be monitored
          using 
 Debugview. Useful when debugging the class.
          
          
Parameters
          
          
            
              
                | Parameter | 
                Description | 
              
              
                | pStr | 
                The String to send to Debugview. The string will be
                  prepended with the identifier  [guts]
                 | 
              
            
          
          
          Return Value
          
          None
          
          
Example
          
          Self.Trace('Hello World')
          
         
        Wait
         Wait(Long pId)
          
          Description
          
          Waits the CriticalSection. Calls to Wait MUST be paired with a call to
          the RELEASE method. Each WAIT requires 1, and only 1, RELEASE. Failure
          to balance WAIT and RELEASE calls will cause bugs in your program that
          are extremely difficult to find.
          This method is used inside the class itself, and is not normally
          called from outside the class.
          
          
Parameters
          
          
            
              
                | Parameter | 
                Description | 
              
              
                | pId | 
                Used for debugging purposes. If each call to Wait and
                  Release has a unique pId, then it's easier to detect
                  mismatched Wait/Release pairs.  | 
              
            
          
          
          Return Value
          
          None
          
          
Example
          
          self.Wait(3)
          
          See Also
          
          Release 
          
         
       
     
    Version History
     1.11 - 24 May 2025 
      
      1.10 - 24 May 2021
      
        - Add: Clarion 11.1 to install.
 
      
      1.09 - 18 September 2018 
      
        - Add: Clarion 11 to install.
 
      
      1.08 - 1 December 2015 
      
        - Fix: An endless loop in PostEvent was possible if both Family and
          Thread were passed.
 
        - Fix: PostEvent did not apply the Thread parameter if the Family
          parameter was blank.
 
      
      1.07 - 16 April 2015 
      
        - Changed name of global template variables %ObjectName and %ClassName
          to avoid clashes with other tools.
 
      
      1.06 - 25 February 2015 
      
      1.05 - 30 July 2014
      
        - Updated with Cape templates version 4.07 (no material change, just
          doc in cape01.tpw updated.) 
 
      
      1.04 - 21 January 2014
      
      1.03 - 13 January 2014
      
        - Updated template to Cape 4.06 level. 
 
      
      1.02 - 6 January 2014
      
        - Updated template to Cape 4.05 level. Should make some Legacy
          generation problems go away.
 
      
      1.01 - 4 November 2013
      
        - Various tweaks to the LeftRight class as discussed during the
          webinar
 
        - Refactor of PostEvent method so that calls
          to the TakeEvent method are outside the
          CriticalSection (as discussed in the webinar)
 
        - Template Reference added to the
          docs.
 
        - Object Reference added to docs.
 
      
      1.00 - 1 November 2013