Jump to content

Dalija Prasnikar

Members
  • Content Count

    1049
  • Joined

  • Last visited

  • Days Won

    91

Everything posted by Dalija Prasnikar

  1. Dalija Prasnikar

    Alexandria 11.3 and Android 13 (part 2)

    This version number is not SDK version it is tools version. SDK version for supporting Android API levels is set in SDK panel in Options dialog under "SDK API level location". You can find which SDK platforms you have installed in SDK\platforms folder. Fro API 33 there should be android-33 folder inside. Also Java interfaces don't change with each API version and they are pretty stable, so they don't need to be constantly updated. Occasionally, when new API has some additional features or some interfaces are changed Delphi Java interfaces will be changed accordingly. When Embarcadero says they support some API level, that means they actually do support that API level.
  2. Dalija Prasnikar

    Alexandria 11.3 and Android 13 (part 2)

    I am using SDK from Android Studio, so I cannot comment on whether SDK 33 is installed with 11.3. You can use Android Studio to update the SDK, but you can also use avdmanager.bat and sdkmanager.bat tools in the <ANDROID-SDK-FOLDER-PATH>\cmdline-tools\bin folder. I am assuming that your referral of missing SDK Manager was about SDKManager.exe that was previously available. See: https://quality.embarcadero.com/browse/RSP-34730 This change is because support for new Android versions required newer Android tools version which no longer ships with SDKManager.exe because Google integrated all those within Android Studio and removed standalone version. See: https://issuetracker.google.com/issues/197818591?pli=1
  3. Dalija Prasnikar

    Async/Await with updating visual controls

    TThread.Synchronize and TThread.Queue are parts of core RTL functionality. You can use them and they are appropriate way to synchronize any Delphi code with main thread, regardless of what other libraries you are using. BTW, following line also needs to be synchronized with main thread. memo1.append(datetimetostr(now)+': Start Processing');
  4. Dalija Prasnikar

    Stack Overflow error

    Interesting. That would be my last option. I wonder what caused it. When you installed the update, did you reinstall your 3rd party components, too?
  5. Dalija Prasnikar

    Stack Overflow error

    Do you use any 3rd party controls on that form? Maybe something changed that causes issue in particular component. You can try adding those to your blank project one by one, or try removing them from that unit and fmx file with some other editor. Or maybe even some IDE plugin that is additionally installed could cause the problems. It is very unlikely that something is wrong with your installation. It is not completely impossible scenario, but I don't think it will help.
  6. Dalija Prasnikar

    Stack Overflow error

    I guess that only thing left for you is to report a bug to Embarcadero, if you can create small test case from your project that will show same behavior. One way to create a test case would be by copying your dpr and dproj files in another folder and opening that. If that crashes you can add that to the report. If it does not crash, then the problem you are having is in some other file. You can try locating it by copying other files from the project in small groups. Besides that the only other option would be to create new FMX application and add your files to it. I don't have other ideas.
  7. Dalija Prasnikar

    Stack Overflow error

    Opening dpr file works only if you have deleted dproj file. Another thig just occurred to me. Have you tried deleting project dsk file, which holds opened IDE files, IDE layout, breakpoints and watches. Maybe something is wrong there and not in your dproj file. What is exact error you get?
  8. Dalija Prasnikar

    Delphi 11.1 with TidThreadComponent and TThread.Synchronize

    This can also be easily solved if you either disable timer while you are updating UI and enable it back when you are finished. Alternative solution is adding some boolean flag and simply skipping UI update if previous update is still running.
  9. Dalija Prasnikar

    Stack Overflow error

    You get this error because you are trying to open project from recent files which links directly to .dproj file. If you open it through File -> Open and open .dpr then dproj will be recreated. Anyway, deleting dproj file, while it can help in certain scenarios is not the best course of action, especially for cross-platform FMX projects as you will lose all custom setup required for those projects, but that depends on how complicated your setup is. If your dproj file is corrupted in some way and it cannot be loaded, then creating brand new project with same name and configuring it from scratch, is better option as autogenerating can cause you other troubles down the road because auto-generation does not properly configure and add all platforms.
  10. Dalija Prasnikar

    Help needed - ANR on Android app UI refresh

    RTTI had (and possibly still has) issues with thread safety when acquiring and releasing pool token. Unless you are using Windows application with dynamically loaded packages, the best option to avoid those issues is to call TRttiContext.KeepContext; in initialization section of some base unit and TRttiContext.DropContext; in finalization section. This will create pool token and keep it alive during lifetime of you application, avoiding thread safety issues, and it will also speed up RTTI operations.
  11. Dalija Prasnikar

    Creating FMX controls in a background thread

    This is not possible because constructing forms and controls also interacts with the OS in thread-unsafe way. For instance creating window has thread affinity and window belongs to a thread that creates it. You cannot construct window in one thread and pass it to another. If you remove initialization code that interacts with OS and other thread-unsafe parts, controls would need to have separate initialization that would need to be synchronized with the main thread. This would be rather messy as different controls have different requirements and construction of controls would get additional layer of complexity which would also only slow things down. Forms streaming also uses global lock mechanism to protect global namespace (data modules can be constructed and streamed in background depending on used components), so adding synchronization during loading forms would also open potential for deadlocking, and preventing the deadlocks would also require additional calls and checks which would again slow everything down. This never worked in VCL and it does not work in FMX. Threading issues can be hard to catch. Just because you can create some components in background thread without immediately bumping into issues does not mean such code is bug free.
  12. Dalija Prasnikar

    Creating FMX controls in a background thread

    From OS perspective bitmap operations can be performed in background threads and then bitmap could be transferred to UI for painting. This is where FMX has some issues that could and should be fixed. Same goes for working with 3D graphics primitives.
  13. Dalija Prasnikar

    Creating FMX controls in a background thread

    In theory when writing and GUI framework from scratch, it could be possible to make that framework thread-safe. But drawing is not the only part that needs to run in the main thread. Any interaction with the OS - creating OS handles (like windows, graphic objects...), mouse interaction, keyboard interaction, OS notifications, needs to run in the main thread. too. Also access to all resources would have to be protected by locks. That means every single field and property inside control. So while background threads would be running doing some work on those controls, UI thread would not be able to use them. Now it may look that this would still be solution if you want to just create and destroy controls in background threads, but again to do that safely ALL access ALL the time have to run through locks, That means even if you never use background threads, accessing and working with UI controls would be much slower ALL the time. Multithreading is not cost free. I don't know what is your intent behind the question. Again, the fact that FMX is not thread-safe is not a flaw in its design, or anything similar. It is because thread-safe UI frameworks are basically non existent (I am saying basically, because like I said in theory they are possible, but I don't know about any). All major OS-es have thread-unsafe UI frameworks: Windows, Linux, Android, iOS, macOS - simply because making those thread-safe does not make sense. Thread safety is not just about throwing locks around some lists, but also defining what interactions need to logically happen without any interruptions from other threads. That would mean locking would have to extend to much broader code besides just accessing lists, and the more complex the scenarios (and UI are extremely complex frameworks with complex code paths) the more chances are that there will be bugs and concurrency issues that cannot be easily resolved. Patching FMX to add thread-safety is impossible as it is not just adding few locks here and there, it would have to be thorough rewrite. If you want to write your own framework, you are always free to do so, but I would have to ask "You and what army?"
  14. Dalija Prasnikar

    Creating FMX controls in a background thread

    Plenty. User interfaces in general (not just Delphi) are not thread-safe. Thread safety comes with hefty price. You would have to lock just about everything and it would significantly slow down the UI. Also, UI controls are complex and have plenty of interactions. Due to that complexity, making UI thread-safe would be complicated and error-prone. Not only that, but UI needs to interact with OS layer where UI controls are also not thread-safe as such where you cannot access the same control from different threads. That means if you would construct one control in background thread to be used in main thread afterward, not only you would have to make sure that interaction with Delphi UI side of controls have to be thread-safe, but control would have to avoid triggering any code that interacts with OS part which is almost impossible. UI is not thread-safe by design and that is something that will not change as it is not practical nor beneficial. There are some parts around handling images that could be fixed to fully support processing images in background threads and then passing them to the UI for presentation.
  15. It takes 10 minutes to create such generator. I have few that generate boring code based on my coding patterns. I just need to write field declaration, copy-paste that to generator and I get all property declarations and assign method out of it. Yes, I need to adjust some of them afterwards, depending on their type, but that is only because my generator is extremely dumb parser and I never bothered to improve it as I don't need it that often. I mean, if you find AI useful for some tasks, then by all means use it. But it is not a magical tool, and it has serious limitations. If you are aware of those, then you can get the most of it, but don't expect any intelligent solutions out of it.
  16. Dalija Prasnikar

    Nested TParallel.For: Immediate deadlock

    The problem happens when outer For loop consumes all available threads and hits maximum where no new threads are being allocated for newly requested task. And then if inner tasks cannot get free thread to run, they cannot complete their job. I have test case that will break more easily as number of needed threads is higher, and sleep also increases the time inner thread runs and gives more time for outer for loop to consume all available threads. Using separate pool for inner for loop solves the problem. This can still be an issue if you have code that indirectly uses nested parallel loops. begin var counter := 0; var pool := TThreadPool.Create; const COUNT = TThreadPool.Default.MaxWorkerThreads * 4; TParallel.For( 0, Pred(count), procedure(i: Int64) begin TParallel.For( 0, Pred(count), procedure(i: Int64) begin TInterlocked.Increment(counter); Sleep(10); end , pool); end ); Writeln(counter); Readln; end. Probably the best solution for parallel for loops that can spawn too many tasks would be to create dedicated thread pool for each loop. The cost of creating a thread pool is not big when dealing with longer running tasks. And for fast running tasks, like in this example, parallel loop is overkill anyway as it can run slower than simple for loop in single task.
  17. Dalija Prasnikar

    try... finally on Mac

    Inline behaves as if you have written the code directly within the try..except method. Just like double nesting does not help with the inlined procedure it will not help with any other code that is written directly in try..except block. Only wrapping the code that can cause exception in additional function, procedure or method is the solution.
  18. Dalija Prasnikar

    try... finally on Mac

    If the G! is inlined then exception will not be caught by second level try..except block. It can only be caunght by exception handler outside the method where exception happens. var P: ^Integer = nil; procedure G1; inline; begin P^ := 42; end; procedure TForm1.G2; begin try try G1; except Memo1.Lines.Add('Inner'); end; except Memo1.Lines.Add('Outer'); end; end; procedure TForm1.Button1Click(Sender: TObject); begin try G2; except Memo1.Lines.Add('Proc'); end; end; In other words, in above code exception will be caught by exception handler around G2 -> Proc If we remove inline directive then exception will be caught by Inner exception handler. I don't know whether LLVM can automatically inline functions that are not explicitly marked for inlining, but I would expect that we shouldn't worry about that as this would break exception handling not only for Delphi, but for other languages, too.
  19. Dalija Prasnikar

    try... finally on Mac

    Don't worry, it was evident that this was just an example to show the failure. Obviously in real code one would not set object to nil and then use if Assigned() to check whether object is nil before using it. But if you have scenario where some function call can return nil object as valid response - for instance finding object that satisfies condition in a collection, and returns nil if the appropriate object is not found, then you have to check for nil before using it. Once you have valid object, calling methods on it, even if they raise exceptions will be caught by surrounding exception handler. Again, in such cases you will be calling some library function, and unless you are calling something on nil object this will be fine. The potential issues may arise if the library itself (Delphi ones) is not written with LLVM based compilers in mind, where some exceptions will won't be caught by appropriate exception handlers within the library code. If that happens then the library code has to be fixed, you cannot solve the problem from your code.
  20. Dalija Prasnikar

    try... finally on Mac

    This issue happens on all LLVM backed compilers because LLVM is not capable of catching hardware exceptions unless exception happens within another function. You find more information on my blog post https://dalijap.blogspot.com/2018/10/catch-me-if-you-can.html I never got around to write the sequel, but the implications is that literally anything that all exception handling implicit or explicit is broken in such situations. The solution is that you either wrap your code in separate function that will not have any exception handling within, and then the caller will be able to catch and handle raised exceptions. Another way of solving issues is to avoid code that can trigger such hardware exception and raise Delphi exception if code does not satisfy some requirement as explained in https://docwiki.embarcadero.com/RADStudio/en/Migrating_Delphi_Code_to_Mobile_from_Desktop#Use_a_Function_Call_in_a_try-except_Block_to_Prevent_Uncaught_Hardware_Exceptions So in the context of your example, you should either check whether object is nil before trying to use it (this would actually be general advice, as accessing nil object, depending on the code, on Windows does not guarantee that you will get AV). Note. I don't know what exactly following quote from documentation about macOS means: "structured exception handling (__try/__except) is not available". Linked page talks about hardware exceptions, but I am not sure whether there are some other implications here besides what I said in context of LLVM. At the moment I don't have my development environment set up in a way that would allow me to verify behavior on Mac. While bugs are always possibility, RTL appropriately handles hardware exceptions in cross-platform code. I removed wrong duplicates and added appropriate one.
  21. Dalija Prasnikar

    How to free object compiled to Linux

    On Windows Delphi uses FASTMM memory manager and on Other platforms it uses POSIX memory manager. I am not that familiar with inner workings of a POSIX memory manager, but FASTMM allocates larger chunks of memory from the OS which is then used for sub-allocating object instances and other heap based data. When you release an object, data in its memory location can be still intact and accessing such data does not always crash. In such cases memory is held by FASTMM so there will be no crash in the OS side because for the OS it is valid memory allocated by the program. If you use FASTMM in full debug mode during the development, then accessing such invalid object will be noticed by FASTMM and shown as error.
  22. Dalija Prasnikar

    How to free object compiled to Linux

    I cannot verify the issue at the moment, but since TJsonTextReader uses TStringReader it might be better to reverse the releasing order. It is likely that TJsonTextReader destructor is accessing the TStringReader instance during destruction process. Such code would also be wrong on Windows, but you are just lucky that it does not fail there. LJsonTextReader.Free; LStringReader.Free;
  23. Dalija Prasnikar

    Need inline InterfacedObjects to be freed?

    Compiler cannot give you appropriate hint at that place. The problem is that it doesn't know whether you need to use interface reference or not because some classes that have interfaces have reference counting disabled and are used through object references. If compiler would give a hint that would result in many false positives and at the end such hints would be useless. This is similar situation as the one where developer declares regular variable, but uses wrong type. There are no hints for such scenarios either.
  24. Dalija Prasnikar

    Need inline InterfacedObjects to be freed?

    The inline variable in question will be of type TCar as its type will be inferred from type used in constructor: TCar. In such code where object instances are reference counted, you will need to explicitly specify correct type: ICar because reference counted instances need to be stored in interface references for proper initialization of reference counting mechanism. var car: ICar := TCar.Create;
  25. I already checked. Domains where it might work better are in a creative domain where there are no right or wrong answers, but then it is just a parrot that repeats someone's thoughts. When people talk about AI they like to focus on intelligence. But ChatGPT is just a language model, with some corrective mechanisms on top. What it means? It means there is no intelligence involved. It is just fancy "text completion" model that uses probability to determine which word should follow next in some sentence. Even when the model grows, and its probability analysis improves, it is still just dumb "text completion" It will never be able to reason about what it writes. And again, it may get better in avoiding ridiculous mistakes, but you are still stuck with original issue: you cannot trust the information it gives you, because it may not be correct and you will not be in position to realize that.
×