Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • Home
  • SEARCH
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 313739
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 12, 20262026-05-12T08:08:09+00:00 2026-05-12T08:08:09+00:00

I’ve been mucking around with Allen Bauer’s code for a generic multicast event dispatcher

  • 0

I’ve been mucking around with Allen Bauer’s code for a generic multicast event dispatcher (see his blog posts about it here).

He gives just enough code to make me want to use it, and unfortunately he hasn’t posted the full source. I had a bash at getting it to work, but my assembler skills are non-existent.

My problem is the InternalSetDispatcher method. The naive approach is to use the same assembler as for the other InternalXXX methods:

procedure InternalSetDispatcher;
begin
   XCHG  EAX,[ESP]
   POP   EAX
   POP   EBP
   JMP   SetEventDispatcher
end;

But this is used for procedures with one const parameter, like this:

procedure Add(const AMethod: T); overload;

And SetDispatcher has two parameters, one a var:

procedure SetEventDispatcher(var ADispatcher: T; ATypeData: PTypeData);

So, I assume that the stack would get corrupted. I know what the code is doing (cleaning up the stack frame from the call to InternalSetDispatcher by popping the hidden reference to self and I assume the return address), but I just can’t figure out that little bit of assembler to get the whole thing going.

EDIT: Just to clarify, what I am looking for is the assembler that I could use to get the InternalSetDispatcher method to work, ie, the assembler to cleanup the stack of a procedure with two parameters, one a var.

EDIT2: I’ve amended the question a little, thank you to Mason for his answers so far. I should mention that the code above does not work, and when SetEventDispatcher returns, an AV is raised.

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-12T08:08:09+00:00Added an answer on May 12, 2026 at 8:08 am

    The answer, after I have done a lot of running around on the web, is that the assembler assumes that a stack frame is present when calling in to InternalSetDispatcher.

    It seems that a stack frame was not being generated for the call to InternalSetDispatcher.

    So, the fix is as easy as turning on stack frames with the {$stackframes on} compiler directive and rebuilding.

    Thanks Mason for your help in getting me to this answer. 🙂


    Edit 2012-08-08: If you’re keen on using this, you might want to check out the implementation in the Delphi Sping Framework. I haven’t tested it, but it looks like it handles different calling conventions better than this code.


    Edit: As requested, my interpretation of Alan’s code is below. On top of needing stack frames turned on, I also needed to have optimization turned on at the project level for this to work:

    unit MulticastEvent;
    
    interface
    
    uses
      Classes, SysUtils, Generics.Collections, ObjAuto, TypInfo;
    
    type
    
      // you MUST also have optimization turned on in your project options for this
      // to work! Not sure why.
      {$stackframes on}
      {$ifopt O-}
        {$message Fatal 'optimisation _must_ be turned on for this unit to work!'}
      {$endif}
      TMulticastEvent = class
      strict protected
        type TEvent = procedure of object;
      strict private
        FHandlers: TList<TMethod>;
        FInternalDispatcher: TMethod;
    
        procedure InternalInvoke(Params: PParameters; StackSize: Integer);
        procedure SetDispatcher(var AMethod: TMethod; ATypeData: PTypeData);
        procedure Add(const AMethod: TEvent); overload;
        procedure Remove(const AMethod: TEvent); overload;
        function IndexOf(const AMethod: TEvent): Integer; overload;
      protected
        procedure InternalAdd;
        procedure InternalRemove;
        procedure InternalIndexOf;
        procedure InternalSetDispatcher;
    
      public
        constructor Create;
        destructor Destroy; override;
    
      end;
    
      TMulticastEvent<T> = class(TMulticastEvent)
      strict private
        FInvoke: T;
        procedure SetEventDispatcher(var ADispatcher: T; ATypeData: PTypeData);
      public
        constructor Create;
        procedure Add(const AMethod: T); overload;
        procedure Remove(const AMethod: T); overload;
        function IndexOf(const AMethod: T): Integer; overload;
    
        property Invoke: T read FInvoke;
      end;
    
    implementation
    
    { TMulticastEvent }
    
    procedure TMulticastEvent.Add(const AMethod: TEvent);
    begin
      FHandlers.Add(TMethod(AMethod))
    end;
    
    constructor TMulticastEvent.Create;
    begin
      inherited;
      FHandlers := TList<TMethod>.Create;
    end;
    
    destructor TMulticastEvent.Destroy;
    begin
      ReleaseMethodPointer(FInternalDispatcher);
      FreeAndNil(FHandlers);
      inherited;
    end;
    
    function TMulticastEvent.IndexOf(const AMethod: TEvent): Integer;
    begin
      result := FHandlers.IndexOf(TMethod(AMethod));
    end;
    
    procedure TMulticastEvent.InternalAdd;
    asm
      XCHG  EAX,[ESP]
      POP   EAX
      POP   EBP
      JMP   Add
    end;
    
    procedure TMulticastEvent.InternalIndexOf;
    asm
      XCHG  EAX,[ESP]
      POP   EAX
      POP   EBP
      JMP   IndexOf
    end;
    
    procedure TMulticastEvent.InternalInvoke(Params: PParameters; StackSize: Integer);
    var
      LMethod: TMethod;
    begin
      for LMethod in FHandlers do
      begin
        // Check to see if there is anything on the stack.
        if StackSize > 0 then
          asm
            // if there are items on the stack, allocate the space there and
            // move that data over.
            MOV ECX,StackSize
            SUB ESP,ECX
            MOV EDX,ESP
            MOV EAX,Params
            LEA EAX,[EAX].TParameters.Stack[8]
            CALL System.Move
          end;
        asm
          // Now we need to load up the registers. EDX and ECX may have some data
          // so load them on up.
          MOV EAX,Params
          MOV EDX,[EAX].TParameters.Registers.DWORD[0]
          MOV ECX,[EAX].TParameters.Registers.DWORD[4]
          // EAX is always "Self" and it changes on a per method pointer instance, so
          // grab it out of the method data.
          MOV EAX,LMethod.Data
          // Now we call the method. This depends on the fact that the called method
          // will clean up the stack if we did any manipulations above.
          CALL LMethod.Code
        end;
      end;
    end;
    
    procedure TMulticastEvent.InternalRemove;
    asm
      XCHG  EAX,[ESP]
      POP   EAX
      POP   EBP
      JMP   Remove
    end;
    
    procedure TMulticastEvent.InternalSetDispatcher;
    asm
      XCHG  EAX,[ESP]
      POP   EAX
      POP   EBP
      JMP   SetDispatcher;
    end;
    
    procedure TMulticastEvent.Remove(const AMethod: TEvent);
    begin
      FHandlers.Remove(TMethod(AMethod));
    end;
    
    procedure TMulticastEvent.SetDispatcher(var AMethod: TMethod;
      ATypeData: PTypeData);
    begin
      if Assigned(FInternalDispatcher.Code) and Assigned(FInternalDispatcher.Data) then
        ReleaseMethodPointer(FInternalDispatcher);
      FInternalDispatcher := CreateMethodPointer(InternalInvoke, ATypeData);
      AMethod := FInternalDispatcher;
    end;
    
    { TMulticastEvent<T> }
    
    procedure TMulticastEvent<T>.Add(const AMethod: T);
    begin
      InternalAdd;
    end;
    
    constructor TMulticastEvent<T>.Create;
    var
      MethInfo: PTypeInfo;
      TypeData: PTypeData;
    begin
      MethInfo := TypeInfo(T);
      TypeData := GetTypeData(MethInfo);
      inherited Create;
      Assert(MethInfo.Kind = tkMethod, 'T must be a method pointer type');
      SetEventDispatcher(FInvoke, TypeData);
    end;
    
    function TMulticastEvent<T>.IndexOf(const AMethod: T): Integer;
    begin
      InternalIndexOf;
    end;
    
    procedure TMulticastEvent<T>.Remove(const AMethod: T);
    begin
      InternalRemove;
    end;
    
    procedure TMulticastEvent<T>.SetEventDispatcher(var ADispatcher: T;
      ATypeData: PTypeData);
    begin
      InternalSetDispatcher;
    end;
    
    end.
    
    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

I have a jquery bug and I've been looking for hours now, I can't
link Im having trouble converting the html entites into html characters, (&# 8217;) i
I have a string like this: La Torre Eiffel paragonata all&#8217;Everest What PHP function
I have this code to decode numeric html entities to the UTF8 equivalent character.
I'm parsing an RSS feed that has an &#8217; in it. SimpleXML turns this
I have this code: - (void)parser:(NSXMLParser *)parser foundCDATA:(NSData *)CDATABlock { NSString *someString = [[NSString
I have a bunch of posts stored in text files formatted in yaml/textile (from
I ran into a problem. Wrote the following code snippet: teksti = teksti.Trim() teksti
That's pretty much it. I'm using Nokogiri to scrape a web page what has
I have just tried to save a simple *.rtf file with some websites and

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.