kokoslolos
Members-
Content Count
5 -
Joined
-
Last visited
Community Reputation
1 NeutralRecent Profile Visitors
The recent visitors block is disabled and is not being shown to other users.
-
Patch a private virtual method
kokoslolos replied to pyscripter's topic in RTL and Delphi Object Pascal
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 :). -
Patch a private virtual method
kokoslolos replied to pyscripter's topic in RTL and Delphi Object Pascal
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! -
Lockfree approach on a Single reader, Multiple Writer queue
kokoslolos replied to kokoslolos's topic in Algorithms, Data Structures and Class Design
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! -
Lockfree approach on a Single reader, Multiple Writer queue
kokoslolos replied to kokoslolos's topic in Algorithms, Data Structures and Class Design
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. -
Lockfree approach on a Single reader, Multiple Writer queue
kokoslolos posted a topic in Algorithms, Data Structures and Class Design
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.