Jump to content

kokoslolos

Members
  • Content Count

    7
  • Joined

  • Last visited

Community Reputation

1 Neutral

Recent Profile Visitors

The recent visitors block is disabled and is not being shown to other users.

  1. kokoslolos

    Properties and design time code

    I was planning to write this but I forgot, I use Delphi 2007. Does this solution work for this version of delphi?
  2. kokoslolos

    Properties and design time code

    Hi, First of all, I'm not an expert in writing design time code, but this what I'm trying to achieve. I have my own custom TAction descendant, lets call it TXAction, with extra published properties (like ActionCode, ActionID, ActionName, ActionDescription ...), in design time time package that is installed in the IDE. Then I have a base form with some default TXAction components with some default properties set like ActionDescription with a place holder i.e "Export [fn] to xls" where the "[fn]" will be replaced in design time with the Form Name. In the TXAction Loaded overridden method, I have this code: procedure TXAction.Loaded; var aIXRBaseForm : IXRBaseForm; begin inherited; if (csDesigning in ComponentState) and (Owner<>nil) then begin if Supports(Owner, IXRBaseForm, aIXRBaseForm) then begin if ActionCode = ('.' + IntToStr(ActionID)) then ActionCode := aIXRBaseForm.FormCode + ActionCode; if (AnsiPos('[fn]', ActionDescription) > 0) and (aIXRBaseForm.FormName <> '') then ActionDescription := StringReplace(ActionDescription, '[fn]', aIXRBaseForm.FormName, [rfReplaceAll]); end; end; end; The code above works as expected, I have several descendant forms that inherit from this base form, and when I open them in the IDE, these inherited TXActions instead of the placeholder "[fn]" in the description, they are replaced with the Form's name. My problem is that the Save All button in the IDE is not activated for the form to indicated there was a change, like it does when a property is changed in the object inspector, so that the user can save it and store these changes in the .dfm. Although, if the Save button which is always enabled is clicked, the changes are saved! This leads me to thinking if I'm indeed doing this right, is this the correct way to change properties in design time? How can I make the Save All button enabled? Thank you.
  3. kokoslolos

    Patch a private virtual method

    I always wanted to know how all these work in memory, if you have any readings or links to articles on the subject that you can suggest I would very much appreciate it, I'm very eager to dive in these topics and learn more. i.e. The instantiation of a class to an object, you say they share the same code but different data members, so when multiple threads are using different objects of the same class how does the OS handles it? Does it load a copy of the methods/instructions of the class in the CPU with the data members of an object? Or how are unit methods are thread safe when only accessing local variables, or how dll methods are loaded and also thread safe as long are accessing local variable. I don't know if it makes sense what I'm asking :)! I'll try to explain what I was asking at the end of the day, it's what the pseudo code is trying to achieve, having an A instance of TFoo method hooked and patched by another B instance's of TWrapper method, and when I call A.Method() it would actually call B.HackedMethod, but during my tests I realized that it isn't that simple and that's why I wrote my previous post asking for confirmation if what I realized was correct :). During my tests I did a patching this way, Patch(@TFoo.DoSomething, @TWrapper.HackedDoSomething) and during the call of A.Method(), it would execute without access violation even if I hadn't created an instance of TWrapper, and there is when I realized I was going the right direction and that I couldn't access the data members of the instances, for example the self pointer or FFoo of TWrapper. I finally managed to achieve this using the DDetours library, it's pretty amazing of what it can do :)! Hope what I wrote makes more sense now :).
  4. kokoslolos

    Patch a private virtual method

    Hi, I recently started learning and experimenting with method patching due to a crazy idea I had and wanted to implement in my framework, but I'm not sure I fully got how it works. I thought that by patching a class method, then any new instances of that class created would have a copy of the new patched method, but that's not the case, right? All new instances point to one single pointer and the information of the 'self' pointer is simply not accessible, correct? And that is why it doesn't matter whether the new method is a unit method or a class method. What I was trying to achieve, is to have a wrapper object around a third party class object and patch the wrapped object's method pointing to a wrapper's method. What I'm also wondering, is this even possible? And if yes, any of the ways discussed here us the solution or do I need the DDetour library, and if this library is able of such task? Just a simple example of what I would like to achieve, if it is possible though : TFoo = class protected procedure DoSomething;virtual; public procedure Something; end; TFooOpener = class(TFoo) end; TWrapper = class private FFoo : TFoo; public constructor Create(pFoo : TFoo); procedure HackedDoSomething; end; implementation constructor TWrapper.Create(pFoo : TFoo); begin FFoo := pFoo; end; procedure TWrapper.HackedDoSomething; begin TFooOpener(FFoo).DoSomething(); end; initialization Patch(@TFoo.DoSomething, @TWrapper.HackedDoSomething) ------------------------------------------------------------------ ... ... fFoo : TFoo; fWrapper : TWrapper; fFoo := TFoo.Create; fWrapper := TWrapper.Create(fFoo); ... // And when fFoo.Something then the HackedDoSomething would be called. fFoo.Something(); Thank you!
  5. I expect that more than two threads will enter "if", but only one will reset the FWriteIndex because of the "MAX_SIZE + aOverFlow" passed to InterlockedCompareExchange. The writer I believe works ok :). About the overflow, it's one of the checks I plan to add, even though I believe the single reader will always be fast enough to consume the items. Thank you for your time!
  6. I know for sure that it doesn't work for more than one readers, my implementation is specific for single reader and I plan to add checks to make sure only one thread reads. If you see GetItem(), I intentionally used Inc() and not Interlocked version knowing that only one reader will exist. Having that in mind, Primož Gabrijelčič, do you think it's a good start? Also thank you dummzeuch for your reply, will check your implementation.
  7. Hi all, For a system I'm currently designing and developing I have the need for a queue that N threads are going to add items and a single thread is going to consume them I have created a class and tested it, it works well in my opinion and I thought to share it here for your opinion as well. Maybe I missed something and it's not actually thread safe. The basic idea is a "ring" buffer and two indexes for read and write access. Also I took as granted that reading an integer is an atomic operation. Please keep in mind the code is draft and definitely needs polishing and more checks. And here it is: unit uMWSRList; interface uses Windows, Classes, SyncObjs, SysUtils; const MAX_SIZE = 32; type TMWSRList = class(TObject) private FWriteIndex : Integer; FReadIndex : Integer; FAvailableCount : Integer; FItems : Array [0..MAX_SIZE-1] of Integer; FOnNewItemAdd : TNotifyEvent; public constructor Create; function AddItem(pItem : Integer):Integer; function GetItem():Integer; function ItemsAvailable():Boolean; property OnNewItemAdd : TNotifyEvent read FOnNewItemAdd write FOnNewItemAdd; end; implementation { TMWSRList } constructor TMWSRList.Create; begin FWriteIndex := -1; FReadIndex := -1; end; function TMWSRList.AddItem(pItem : Integer):Integer; var aOverFlow : Integer; begin Result := InterlockedIncrement(FWriteIndex); if Result >= MAX_SIZE then begin aOverFlow := Result - MAX_SIZE; { Reset FWriteIndex when it reaches MAX_SIZE } InterlockedCompareExchange(FWriteIndex, -1, MAX_SIZE + aOverFlow); Result := InterlockedIncrement(FWriteIndex); end; FItems[Result] := pItem; InterlockedIncrement(FAvailableCount); if Assigned(FOnNewItemAdd) then FOnNewItemAdd(self); end; function TMWSRList.GetItem():Integer; begin if FAvailableCount > 0 then begin Inc(FReadIndex); if FReadIndex = MAX_SIZE then FReadIndex := 0; Result := FItems[FReadIndex]; InterlockedDecrement(FAvailableCount); end else Result := -1; end; function TMWSRList.ItemsAvailable():Boolean; begin Result := FAvailableCount > 0; end; end. Regards.
×