Jump to content

Marat1961

Members
  • Content Count

    74
  • Joined

  • Last visited

  • Days Won

    1

Everything posted by Marat1961

  1. Marat1961

    Organizing enums

    I remember where I had to use an enumerated type of this size. Probably the largest type is tokens in the parser. But now I use the compiler of the compiler. In my opinion, when there are a lot of objects, they no longer work by name. The head and brains do not need to be overloaded. For identification, you already need to use handlers. So that there is no desire to cope with them, you can put the whole in the record. hParam = record v: Cardinal; end; hParamHelper = record Helper for hParam constructor From (v: Cardinal); function request: hRequest; inline; end; or they write well here http://gamesfromwithin.com/managing-data-relationships
  2. Marat1961

    Organizing enums

    If you put in a record or a class, the type name will be a namespace. To refer to a constant you use the dot notation Record_type.Constant_name
  3. Marat1961

    Organizing enums

    Or you can add a new value to the end of the list. For example, we take Google protocol buffer, where tags are used to identify fields. Do not touch the old field identifiers unless you want to break anything.
  4. Marat1961

    Organizing enums

    Why do you need to inherit records? If I know the value of the constant, I don't need anything else. Also, no one forbids transferring the api header files. Take tlb for example, constants are beautifully declared in it. Within the module. Can be within a record or class. When I use Windows dll I can perfectly use the constants from the header file.
  5. I do not understand the thought, perhaps I am already tired and my head is working so-so.
  6. Marat1961

    Organizing enums

    I corrected the syntax of the example
  7. Marat1961

    Organizing enums

    As for C ++, I was in a hurry. Although when porting, I very often port as a list of constants. Wonderful sources for oberon do without enumerated types. In Java, an enumerated type can be inherited and extended.
  8. Marat1961

    Organizing enums

    type TMyType = record const &Template = 0; &Static = 1; Header = 2; Custom = 3; type TMySetType = set of &Template..Custom; end;
  9. Marat1961

    Organizing enums

    For example, we took the direction of the cardinal points North South West East. Then he finds out that this is not enough, we decided to add. The question is where to add? Now what to do with that code that uses only 4 directions?
  10. Marat1961

    Organizing enums

    Of course I do. All programmers, for example, in java-script are forced to use the same approach. The original K&R C dialect did not have enumeration types, however they were added in the ANSI C standard.
  11. Marat1961

    Organizing enums

    The enumerated type has been removed in oberon. When Niklaus Emil Wirth came to us in Tomsk. We asked him a question, the reason for this was done? We got an answer about his shortcomings. 1. Very often, an enumerated type cannot be extended, This may be due to the fact that it is from a third party library and the domain of its values is already sealed. 2. A set of constants can successfully perform the same role. 3. One and the same concept is often used in different classifications, which leads to the growth of similar names with distinguishing prefixes. 4. The prefix is essentially the same vicious Hungarian notation LPStrZ_to_hell For convenient use, a related set of constants can be placed in a module or record. The record will act as a namespace. Here we will not be limited to expanding the list of values. Also, we can always add related methods for working with these values. THTMLType = record public const Template = 0; Static = 1; Header = 2; Custom = 3; end; Criticism The enumeration type is traditional in advanced programming languages, is widely used and is often taken for granted. However, this type is also not without criticism from programming theorists and practitioners. So, when developing the Oberon programming language, enumerated types were included in the list of features that were removed from the language. Niklaus Wirth, the language developer, gave the following reasons: “In an increasing number of programs, the ill-considered use of enumerations ... leads to a population explosion among types, which, in turn, leads not to clarity of programs, but to verbosity” [1]; when an enumeration type is exported by a module (that is, it becomes part of the interface), the general rule is violated - the type export command simultaneously exports all its elements, while for all other types, the type export hides its internal structure; from the point of view of ensuring readability of programs, nothing prevents you from using just a group of jointly defined named constants instead of an enumerated type, especially when there are language mechanisms such as modules or classes. On the other hand, for example, in Java, which initially did not contain an enumerated type, this type was subsequently introduced for reasons of not only convenience, but also reliability: the problem of using named constant groups instead of enumerations is that there is no compiler control as to the uniqueness of values constants, and the possibility of random assignment to variables of values that do not correspond to any of these constants.
  12. I think the compiler developers have work to do. In my opinion, of all the pascal compilers I have worked with, the best code generated was Pascal - 2 Oregon software for pdp-11. Amazing register optimization. Carrying out expressions for cycles and much more. This compiler generated better code than the C compiler.
  13. I'm sorry, I was wrong in this case. SgList doesn't really support managed types. The implementation of this collection was one of the very first. I actually used it for data that does not contain managed types. It will be necessary to fix this shortfall and do it in about the same way as in other collections, in which this problem should not be. You will need to look into the code of each collection again and provide test support for the managed types.
  14. I have no complaints about the library. I already wrote about this. I looked at the library code. The spirit of the library is close to java. I was offended by several phrases that I considered incorrect. 1. What I observed though is that they are no general purpose collection classes but obviously tailored for some specific needs - you cannot use TsgList <T> for any type as it is very limited as what it handles (only non managed types). I'm sorry, I was wrong in this case. SgList doesn't really support managed types. The implementation of this collection was one of the very first. I actually used it for data that does not contain managed types. It will be necessary to fix this shortfall and do it in about the same way as in other collections, in which this problem should not be. You will need to look into the code of each collection again and provide test support for the managed types. 2. I also did not do a in depth performance comparison but just adding some Integers to a list was 3-4 times slower than in my latest Spring4D build (which is a faster than the RTL). I looked at the test. First, we specify the size of the list, and then we assign a scalar value to the allocated memory area. In this case, a collection is used, which is essentially a clone of the standard collection, with the exception of the possibility to refer to a data element by a pointer and using a memory region. I suggested changing the test a bit, bringing it closer to real conditions. Added a level and we have indirection of access to the data item. In my opinion, an indirect base-index access method is obtained. Instead of a base-index accessor. In addition, I now have to check the correctness of the index. procedure TMemSegment.CheckPointer (Ptr: Pointer; Size: Cardinal); var lo, hi: NativeUInt; begin lo: = NativeUInt (@Self) + sizeof (TMemSegment); hi: = NativeUInt (@Self) + HeapSize - Size; Check (InRange (NativeUInt (Ptr), lo, hi)); end; I have been developing software for embedded microprocessors for six years and always took my parachute with me during a real flight. This is me about checks when accessing an array. Now, though, I have this option enabled at least during the development of the project. This and some other checks can be left only for debugging, but I love to fly with a parachute and identify the problem at the point of origin.
  15. The conversation is about the Spring4D project. For simplicity of heart, I ran the test in the IDE. program Spring.Tests;
  16. I actually talked about "division by zero in the context of working with a library offering work with collections and IOC. Why not check the parameter for zero and display a message in the place where it might appear? Perhaps the error was in the test: "What will happen with our engine if we are dealing with a buggy UDF?" Access Violation was not met! I brought them alongside because they are hardware.
  17. The Delphi Runtime Library is a collection of levels of abstraction. RTL itself is implemented on top of the operating system API. The operating system (already sometimes) runs using hardware and a processor. Take an I / O library for example. It is pertinent to see an exception like "Oh, I (i / o) cannot open the file". Or "Oh, why am I (i / o) trying to read something beyond the end of the file." When I see "division by zero" or "Access violation" it is generally a disaster - a tragedy. This means that the problem did not occur at the library level, but at the hardware and processor levels. For me, this is a signal that the memory is destroyed, or the code does not understand what. I am an advocate of defensive programming. The library function must validate the input parameters.
  18. Usually when I implement a library for it, I declare a separate type of exception. When checking when throwing an exception, I try to use only this type of exception. While running the tests, I added a bunch of "ignore on execution" exceptions. The most incredible exceptions were thrown. Especially, I was very confused by the "division by zero" exception. I decided that it was not worth continuing further. I really decided that the installation of the library was done incorrectly.
  19. Your library code is functionally complete. Written well and reliably, you can see a strong love for interfaces and OOP. I also had a love stage with COM objects and interfaces. I am now developing the protobuf-delphi project and was looking for a suitable collection implementation. It will be possible to try to make code generation for your library. The integer test will not be able to show the advantage of using memory regions. I have an implementation of two buffers https://sourceforge.net/projects/protobuf-delphi/, which I used on the application server for folding there the results sent to the client. A segmented buffer is a connected chain of memory regions and when there is not enough memory, it asks for another piece of memory. The second buffer uses a continuous piece of memory and has a different allocation strategy. When there is insufficient memory, it asks for a larger piece of memory (usually ReallocMem), copies the current data (Assign) and then deletes the old block (FreeMem). Now we have to consider a typical memory manager implementation. And at my age, I have seen and studied the device dozens of their implementations (starting with the implementation of Donald Knuth on his UM processor...). Working with a heap in Delphi uses this structure TMemoryManager = record GetMem: function(Size: Integer): Pointer; FreeMem: function(P: Pointer): Integer; ReallocMem: function(P: Pointer; Size: Integer): Pointer; end; At first, the memory in the heap is not defragmented and we have one solid piece of memory. The mechanism of allocation at this stage is sequential. A correct implementation of ReallocMem checks the input parameter of a variable and if it is on the free memory pile boundary, it will simply reduce the amount of free memory and move the free memory pile boundary. In this case there is no need to copy data and delete the old block. You have TArray<Integer> used "overboard" your class. In other words, it's a dynamic array. In my case, it uses a continuous memory region. If you are in a loop, you will increment a single collection we have one solid piece of memory and we test the dynamic array operation in the best conditions imaginable. So your test is in an ideal world. In order to see the difference you need to get closer to the combat conditions of use. Integer is not an object, not a string that is placed in a heap. If it is possible to use records instead of an object I use a record. I don't like to use controllable types (string, interface, reference to proc). for the record fields in a heavily loaded server. Because Delphi's finalization operation is not very cheap, it uses rtti and will scan the record fields in order to take account of the referenced fields with a managed type. Why don't we improve the test and bring it closer to the real world? It is possible to simulate the real working conditions of the program. First, we bring the heap to a defragmented state. Defragmentation occurs after multiple memory allocation and memory return. Then we interrupt the work of several collections including a linked list, a hash table and a tree. Memory freeing should be used as well. BSP Test Take for example the BSP algorithm and implement it 1. on your collections using objects. 2. on SGL collections using records placed in memory regions. Multithreaded application server Simulate typical server operation state. There are different types of requests from different clients. We accept them, service and return the answer. It can be json, xml or binary data format such as Google protocol buffer.
  20. I always analyze the types of data being processed and the operations that will be performed on them. It is possible to combine the merits of both array and linked list. To do this, it is enough to use data structures using memory regions. If you arrange the list items in a memory region, the data will certainly be located side by side and the percentage of cache hits will be maximum. Using structures using memory regions can also make the job of freeing memory easier. I would also advise to take a closer look at the storage format of the buffer protocol. Which is equally good for storing any data. In addition, it shakes data quite well. at the expense of default values and does not store empty values. All messages in this format start with a length value. You can store pointers to their beginning in an array. You can pass this set of bytes to the reader of an object that reads data. The writer of an object can write its state to a buffer. If this is processing data from client applications, I would do something like a processing context associated with a specific client and perhaps a message builder based on a deterministic finite automaton. https://github.com/marat1961/protobuf-delphi https://github.com/marat1961/Oz-SGL
  21. François, I was very glad to see you. I want to say a big thank you for your ICS components. In my server, I used them.
  22. I was wondering if you've actually done comparative testing of adding to the list? Which list did you use? Can I see your code? I downloaded your project. Installed. Trying to run the tests resulted in a huge number of exceptions being thrown. What's wrong with the project? I am using Delphi Community Edition 10.3.
  23. I rarely inherit from collections, for some reason I rarely have a desire to add something. If you want to extend functionality without adding fields, use a helper. I am a fan of domain-driven design. Using inheritance for collections does not seem to be a very good idea to me. I am very suspicious of thoughtless inheritance. Most often, inheritance does not solve a problem, usually it creates them. If it is necessary to reuse code, use the aggregation relation. You can replace inheritance with aggregation and declare only the methods you need in the public section. 1. Place the structure you want to aggregate as a private field 2. Next we open only the necessary part of the interface by redefining it to public sections of required methods and properties. If you set the inline option, we will avoid additional costs. The Delphi compiler will not generate code for overridden methods. At the place where the method is called, there will be a direct call to the aggregated structure method. Selecting abstraction levels is not a rarity. FastMM replaces the memory manager. Delphi manager works on top of the operating system manager. The memory organization system is very well written here. https://www.gunsmoker.ru/2009/01/blog-post.html https://www.gunsmoker.ru/2011/04/windows.html https://en.wikipedia.org/wiki/Region-based_memory_management I use FastMM with fully enabled diagnostics, no problems with memory leaks. The code of this library is used in real projects. Practice is a criterion of truth.
  24. Why did you decide that the type of something is limited? You want to use a record, an object or a string ... This is not quite true, managed types are supported. First, when type assignment occurs, all counters for managed types will be updated (Delphi string, interfaces, etc.). Second, when deleting data, the cleanup method is passed, which will be used when deleting. If it is a record with managed types, it can be a procedure inside which the Default (TMyRecord) operator contains.
×