Jump to content

Search the Community

Showing results for 'TMultiReadExclusiveWriteSynchronizer'.


Didn't find what you were looking for? Try searching for:


More search options

  • Search By Tags

    Type tags separated by commas.
  • Search By Author

Content Type


Forums

  • Delphi Questions and Answers
    • Algorithms, Data Structures and Class Design
    • VCL
    • FMX
    • RTL and Delphi Object Pascal
    • Databases
    • Network, Cloud and Web
    • Windows API
    • Cross-platform
    • Delphi IDE and APIs
    • General Help
    • Delphi Third-Party
  • C++Builder Questions and Answers
    • General Help
  • General Discussions
    • Embarcadero Lounge
    • Tips / Blogs / Tutorials / Videos
    • Job Opportunities / Coder for Hire
    • I made this
  • Software Development
    • Project Planning and -Management
    • Software Testing and Quality Assurance
  • Community
    • Community Management

Find results in...

Find results that contain...


Date Created

  • Start

    End


Last Updated

  • Start

    End


Filter by number of...

Joined

  • Start

    End


Group


Delphi-Version

Found 18 results

  1. Anders Melander

    Threadvar "per object"

    The suitability of TMultiReadExclusiveWriteSynchronizer depends on how you use it and what your needs are and only you know the answer to that. There's a more lightweight and faster alternative available in the RTL of recent Delphi versions. Google, or the help, will find the name for you. TMultiReadExclusiveWriteSynchronizer got broken when Danny Thorpe rewrote it for D6. I believe it was fixed in D7. Before the rewrite it supported lock promotion which opened up for deadlocks in some usage patterns - not because it was buggy but because people didn't know what they were doing.
  2. Anders Melander

    Threadvar "per object"

    Search broken again? https://en.delphipraxis.net/search/?q=TMultiReadExclusiveWriteSynchronizer https://www.google.com/search?q=TMultiReadExclusiveWriteSynchronizer
  3. JonRobertson

    Threadvar "per object"

    Does anyone use TMultiReadExclusiveWriteSynchronizer? The application team I was on 20 years ago had some problems with it in D6. But I see that the VCL still uses it for GlobalNameSpace (for Windows anyway).
  4. I've found only one difference here and this could not be an issue for MacOS: {$IFDEF ANDROID} {$MESSAGE 'TODO processmessage loop'} Result := False; // Error { V9.1 } {$ENDIF ANDROID} But I've checked the reason for the blocker in function TMultiReadExclusiveWriteSynchronizer.BeginWrite: Boolean; is the line as here it's not coming back: WaitForWriteSignal; P.S.: TIcsMessagePump.ProcessMessage is not reached under MacOS, if this could be an issue here. P.P.S.: I assume it's an initialisation issue if such a central functionality as WaitForWriteSignal is not working and processMessage is not requested at all. But I don't know what to test further.
  5. Hi , I have downloaded the delphimvcframework and it look’s great 🙂 thanks to @Daniele Teti , I have also bought the book 🙂 great reading, recommended. I love this system , but will play more with it next couple of weeks. A small question. We have a small webbroker app today running on Apache AWS, we use a globale Dict as a keystore in all requests, and we use FMX data pooling. FMX data pooling seems to be well documented in your book, and I guess I can almost use like before. If you look at below code we use dict String_Dict as a global variable handled by TMultiReadExclusiveWriteSynchronizer, any suggestion where to put his variable in delphimvcframework to be able to use it in the different controller / actions like FMVC.AddController(TCustomersController); In our webmodule we have a global variable and we use it with TMultiReadExclusiveWriteSynchronizer from system.sysutil Example data from from our Webmodule … public { Public declarations } SettingTemplateClass : TSettingTemplateClass; end: var WebModuleClass: TComponentClass = TWebModule1; String_Dict : TDictionary<string,String > ; string_Dict_Sync : TMultiReadExclusiveWriteSynchronizer; ….. // connecting String_Dict to a setting class unique for each request procedure TWebModule1.WebModuleCreate(Sender: TObject); begin SettingTemplateClass := TSettingTemplateClass.Create SettingTemplateClass.string_Dict_Sync := string_Dict_Sync; SettingTemplateClass.String_Dict := String_Dict; …. end; // a typical request sending string_dict further using settingTemplateClass to the class generating the response via usersession class procedure TWebModule1.WebModule1getlogondataAction(Sender: TObject; Request: TWebRequest; Response: TWebResponse; var Handled: Boolean); var userSession : TuserSession; ssoInternalClass : TssoInternalClass; companyid : Integer; lsession_data : String; begin companyid := strtointdef( getRequestParamValue (Request , 'companyid' ),0); userSession := TuserSession.create(SettingTemplateClass,getRequestParamValue(request,'token')); try if isSessionValid(Response,userSession) then begin lsession_data :=getRequestParamValue (Request , 'session_data' ); userSession.userSessionData.setSessionData(lsession_data); ssoInternalClass := TssoInternalClass.Create(userSession); try Response.content := ssoInternalClass.getLogonData( companyid ); finally ssoInternalClass.Free; end; end; finally userSession.Free; end; end; ………… initialization String_Dict := TDictionary<string,String >.create ; string_Dict_Sync := TMultiReadExclusiveWriteSynchronizer.Create; finalization String_Dict.Free; string_Dict_Sync.Free; Example using string_dict in class generating the response data below . string_Dict_Sync.BeginRead; try string_Dict.TryGetValue('severDayNumberString', severDayNumberString ); finally string_Dict_Sync.EndRead; end; It it possible o do something similar with delphimvcframework, ? For me it seems like difficult to share data to a controller .. Thanks in advance
  6. borni69

    delphimvcframework global variable

    This is my result from test.. and it seems to work.. unit HseqDmDictU; interface uses System.SysUtils, System.Classes, Generics.collections; type TDataModuleDict = class(TDataModule) private FString_Dict: TDictionary<string, String>; Fstring_Dict_Sync: TMultiReadExclusiveWriteSynchronizer; procedure SetString_Dict(const Value: TDictionary<string, String>); procedure Setstring_Dict_Sync( const Value: TMultiReadExclusiveWriteSynchronizer); { Private declarations } public { Public declarations } destructor Destroy; override; procedure initDict; property String_Dict : TDictionary<string,String > read FString_Dict write SetString_Dict; property string_Dict_Sync : TMultiReadExclusiveWriteSynchronizer read Fstring_Dict_Sync write Setstring_Dict_Sync; end; var DataModuleDict: TDataModuleDict; implementation {%CLASSGROUP 'System.Classes.TPersistent'} {$R *.dfm} { TDataModuleDict } procedure TDataModuleDict.initDict; begin FString_Dict := TDictionary<string,String >.create ; Fstring_Dict_Sync := TMultiReadExclusiveWriteSynchronizer.Create; end; destructor TDataModuleDict.Destroy; begin FString_Dict.Free; Fstring_Dict_Sync.Free; inherited; end; procedure TDataModuleDict.SetString_Dict( const Value: TDictionary<string, String>); begin FString_Dict := Value; end; procedure TDataModuleDict.Setstring_Dict_Sync( const Value: TMultiReadExclusiveWriteSynchronizer); begin Fstring_Dict_Sync := Value; end; end. On my console app startup init the Datamodule (not sure for Linux where I will put it, but will try later) begin ReportMemoryLeaksOnShutdown := True; IsMultiThread := True; // Prepare Dict DataModuleDict:= TDataModuleDict.Create(nil); try DataModuleDict.initDict; // Important try if WebRequestHandler <> nil then WebRequestHandler.WebModuleClass := WebModuleClass; WebRequestHandlerProc.MaxConnections := 1024; RunServer(8080); except on E: Exception do Writeln(E.ClassName, ': ', E.Message); end; finally DataModuleDict.Free; end; end. Using dict in code from seperate unit unit DictU; interface uses system.sysutils , system.classes ,DataConU, Generics.collections , TemplateRecordU; type TDictClassV2 = Class ( Tobject ) private public procedure saveString ( akey , avalue : String ) ; function loadString ( akey : String ) :String; End; implementation uses HseqDmDictU; { TDictClassV2 } function TDictClassV2.loadString(akey: String): String; begin result:=''; DataModuleDict.string_Dict_Sync.BeginRead; try DataModuleDict.string_Dict.TryGetValue(akey,result); finally DataModuleDict.string_Dict_Sync.EndRead; end; end; procedure TDictClassV2.saveString(akey, avalue: String); begin DataModuleDict.string_Dict_Sync.BeginWrite; try try if not DataModuleDict.String_Dict.ContainsKey(akey) then DataModuleDict.String_Dict.Add(akey,avalue); Except on E : Exception do begin // logg error end; end; finally DataModuleDict.string_Dict_Sync.EndWrite; end; end; end. If you would do it differently please let me know Thanks again...
  7. Alberto Fornés

    delphimvcframework global variable

    No , this datamodule should be created at start, and always alive, you reference it from your controller (add datamodule unit to controller), and access it through TMultiReadExclusiveWriteSynchronizer.
  8. Thanks for the Idea, and we are considering this. But we have some consideration. Our Delphi app is an API server , ISAPI webbroker module running on Apache linux docker several container instances behind a load balancer. We can share a dictionary between the threads using DataSync := TMultiReadExclusiveWriteSynchronizer.Create; We use MPM_event on apache with this setup per production server <IfDefine TSprod> ServerLimit 8 MaxRequestWorkers 200 ThreadsPerChild 25 </IfDefine> And for setup above this will give 8 dictionary per server holding almost the same information, and 25 threads will share same dictionary this will be super fast but consume more memory than memcache. We could consider reducing ServerLimit and increase ThreadsPerChild for this setup to not use so much memory per server this will increase threads using same dict. We will test a little more on this. B
  9. Hi there, I'm playing around with the new TLightweightMREW, and it seems to be a custom record now. There were already some important improvements from @Primož Gabrijelčič available. In comparison to TMultiReadExclusiveWriteSynchronizer, which is a class, I ask myself if this new TLightweightMREW is intended to be used as a field over a classes lifetime. Like type TMyClass = class private FLock : TLightweightMREW; ... ... procedure DoSomeLocking; procedure DoSomeMoreLocking; procedure DoSomeLockingStart; procedure DoSomeLockingStop; ... constructor Create; destructor Destroy; override; ... end; implementation ... constructor TMyClass.Create; begin inherited; //FLock as custom record needs no special initialization ! end; procedure TMyClass.DoSomeLocking; begin FLock.BeginRead; ... FLock.EndRead; end; procedure TMyClass.DoSomeMoreLocking; begin FLock.BeginWrite; ... FLock.EndWrite; end; procedure TMyClass.DoSomeLockingStart; begin FLock.BeginWrite; ... end; procedure TMyClass.DoSomeLockingStop; begin FLock.EndWrite; end; constructor TMyClass.Destroy; begin inherited; // !! There is no way to find our if a locking is currently is running // FLock maybe destroyed when class is destroyed, the all locking released ? end; Is this kind of "class global" field, inside a class, intended to be used like that ? If so, how to manage possible hanging "locks", when the whole class is destroyed before locks were released ? Maybe its somehow guaranteed by design that FLock is releasing all locks, when the class is destroyed, but I would doubt that. So that means, I would have to put my own "lock accounting" around this TLightweightMREW field, is that correct ? Maybe this kind of use-case is not the right for the TLightweightMREW, and it better should be used only "locally" within a method ?
  10. Rollo62

    TLightweightMREW considerations

    My goal was to ensure that no pending internal lock are open. Unfortunately there is no "ReadLockCount" or "WriteLockCount" to check that. I was considering a kind of "Flush" for all open locks, I thought the TMultiReadExclusiveWriteSynchronizer is doing something like that destructor TMultiReadExclusiveWriteSynchronizer.Destroy; begin BeginWrite; inherited Destroy; CloseHandle(FReadSignal); CloseHandle(FWriteSignal); tls.Free; end; Is calling BeginWrite maybe recommended to assure issues with open locks ? Of course it would create a lock, instead of closing. The TLightweightMREW has Initialize, but no according Finalize. class operator Initialize And even if so, would the Finalize be reliable called on class destruction, never checked that with CustomManagedRecords ( I hope it would ) ? I used to track locks with each successful TryBeginRead/EndRead, if needed, inside the class, by accounting with TInterlocked counters. But wouldn't it be better if the locking class/record itself would have offered its internal accounting. Probably there is something wrong with accounting of locks at all ( I know after the moment I've got a count, its all can be changed ) ? For just waiting until all is cleaned up before class destruction, or at least for preparing a clear error message "Hanging lock".
  11. Hi Again and thanks.. I have never used TMultiReadExclusiveWriteSynchronizer , but it looks straight forward. I created a test app and it seems to work, so I guess it is as simple as code below. except I will use a Dictionary. unit WebModuleUnit1; interface uses System.SysUtils, System.Classes, Web.HTTPApp; type TWebModule1 = class(TWebModule) procedure WebModule1DefaultHandlerAction(Sender: TObject; Request: TWebRequest; Response: TWebResponse; var Handled: Boolean); private { Private declarations } public { Public declarations } end; var WebModuleClass: TComponentClass = TWebModule1; Data: TStringList; DataSync: TMultiReadExclusiveWriteSynchronizer; implementation {%CLASSGROUP 'System.Classes.TPersistent'} {$R *.dfm} procedure TWebModule1.WebModule1DefaultHandlerAction(Sender: TObject; Request: TWebRequest; Response: TWebResponse; var Handled: Boolean); var i : Integer; begin if Request.QueryFields.Values['add'] > '' then begin // Add line DataSync.BeginWrite; try Data.Add ( Request.QueryFields.Values['add']); finally DataSync.EndWrite; end; end; Response.Content := '<html>' + '<head><title>Web Server Application</title></head>' + '<body>'; DataSync.BeginRead; try for I := 0 to data.Count-1 do begin Response.Content := Response.Content+data[i]+'</br>' end; finally DataSync.EndRead; end; Response.Content := Response.Content+' </body>' + '</html>'; end; initialization // test:='Test'; Data := TStringList.Create; DataSync := TMultiReadExclusiveWriteSynchronizer.Create; finalization Data.Clear; Data.Free; DataSync.Free; end. end. thanks
  12. For example a TMultiReadExclusiveWriteSynchronizer.
  13. Marco's announcement on the new blogs site: https://blogs.embarcadero.com/rad-studio-10-4-1-has-been-released/ Updated my wiki page with info on 10.4.1: https://github.com/ideasawakened/DelphiKB/wiki/D27.SYDNEY.10.4.1.0 RAD Studio 10.4.1 has a strong focus on quality improvements. Key quality focus areas include: IDE Delphi Code Insight (LSP) Parallel Library SOAP & XML C++ Toolchain FireMonkey VCL Delphi Compiler iOS Deployment New Features Packages can now have an automatic version suffix (instead of manually updating and specifying the right version suffix with each new release) New reader-write lock implementation via the new TLightweightMREW record Faster and more lightweight than the TMultiReadExclusiveWriteSynchronizer (TMREW) Works across all platforms (TMEW was a simple critical section on some) Much improved support for multi-monitor desktop layouts and 4k monitors The floating form designer has been removed The Broadcast to devices option is now off by default Platform Support Deployment to Windows Server 2019 now supported The LSP based Code Insight much improved from its initial 10.4 release
  14. I've had a go at stepping through code from my app. It's a bit tricky because the units such as Ics.Fmx.OverbyteIcsWndControl contain no actual code, just an include {$I OverbyteIcsWndControl.pas}, which the Debugger isn't pulling in, so I don't get to see the lines of code I Trace Into or Step Over in the IDE. It is stepping though, because the call stack changes when I press F7, and I occasionally step into the System unit. Shortly before the hang, the call stack looks like this : Ics.Fmx.Overbyteicshttpprot.THttpCli.SetTerminated(bool)(0x0000000203a33170,false) Ics.Fmx.Overbyteicswndcontrol.TIcsWndControl.TIcsWndControl(System.Classes.TComponent*)(0x0000000203a33170,false,0x000000020bd3b640) Ics.Fmx.Overbyteicshttpprot.THttpCli.THttpCli(System.Classes.TComponent*)(0x0000000203a33170,true,0x000000020bd3b640) And the hang occurs after/when the System unit executes : constructor TObject.Create; begin end; Oh, here we go - this looks more useful : :00007FFF6E68AE36 semaphore_wait_trap :00007FFF6E4F0AED _dispatch_sema4_wait :00007FFF6E4F0FBF _dispatch_semaphore_wait_slow System.Syncobjs.TEvent.WaitNoReset(unsigned int)(0x0000000205815ff0,4294967295) System.Syncobjs.TEvent.WaitFor(unsigned int)(0x0000000205815ff0,4294967295) Ics.Posix.Messages.TMultiReadExclusiveWriteSynchronizer.WaitForWriteSignal()(0x0000000105809620) Ics.Posix.Messages.TMultiReadExclusiveWriteSynchronizer.BeginWrite()(0x0000000105809620) Ics.Posix.Messages.TIcsMessagePump.AfterConstruction()(0x000000020beeb1b0) System._AfterConstruction(System.TObject*)(0x000000010bed9a40) System.TObject.TObject()(0x000000010bed9a40,true) Ics.Fmx.Overbyteicswndcontrol.TIcsWndControl.AllocateHWnd()(0x0000000203a33170) Ics.Fmx.Overbyteicshttpprot.THttpCli.THttpCli(System.Classes.TComponent*)(0x0000000203a33170,true,0x000000020bd3b640) So the app hangs at semaphore_wait_trap. Not sure what that is yet, but there is a Thread #7 labelled : TIcsAsyncSocketThread (7) with the following Call Stack kevent Ics.Fmx.Overbyteicswsocket.TIcsEventQueue.HandleEvents() Ics.Fmx.Overbyteicswsocket.TIcsAsyncSocketThread.Execute() System.Classes.ThreadProc(System.Classes.TThread*) System.ThreadWrapper(void*) _pthread_start thread_start Could Thread #1 be waiting for Thread #7 to complete or sync? Other threads do exist (4, 10, 14, 19) but are all unlabelled.
  15. Angus Robertson

    Invalid Compiler Directive: 'MESSAGES'

    Thanks for joining this thread and helping to get ICS working on MacOs64. I've updated Ics.Posix.KEventTypes,pas with your fixes, but am wondering whether I should also be changing WSocket to use EV_SET64 and TKEvent64 instead of EV_SET in TIcsEventQueue? Or does MacOS64 support both. Not in SVN yet. I don't believe there is much point in trying to retain MacOS32 compatibility going since 10.4 no longer supports it. Regarding your off-list comment about TMultiReadExclusiveWriteSynchronizer and ThreadID, I did change this to ThreadID: TThreadID; last week to match all other instances. Please be aware I can now build for Linux64 but not for MacOS since don't have any Apple hardware, so I can catch general Posix compiler issues, but not Mac only issues. And the Linux message handler is not done yet. Angus
  16. I think FMX renders its UI to a surface/canvas, rather than having the OS render the controls (?) - so yes, it could be different. This is where the IcsHttpsTst seems to get stuck at startup: Line 1962 of Ics.Posix.Messages function TMultiReadExclusiveWriteSynchronizer.BeginWrite: Boolean; var Thread: PThreadInfo; HasReadLock: Boolean; ThreadID: Cardinal; Test: Integer; OldRevisionLevel: Cardinal; begin ... ThreadID := GetCurrentThreadID; The top of the call stack looks like this : :000000010001D0F0 System::_DbgExcNotify(int, void*, System::SmallString<(unsigned char)255>*, void*, void*) :000000010001D12E System::NotifyReRaise(System::TObject*, void*) :000000010001D1CA System::_RaiseAtExcept(System::TObject*, void*) :0000000100056AB8 System::Sysutils::ErrorHandler(unsigned char, void*) :0000000100015F30 System::ErrorAt(unsigned char, void*) :000000010001B252 System::_BoundErr() Ics.Posix.Messages.TMultiReadExclusiveWriteSynchronizer.BeginWrite()(0x0000000102521120) Ics.Posix.Messages.TIcsMessagePump.AfterConstruction()(0x000000020245bd80) :0000000100016B45 System::_AfterConstruction(System::TObject*) :0000000100011443 System::TObject::TObject() Ics.Fmx.Overbyteicswndcontrol.TIcsWndControl.AllocateHWnd()(0x0000000203080ff0) Ics.Fmx.Overbyteicshttpprot.THttpCli.THttpCli(System.Classes.TComponent*)(0x0000000203080ff0,true,0x000000020801e5f0) ... Maybe that contains useful information. On Posix, the System unit defines: TThreadID = NativeUInt; But local var ThreadID is Cardinal. Maybe Cardinal and NativeUInt are not compatible. If I redefine ThreadID as a NativeUInt too, then the ERangeError disappears, and the app is "[Running]" - but the UI does not appear. I think Thread #1 might be waiting for something.
  17. dummzeuch

    Using dxgettext on Windows 10

    As a test whether a bug in TMultiReadExclusiveWriteSynchronizer is to be blamed, I have just replaced it with the TMultiReadSingleWrite class from DWScript. Here is the code: https://download.dummzeuch.de/twm/gnugettext-pas-with-TMultiReadSingleWrite.zip Could you please download and try it? It's only active if the symbol dx_UseDWSMultiReadSigleWrite is defined (which I have done in the code linked above). If we believe Eric Grange (which I tend to do), it is also much faster, but that was with the implementation from 2013, so might no longer be true. Also, it is not reentrant. I have not checked whether that might be a problem with dxgettext.
  18. dummzeuch

    Using dxgettext on Windows 10

    RefCount should always be 0 if the class is not assigned to an interface variable, which it isn't. So that change basically means: if true then begin Result := MsgId; Exit; end; So, that's not a solution to the actual problem. Did you try to set a breakpoint in the finalization section and single step through it to find the position where it hangs? (Or maybe see that it doesn't hang there but somewhere else?) I looked at the code and can't find anything wrong with it. It does use various instances of TMultiReadExclusiveWriteSynchronizer which, if I remember correctly, was broken in several RTL versions. So using that class might not have been the best decision. But on the other hand, my memory might fail me and anyway those bugs should have been fixed long ago. Which Delphi version are we talking about? 10.1, as your profile suggests?
×