Results 1 to 4 of 4

Thread: Centralized Timer Host Demo

  1. #1

    Thread Starter
    PowerPoster
    Join Date
    Aug 2010
    Location
    Canada
    Posts
    2,651

    Centralized Timer Host Demo

    So this one is a little bit different - it's the first code I've written in a long time that I have no use for personally, nor can I really imagine a use for it. That said, it was fun to write and it has some interesting features that I think might be useful to somebody out there, so I figured I'd share it.

    As I was nodding off to sleep the other day, I got thinking about a different approach to Timers (as one often does when nodding off to sleep). The idea that came to mind was to have a single centralized timer "host" that any number of timer "clients" can register with and be notified when the appropriate interval has elapsed, instead of the usual method of having Timer controls and/or Timer classes in all your classes/forms.

    The more I thought about it, the more I thought this approach would offer some interesting properties/behaviours - for example, it would be possible to easily pause/unpause all the timer clients in one call, and even selectively pause/unpause timers based on individual instances or various "groups" of instances (for example, implementing Class Type, Tag, or combinations thereof). Maybe useful for certain types of games?

    So I set to work straight away...

    Name:  2025-02-01_11-22-53a.jpg
Views: 189
Size:  40.9 KB

    And a couple days later, I had something that seems to work reasonably well and includes a fairly comprehensive demo form for testing/experimenting:

    Name:  2025-02-01_11-47-06.jpg
Views: 202
Size:  28.7 KB

    And here is the full source + demo for anyone that is interested in trying it out:

    SOURCE CODE + DEMO: TimerHostDemo2.zip


    IMPORTANT NOTE: The code is very new and lightly tested, so there will likely be bugs or undesired operation under certain loads that I haven't considered yet. Please report any problems here and I will try to address them promptly.

    Before You Begin

    It will be useful to understand some core concepts before you begin:

    • A Timer Host is an instance of the cTimerHost class (provided with the demo source). It can be instantiated anywhere (Class Module, Form, Standard Module) and it includes no Events.

    • A Timer Client is an instance of any class that implements the ITimerClient interface (provided with the demo source). Timer clients will be any of your classes or forms that you want to register with a Timer Host to process code at specified intervals.

    • The ITimerClient interface is a very simple interface with only 2 methods: ITimerClient_TimerFired() and ITimerClient_IsTypeOfMe(). See the ITimerClient class that is included with the demo for details on how to implement these methods.

    • A Timer Entry is a unique combination of Timer Client instance (identified by ObjPtr) and Tag that is registered with a Timer Host instance. So any single Timer Client instance can be registered with any number of Tags, and each combination of Timer Client instance and Tag will be a Timer Entry in the Timer Host.

    • You can register any number of Timer Client instances (even from different ITimerClient implementing classes) and Tags with a single Timer Host (up to the point of system resource exhaustion anyway).


    Them's the basics! Hopefully between the above, the demo code, and the cdode comments you will be able to understand how it all works, but I'm happy to answer any questions you may have here.

    Final Thoughts

    I'd also be very interested to hear whether you think this type of Timer approach has any real-world uses, and if so, what they might be. Or is this approach a generally bad idea borne of the kind of logic you only experience at the "twilight zone" before sleep? In any case, enjoy it and use it if you can, otherwise chuck it in the bin
    Last edited by jpbro; Feb 2nd, 2025 at 10:51 AM.

  2. #2

    Thread Starter
    PowerPoster
    Join Date
    Aug 2010
    Location
    Canada
    Posts
    2,651

    Re: Centralized Timer Host Demo

    PUBLIC METHOD DOCUMENTATION




    TIMER ENTRIES COLLECTION INFO & MANAGEMENT

    TimerEntryCount()

    Returns the number of timer entries.

    ITimerClientByObjPtr(p_ObjPtr As Long) As ITimerClient

    Retrieves an ITimerClient instance by its object pointer.

    UniqueITimerClientInstances() As ITimerClient()

    Returns an array of unique ITimerClient instances (by ObjPtr) from the collection of timer entries.

    TimerEntryByIndex(p_ZeroBasedIndex As Long) As ITimerClient

    Returns an ITimerClient instance by index in the collection of timer entries.

    TimerEntryIsPausedByIndex(p_ZeroBasedIndex As Long) As Boolean

    Returns whether a timer entry is paused at the specified index.

    TimerEntryIsPausedByIndex(p_ZeroBasedIndex As Long, p_IsPaused As Boolean)

    Sets the paused/unpaused state of a timer entry by its index.

    TimerEntryTagByIndex(p_ZeroBasedIndex As Long) As String

    Returns the tag of a timer entry at the specified index.

    TimerEntryIntervalMsByIndex(p_ZeroBasedIndex As Long) As Long

    Returns the timer interval (in milliseconds) of a timer entry at the specified index.

    TimerEntryLastFiredMsAgoByIndex(p_ZeroBasedIndex As Long) As Long

    Returns the time elapsed (in milliseconds) since the last interval for a timer entry at the specified index.

    Tags() As String()

    Returns a sorted string array of all unique tags across timer entries. Mostly useful for UI reporting/debugging.

    TagsByInstance(po_TimerClient As ITimerClient) As String()

    Returns a sorted string array of all tags assigned to a specific ITimerClient instance. Mostly useful for UI reporting/debugging.

    TagsByTypeOf(po_TimerClient As ITimerClient) As String()

    Returns a sorted string array of unique tags assigned to multiple instances of a specific ITimerClient class. Mostly useful for UI reporting/debugging.




    TIMER ENTRY MANAGEMENT

    AddTimerEntry(po_TimerClient As ITimerClient, p_Tag As String, p_TimerIntervalMs As Long)

    Adds a timer client to the pool by tag. If the combination of Instance & Tag exists, it updates the interval.

    RemoveTimerEntries()

    Removes all timer entries, resetting the class.

    RemoveTimerEntriesByInstance(po_TimerClient As ITimerClient)

    Removes all timer entries matching the ObjPtr of the given ITimerClient instance.

    RemoveTimerEntriesByTypeOf(po_TimerClient As ITimerClient)

    Removes all timer entries matching the ITimerClient_IsTypeOfMe result of the given instance.

    RemoveTimerEntriesByTypeName(po_TimerClient As ITimerClient)

    Removes all timer entries matching the TypeName() of the given instance.

    RemoveTimerEntriesByTypeOfAndTag(po_TimerClient As ITimerClient, p_Tag As String)

    Removes timer entries matching the ITimerClient_IsTypeOfMe result and the given tag.

    RemoveTimerEntriesByTypeNameAndTag(po_TimerClient As ITimerClient, p_Tag As String)

    Removes timer entries matching the TypeName() result and the given tag.

    RemoveTimerEntriesByInstanceAndTag(po_TimerClient As ITimerClient, p_Tag As String)

    Removes timer entries matching the ObjPtr of the given instance and the given tag.

    RemoveTimerEntriesByTag(p_Tag As String)

    Removes all timer entries matching the given tag, regardless of client type.

    RemoveTimerEntryByIndex(p_ZeroBasedIndex As Long)

    Removes a timer entry by index.




    PAUSE STATE INFORMATION

    IsPausedGlobally() As Boolean

    Returns whether the global pause state is enabled.

    IsPausedByInstance(po_TimerClient As ITimerClient) As Boolean

    Returns a count of paused timer entries matching the ObjPtr of the given ITimerClient.

    IsPausedByTypeOf(po_TimerClient As ITimerClient) As Boolean

    Returns a count of paused timer entries matching the ITimerClient_IsTypeOfMe result.

    IsPausedByTypeName(po_TimerClient As ITimerClient) As Boolean

    Returns a count of paused timer entries matching the TypeName() result.

    IsPausedByInstanceAndTag(po_TimerClient As ITimerClient, p_Tag As String) As Boolean

    Returns a count of paused timer entries matching the ObjPtr of the given instance and the given tag.

    IsPausedByTypeOfAndTag(po_TimerClient As ITimerClient, p_Tag As String) As Boolean

    Returns a count of paused timer entries matching the ITimerClient_IsTypeOfMe result and the given tag.

    IsPausedByTypeNameAndTag(po_TimerClient As ITimerClient, p_Tag As String) As Boolean

    Returns a count of paused timer entries matching the TypeName() result and the given tag.

    IsPausedByTag(p_Tag As String) As Boolean

    Returns a count of paused timer entries matching the given tag.




    PAUSE/UNPAUSE STATE MANAGEMENT

    PauseGlobally()

    Enables the global pause state.

    PauseTimerEntriesByInstance(po_TimerClient As ITimerClient)

    Pauses all timer entries matching the ObjPtr of the given instance.

    PauseTimerEntriesByTypeOf(po_TimerClient As ITimerClient)

    Pauses all timer entries matching the ITimerClient_IsTypeOfMe result.

    PauseTimerEntriesByTypeName(po_TimerClient As ITimerClient)

    Pauses all timer entries matching the TypeName() result.

    PauseTimerEntriesByInstanceAndTag(po_TimerClient As ITimerClient, p_Tag As String)

    Pauses all timer entries matching the ObjPtr of the given instance and the given tag.

    PauseTimerEntriesByTypeOfAndTag(po_TimerClient As ITimerClient, p_Tag As String)

    Pauses all timer entries matching the ITimerClient_IsTypeOfMe result and the given tag.

    PauseTimerEntriesByTypeNameAndTag(po_TimerClient As ITimerClient, p_Tag As String)

    Pauses all timer entries matching the TypeName() result and the given tag.

    PauseTimerEntriesByTag(p_Tag As String)

    Pauses all timer entries matching the given tag.

    UnpauseGlobally(Optional p_PausedTimerEntryHandling As e_PausedTimerEntriesHandling = LeaveAlone)

    Unpauses all timer entries matching the given handling mode.
    The optional PausedTimerEntriesHandling parameter controls how Timer Entries that were paused using non-Global Pause method are treated on Global Unpause. The default value is LeaveAlone which will leave all Timer Entries in the pause state that they were in when the Global Pause was applied. Pass UnpauseAll to unpause all Timer Entries, even if they were previously paused using one of the non-Global Pause methods.

    UnpauseTimerEntriesByInstance(po_TimerClient As ITimerClient)

    Unpauses all timer entries matching the ObjPtr of the given instance.

    UnpauseTimerEntriesByTypeOf(po_TimerClient As ITimerClient)

    Unpauses all timer entries matching the ITimerClient_IsTypeOfMe result.

    UnpauseTimerEntriesByTypeName(po_TimerClient As ITimerClient)

    Unpauses all timer entries matching the TypeName() result.

    UnpauseTimerEntriesByInstanceAndTag(po_TimerClient As ITimerClient, p_Tag As String)

    Unpauses all timer entries matching the ObjPtr of the given instance and the given tag.

    UnpauseTimerEntriesByTypeOfAndTag(po_TimerClient As ITimerClient, p_Tag As String)

    Unpauses all timer entries matching the ITimerClient_IsTypeOfMe result and the given tag.

    UnpauseTimerEntriesByTypeNameAndTag(po_TimerClient As ITimerClient, p_Tag As String)

    Unpauses all timer entries matching the TypeName() result and the given tag.

    UnpauseTimerEntriesByTag(p_Tag As String)

    Unpauses all timer entries matching the given tag.
    Last edited by jpbro; Feb 2nd, 2025 at 05:36 PM.

  3. #3

    Thread Starter
    PowerPoster
    Join Date
    Aug 2010
    Location
    Canada
    Posts
    2,651

    Re: Centralized Timer Host Demo

    Reserved for example code

  4. #4

    Thread Starter
    PowerPoster
    Join Date
    Aug 2010
    Location
    Canada
    Posts
    2,651

    Re: Centralized Timer Host Demo

    Updated source in the first post with a small change to a misleading Enum/Parameter names (swapped "TimerClient" for "TimerEntry"). No functionality changed.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width