C ++ permanent Object Storage

Source: Internet
Author: User

C ++ permanent Object Storage (Persistent Object Storage for C ++)

Introduction

Describes how to use object types to allocate and release objects from memory permanent Object Protocol Memory constructor to enable POST ++ installation of memory POST ++ class library and POST ++ to replace standard sub-game with STL class POST ++ debugging POST ++ application details about POST ++ more information

POST ++ provides simple and effective storage for application objects. POST ++ is based on the memory file image mechanism and page image processing. POST ++ eliminates the overhead for permanent object access. In addition, POST ++ supports multi-storage, virtual functions, atomic data update operations, efficient memory allocation, and optional garbage collectors for specified memory release modes. POST ++ can also work well on objects with multiple inheritance and pointers.

Description object type

POST ++ storage management requires some information so that the permanent object type supports the Garbage Collector. During loading, the reference is relocated and the function pointer in the virtual table is initialized. Unfortunately, the C ++ language does not provide a mechanism to extract the information from the class during runtime. To avoid using special tools (pre-processors) or "dirty" channels (retrieving class information from debugging information), this information must be specified by the programmer. These are called class registrars and can be simply implemented through some macros provided by POST ++.

POST ++ calls the default constructor to initialize objects when reloading objects from memory. To store object handles, the programmer must include the macro CLASSINFO (NAME, FIELD_LIST). NAME in the class definition to specify the object NAME. The reference field of the FIELD_LIST description class. In the header file classinfo. h, three macros are defined to describe fields:

REF (x) describes a field. REFS (x) describes a One-Dimensional Fixed Array field .. (For example, a fixed-length array ). VREFS (x) describes variable one-dimensional array fields. A mutable array can only be the last member of a class. When defining a class, you can specify an array containing only one element. The number of elements in a specific object instance can be specified during creation.

These macro lists must be separated by spaces: REF (a) REF (B) REFS (c ). Macro CLASSINFO defines the default constructor (constructor without parameters) and Class descriptor. The class descriptor is a static member of the class named self_class. In this way, the class foo descriptor can be accessed through foo: self_class. Default constructors of base classes and members are automatically called by the compiler, so you don't have to worry about calling them explicitly. However, do not forget to use the CLASSINFO macro in the structure definition for the structure members in the serialized class. Then, register the class through the memory management to make it accessible. This process is completed by the macro REGISTER (NAME. Class names and objects are put together in the memory. When the storage is opened, the class is mirrored between the storage and the application. The class names in the memory and the class names in the program are compared. If a class is not defined by the program or the class in the application and memory has different sizes, the program asserted that it will fail.

The following example describes these rules:

Struct branch {object * obj; int key; CLASSINFO (branch, REF (obj) ;}; class foo: public object {protected: foo * next; foo * prev; object * arr [10]; branch branches [8]; int x; int y; object * childs [1]; public: CLASSINFO (foo, REF (next) REF (prev) REFS (arr) VREFS (linked); foo (int x, int y) ;}; REGISTER (1, foo); main () {storage my_storage ("foo. odb "); if (my_storage.open () {my_root_class * root = (my_root _ Class *) my_storage.get_root_object (); if (root = NULL) {root = new_in (my_storage, my_root) ("some parameters for root ");}... Int n_childs = ...; Size_t varying_size = (n_childs-1) * sizeof (object *); // We shocould subtract 1 from n_childs, because one element is already // present in fixed part of class. foo * fp = new (foo: self_class, my_storage, varying_size) foo (x, y );... My_storage.close ();}}

Allocate and release objects from memory

POST ++ provides special memory allocation sub-accounts to manage the storage memory. This assignment uses two different methods: small objects and large objects. All storage memory is divided into pages (the page size is irrelevant to the page size of the operating system, and 512 bytes are used in the current version of POST ++ ). Small objects are such objects whose size is less than or equal to 256 bytes (page size/2 ). These objects are allocated as fixed block links. Each chain contains blocks of the same size. The size of the allocated object is 8 bytes. It is recommended that the number of chains allocated to each object containing 256 of these chunks should not be greater than 14 (different number of balanced pages ). Before each object, POST ++ assigns an object header, which contains the Object ID and object size. Considering that the header is exactly 8 bytes, and the total size of the object in C ++ is greater than 0, 8 chunks can be discarded. It is usually very fast to allocate and release small objects: you only need to perform one insert/delete operation from the L1 queue. If the chain is empty and we try to allocate new objects, the new page is allocated to store objects of the current size (the pages are divided into blocks and added to the linked list ). Space required for large objects (larger than 256 bytes) is allocated from the free page queue. The size of a large object is aligned with the page boundary. POST ++ uses the first feed to the random location algorithm to maintain the free page Queue (the idle segments of all pages are arranged by address and followed by a special pointer to the current position of the queue ). For the implementation of storage management, see file storage. cxx.

Whether explicit or implicit memory is used depends on the programmer. Explicit Memory release is faster (especially for small objects), but implicit memory release (garbage collection) is more reliable. Use the flag and garbage collection mechanism in POST ++. There is a special object in the storage: root object. The garbage collector first marks that all objects can be accessed by the root object (that is, they can be reached from the root object and traversed through reference ). In this way, all unlabeled objects are released in the first GC phase. The garbage collector can be generated when an object is loaded from a file (if you pass the do_garbage_collection attribute to the storage: open () method ). You can also call the storage: do_mark_and_sweep () method to call the Garbage Collector during the program running. However, be sure that the objects not pointed to by program variables cannot be accessed from the root object (these objects will be released by GC ).

The multi-inheritance C ++ class can have a non-zero offset in the object and may also be referenced in the object. This is why we need to use special technologies to access object headers. POST ++ maintains the page allocation bitmap, where each bit corresponds to the page in the memory. If some large objects are allocated on several pages, all the pages occupied by these objects are set to 1 except the first one. All other page BITs exist in the in-place graph. To find the starting address of an object, we first sort the pointer values by page size. Then, POST ++ searches for the object start page from the bitmap (This page has a zero position in the bitmap ). Then, the object size information is retrieved from the object header contained at the beginning of the page. If the size is greater than half of the page size, we have found the Object Description: it is at the beginning of the page. On the contrary, we calculate the size of the fixed block used in the page and calculate the pointer offset in the page based on the block size. This head location scheme is used by the garbage collector. class objects define operator delete and are used to parse the object size and class information from the object header.

In POST ++, a particularly overloaded new method is provided for object allocation in storage. This method requires the class description of the object, the storage of the object, and the variable part size of the optional object instance as an additional parameter. The macro new_in (STORAGE, CLASS) provides permanent object creation "syntactic Sugar ". Permanent objects can be deleted by the redefined operator delete.

Permanent object protocol

All permanent object classes in POST ++ must inherit the class objects defined in object. h. This class does not contain any variables and provides methods to allocate/release objects and obtain class information and size during runtime. A class object can be a base class that inherits multiple classes (the order of the base classes does not matter ). Each Permanent class must have a constructor for the POST ++ system (see the Describing object class section ). This means that you cannot use constructors without parameters for initialization. If your class constructor does not even have any meaningful parameters, you must add a fictitious one to distinguish it from the constructor created by macro CLASSINFO.

To access objects in permanent storage, programmers need a root object, which can be used to access every other object using a common C pointer. The POST ++ memory provides two methods to specify and obtain the reference of the root object:

Void set_root_object (object * obj); object * get_root_object ();

When you create a new storage, get_root_object () returns NULL. You need to use the set_root_object () method to create the root object and save the reference in it. The next time you open the storage, you can get the root object through get_root_object.

Tip: in actual applications, classes are usually changed during program development and maintenance. Unfortunately, POST ++ does not provide a tool for Automatic Object conversion (see the lazy object update design example in GOODS). To avoid adding new fields to the object, I only recommend that you reserve some space in the object for future use. This is especially important for the root object because it is the preferred choice for newly added objects. You also need to avoid converting the reference of the root object. If no other object contains references to the root object, the root object can be simply changed (through the set_root_object method) to the instance of the new class. POST ++ storage provides methods for setting and obtaining the Village Publishing logo. This identifier can be used by the application to update objects in the memory based on the storage and application version.

Memory constructor you can use several memories in an application at the same time. The memory constructor has a required parameter-storage file path. If the file does not have an extension, POST adds a suffix "for the file name. Odb ". This file name is also used by POST ++ to form the names of several auxiliary files:

File description uses the timing suffix to include temporary files for the new memory image for saving the new memory image in non-transaction processing mode ". tmp "the transaction record file is used to save the image page in transaction mode ". log "saving storage file backup is only used for renaming temporary files under Windows-95 ". sav"

The other two parameters of the memory constructor have default values. The first parameter max_file_size indicates the memory file extension limit. If the storage file is larger than storage: max_file_size, it will not be removed, but it cannot be further expanded. If max_file_size is greater than the file size, the action depends on the mode in which the storage is enabled. In transaction mode, files are mirrored to the memory under read/write protection. Expand the file size from Windows-NT/95 to max_file_size. The file size is shortened by the storage: close () method to the boundary of the last object in the memory. In Windows, to enable storage in read/write mode, there must be at least the number of idle bytes of storage: max_file_size on the disk, even if you are not prepared to add a new object to it.

The last parameter of the memory constructor is max_locked_objects. this parameter is only used in transaction mode to provide a buffer for writing transaction record files on the image page. To provide data consistency, POST ++ must ensure that the modification page is saved in the transaction record file before the image page is refreshed to the disk. POST ++ uses one of the two methods: Synchronous record writing (max_locked_objects = 0) and page lock buffer writing in the memory. By locking the page in the memory, we can ensure that the transaction record buffer money is not exchanged to the disk. The image page is written to the transaction record file in asynchronous mode (including operating system buffering enabled ). When the number of locked pages exceeds max_locked_pages, The Record File Buffer is refreshed to the disk and all locked pages are unlocked. This method can significantly improve the transaction processing capability (increased by 5 times under NT ). Unfortunately, different operating systems use different methods to Lock pages in memory.

Windows 95 is not supported at all. In Windows NT, each process can lock its page, but the total number of locked pages cannot exceed the running configuration limit. By default, processes can lock more than 30 pages. If you specify the max_locked_pages parameter greater than 30, POST ++ will try to extend the process configuration to suit your needs. However, in my experience, the performance gap between 30 and 60 locked pages is very small. In Unix, only super users can Lock pages in memory. This is why the file constructor checks whether the process has sufficient permissions to use the lock operation. Therefore, if you specify the max_locked_pages parameter to be greater than 0, you will decide whether to use synchronous or asynchronous write transaction record files when creating the storage class. If you want to use the Memory Lock Mechanism (2-5 times, depending on the transaction type), you need to change the owner of your application to root and grant the set-user-ID permission: chmod + s application.

Open storage

POST ++ uses the Memory ing mechanism to access data in files. In POST ++, data consistency is provided through two different methods. First of all, more advanced is that the image page used based on the transaction mechanism provides storage recovery and transaction rollback after an error occurs. The operation is created before the image writing page. This operation is performed as follows: all file ing pages are set to read-only protection. Any write access to these pages will cause access violation exceptions. This exception is captured by a special handle, which changes the page to be protected as read/write and copies of this page in the transaction record file (the record file name is the original file name and the suffix ". Log ). All subsequent write operations on this page will not cause page errors. The memory method commit () refreshes all the changed pages to the disk and truncates the record files. The storage: commit () method is implicitly called by storage: close. If an error occurs before the storage: commit () operation, all changes will be restored by copying the changed pages in the transaction record to the stored data file. Similarly, all changes can be explicitly called.

Storage: rollback () method for restoration. Specify the storage: open () method's storage: use_transaction_log attribute to select the mode in which the file access service is based.

Another method that provides data consistency is based on the write copy mechanism. In this case, the source file is not affected. Any attempt to change the file image page causes a copy of the page, which is allocated from the system swap zone and has read/write permission. Files are not updated until the storage: flush () method is explicitly called. This method writes data to a temporary file (with a suffix ". Tmp) and rename it to the original one. Therefore, this operation forms an atomic update of the file (assuming that the operating system can ensure the number of atoms for the rename () operation ).

Note: if you do not use transaction processing, the storage: close () method does not fl data into the file. So if you call the storage: flush () method before this, all the changes since the last flush will be lost.

Windows 95 details: Renaming an existing file in Windows 95 won't work, so the source file is saved as a suffix first. The name of the sav file. Then the suffix is ". Tmp "temporary file is renamed to the original name and the last old copy is deleted. So if the error occurs in the flush () operation and you cannot find the storage file, please do not panic, just find the suffix ". And rename the sav file to the original one.

Tip: If you plan to save data during program execution, I strongly recommend that you use transaction processing. You can also use the write copy method, but this requires a lot of consumption. Similarly, it is usually better to store very large transactions, because the generation of temporary file copies requires a lot of disk blank faces and time.

There are several attributes available for storage open ()

Usage:

Support_virtual_functions this attribute must be set if the object in the memory carries a virtual function. If this attribute is not set, POST ++ assumes that all permanent objects in the storage only contain references (for other objects in the storage ). Therefore, you need to adjust the reference only when the base address of the data file image changes (this address is stored in the first word of the data file, and POST ++ usually tries to map the file to the same address. to avoid unnecessary reference adjustments ). However, if the object class contains a virtual function, the pointer to the virtual table is placed in the object. If you recompile your application, the address of this subject may change. The POST ++ library compares the timestamp of the execution object with the timestamp of the database generated by this application. If the timestamp is different, the pointer of the virtual table is corrected. To obtain the application timestamp POST ++, you must be able to locate the execution file object. Unfortunately, the simple method for executing the file name is not found. In Unix POST ++, check the value of the environment variable "_" set by the command line interpreter. However, if the process is not executed from the command line (such as through system () or the working directory is changed by chdir (), this method does not work. The simplest method is to use the file comptime. cxx, which must be compiled every time you recompile your application and linked together with the repository. This problem is not found in Windows. You can obtain the image name through Win32 API. When the memory is opened, POST ++ compares the timestamp with the time limit of the data file. If they do not wait and specify the support_virtual_functions attribute, all objects are corrected (by calling the default constructor ). By setting this attribute, read_only indicates that the programmer only needs the data file read permission. POST ++ will create a read-only view of the data file and any attempt to change the objects in the memory or assign new objects will cause a protection violation error. Here is an exception: if the image data file cannot be mapped to the same address or the application changes, and support_virtual_functions is specified, so the protection for this region is temporarily changed to write copy and the loaded object is converted. Use_transaction_log sets this attribute to force transactions to be used for all data file updates. The Shadow page is used to execute transactions. The transaction is opened after the storage is modified for the first time. You can use the storage: commit () or storage: rollback () operation to explicitly disable the service. Method storage: commit () saves all change pages to the disk and truncates transaction records. Method storage: rollback () ignores all changes in this transaction. No_file_mapping by default, POST ++ transfers the image data file to the virtual memory of the process. In this case, the time to open the database is greatly reduced, because the file page will be transferred as needed. However, if the database size is not very large or all data in the database needs to be accessed immediately, it is better to read the file into the memory than to use the virtual memory image because there is no additional page overflow error in this case. It indicates that no_file_mapping blocks the POST ++ image file and reads the file based on the allocated memory segment. The fault_tolerant flag is used by applications to protect Database Consistency when system or application errors occur. If the transaction use_transaction_log flag is used, you do not need to specify it because consistency can be provided by the transaction mechanism. If the use_transaction_log flag is not specified and the fault_tolerant flag is set, POST ++ will not change the source file and maintain its consistency. This relies on reading files to the memory (if the no_file_mapping flag is not set) or using write copy page protection. In the latter case, a page copy attempt to change the image to a file will generate a page copy in the system swap file. The flush () method saves the image of the in-memory database to a temporary file and renames it to the source file using the atomic operation. If the fault_tolerant flag is not specified, POST ++ changes the original location on the database page, provides maximum application performance (because there is no additional overhead for copying and modifying pages and saving database images to temporary files ). When the modification page does not immediately refresh to the disk, some changes may be lost due to system errors (the worst thing is that some modified pages are saved while others are not saved-So Database Consistency may be disrupted ). When this attribute is set for do_garbage_collection, POST ++ will perform garbage collection when the storage is opened. Garbage collection operations and pointer alignment are linked together. It is often safer to use garbage collection than to release manual memory (considering the suspended reference issue), but the explicit memory release overhead is less. The garbage collection in POST ++ has a greater advantage than explicit memory allocation: the memory collector optimizes the pages used by small objects. If no small objects have been allocated to the page, the garbage collector will include this page in the idle page. This will not be completed during explicit release, because the idle units of small objects are chained and cannot be simply removed from the chain (all chains in the garbage collector are reconstructed ). Even if you use explicit memory release, I still recommend that you perform garbage collection at regular intervals to check the reference consistency and no memory leakage (the garbage_collection method returns the number of released objects, if you are sure that you have released all unreachable objects, the value will be 0 ). Considering that the Garbage Collector modifies all objects in the storage (sets the mask bit) and reconnects idle objects in the chain), running GC in transaction mode may consume time and disk space, because the pages in all files will be copied to the transaction record file ).

You can use the file: max_file_size variable to specify the maximum size of the stored file. If the data file size ratio is file: max_file_size and the mode is not read_only, bytes other than size_of_file-file: max_file_size in the virtual space will be kept behind the file image space. When the storage size is expanded (because new objects are assigned), these pages are submitted (in Windows NT) and used. If the file size is greater than file: max_file_size or the read_only mode is used, the image size is the same as the file size. In the latter case, storage expansion is not possible. In Windows, I use the GlobalMemoryStatus () method to obtain information about the actually allocable virtual memory of the system and reduce file: max_file_size to this value. Unfortunately, I found that there is no lightweight call in Unix to achieve the same purpose (getrlimit does not return the exact information of the virtual memory that a user process can use ).

The Object storage interface is defined in file storage. h and the implementation part can be seen in storage. cxx. The image memory files dependent on the operating system are encapsulated in the file class, which is defined in file. h and implemented in file. cxx.

POST ++ Installation

POST ++ is easy to install. Currently tested in the following systems: Digital Unix, Linux, Solaris, Windows NT 4.0, Windows 95. I hope for most of the other new Unix dialects (AIX, HP-UX 10, SCO ...) No problem. Unfortunately, I have never used these systems. In Windows, I use Microsoft Visual C ++ 5.0 and Borland 5.02 compilers for compilation. The Makefiel of Visual C ++ is makefile, And the Makefile of Broland C ++ is makefile.

The only thing you need to use POST ++ is the function library (libstorage. a in Unix is and storage. lib in Windows ). This library can be generated by running the make command. There is a special MAKE. BAT is used in Microsoft Visual C ++ and uses makefile. mvc calls NMAKE as input (if you are using Borland, edit this file or use make.exe-f makefile. bcc command call ).

The installation in Unix can be completed by copying the POST ++ Library and the same file to some standard system directories. You must set the appropriate values for the INSTALL_LIB_PATH and INSTALL_INC_PATH variables in makefile and run the make install command. The default value of INSTALL_LIB_PATH is/usr/local/lib INSTALL_INC_PATH, Which is/usr/local/include. You can explicitly specify the path to the POST ++ directory to compile and link to avoid copying files to the system directory.

POST ++ class library

POST ++ includes some definitions of persistent classes, which can be used for your application or as a good example for developing POST ++ classes. You can see that the implementation of those classes does not even have POST-specific code. These classes include array (array), matrix (matrix), string (string), L2-list (L2-list), hash table (hash table ), AVL-tree (AVL-tree), R-tree (R-number), and text object (text object ). R-tree provides fast access to spatial objects (objects containing spatial equivalents. The text object contains the correction of the Boyer and Moore algorithm, which is extended to the symmetric search composed of the OR/AND relationship. The definitions of these classes can be found in the following files:

Arrays of scalars and references, matrixes and stringsarray. harray. cxxL2-list and AVL-treeavltree.havltree.cxxHash table with collision chainshashtab. hhashab. cxxR-tree with quadratic method of nodes splittingrtree. hrtree. cxxT-tree (combination of AVL tree and array) ttree. httree. cxxText object with modified Boyer and Moore search algorithmtextobj. htextobj. cxx

T. j. lehman and M.J Carey propose to use T-trees as an effective data structure for storage of the primary memory database. T-trees is proposed by Adelson-Velsky and Landis Based on the AVL Tree. In this segment, we provide an overview of T-trees as an implementation in POST ++.

Like the AVL tree, the height difference between the left and right subtree of the T-tree is not greater than 1. Unlike the AVL tree, each node in the T-tree stores multiple key values instead of a single key value. The leftmost and rightmost key values in a node define the ranges of key values contained in the node. In this way, the left subtree of a node only contains key values smaller than the leftmost key values, while the right subtree contains key values greater than the rightmost key values of the node. The key value falling between the minimum and maximum key values in a node is called bounded ). Note that keywords equal to the maximum or minimum keyword can be considered to be restricted or not restricted based on whether the index is globally unique and the Search Condition (e.g. "greater than" ("greater-than") relative to "greater than or equal to" ("greater-than or equal-")).

A node with both left and right subtree is classified as an internal node. A node with only one subtree is classified as an incomplete leaf (semi-leaf ), A node without a subtree is classified as a leaf (leaf ). To maintain high occupancy, each internal node has a minimum number of key values that must be included (typically K-2, if k is the maximum number of keywords that can be arranged in a node ). However, for leaves and incomplete leaves, there is no occupancy condition.

Searching in T-tree is equivalent to directly searching. For each node, check whether the key value is between the leftmost and rightmost key values of the node. In this case, that is to say, if the key value is included in the node, the value is returned (otherwise, the key value is not included in the tree ). Otherwise, if the key value is smaller than the leftmost key value, search for the left subtree, and vice versa. Repeat this process until the key value is found or the null node is found.

It is a little complicated to insert or delete data in the T-tree. For the insert operation, first use the search process above to find the nodes that constrain the insertion of key values. If such a node exists, the key value is inserted into the node if the node is idle. If the node is not empty, the key value is inserted into the node, and the leftmost key value of the node is inserted into the left subtree of the node (if the left subtree is empty, assign a new node to insert the leftmost key value ). If no constraint node is found, use N to represent the last node that fails to be searched and follow the steps below to continue: If N is free, then the key value is inserted into N; otherwise, the key value is inserted into a new node and is used as the right or left subnode/tree of N based on the key value, the leftmost key value, and the rightmost key value.

Deleting a key value starts from determining the node that contains the key value and deletes the key value from the node. If an empty leaf node is left after the key value is deleted, the node is also deleted. If an internal node or incomplete leaf contains a key value smaller than the minimum number after deletion, otherwise, it will be supplemented by moving the maximum key value in the left subtree to the node or merging the node and the right subtree.

Whether inserted or deleted, assigning or releasing nodes may cause tree imbalance and rotation (RR, RL, LL, LR ). (The height of the subtree is described below, including the impact of insertion and deletion .) In the case of insertion, check the nodes from the newly allocated node to the root node

It is found that a node has two tall Subtrees (in this case, no rotation is required ), you can also find that the left and right subtree of a node have different heights greater than 1 and perform a single rotation containing nodes.

When deleting a node, check that the height of the Child tree of a node is 1 different from that of the parent node of the released node to that of the root node. In addition, when the height difference of the subtree of a node is greater than 1, a rotation is performed. Note that releasing a node may cause multiple rotations.

There are several test programs to test the classes in the POST ++ persistent class library. They are included in the default make target:

ProgramTested classestesttree. cxxAVL-tree, l2-node, hash tabletesttext. cxxtext, stringtestspat. cxxrectangle, R-tree, hash tabletestperf. cxxT-tree insert, find and remove operations

Use STL class with POST ++

It is possible to save and retrieve STL classes from POST ++ memory. POST ++ provides a special STL Allocation Sub-function and reloads the new/delete operator to keep STL objects. There are several models that make STL persistent, which are controlled by the following macros:

USE_MICROSOFT_STL uses the Microsoft STL class, which is included with Microsoft Visual C ++. This class library is not fully compatible with the C ++ STL standard. USE_STD_ALLOCATORS uses the same Allocation Sub-item as in the C ++ standard. Assign sub-objects to be included in STL objects. Assign the sub-objects to the instance to allocate/release space. Therefore, it is possible to execute a "smart" sub-assignment: only when the object contains this allocation sub-item can the sub-game allocate space for the objects in the POST ++ memory and the Allocation Sub-item is stored in the memory. Otherwise, the space occupied by the object will be allocated through the standard malloc () function. This option can be used with the sgi stl library and Microsoft STL library. Note that following the standard sgi stl assignment sub-uses many language features that are not widely implemented. In particular, they rely on member templates, local specialization, method templates for local classification (sorting), typename keywords, and template members that use the template keyword to reference dependency types. Therefore, when this macro definition is specified, only a few C ++ compilers can compile sgi stl libraries. If this macro is not set, POST provides an allocation sub-function containing static member functions and all objects are allocated from the POST ++ memory. Only one POST ++ storage can be opened at a time for the Application allocated with this sub-resource. REDEFINE_DEFAULT_ALLOCATOR has two ways to make the STL object persistent. One way is to introduce a new type:

Typedef basic_string, post_alloc > Post_string;

Another way is to make all classes persistent. When the REDEFINE_DEFAULT_ALLOCATOR macro is defined, any STL class can be allocated in POST ++ memory. To create a new object in persistent storage, you must specify the memory as an additional parameter of the new operator. If the memory is ignored, the object uses the standard malloc () function.

The POST ++ to STL interface does not need to be changed by any STL class, so you can use any STL you want to execute. However, as a result, the STL class does not contain the type description, so POST ++ does not have the format information of the STL object. Therefore, POST ++ cannot perform garbage collection and reference alignment. When the STL interface is used, the POST ++ memory must always be mirrored to the same virtual address. If you pass the storage: fixed flag to the storage: open (int flags) method, if you cannot mirror the storage to the same memory address POST ++, an error is reported and false is returned. If your application only uses one storage and does not mirror other objects to the virtual memory, then almost all operations may mirror the storage to the same memory address.

The POST ++ interface to STL library is defined in the header file post_stl.h. This file must be included in any STL inclusion file. Likewise, macro REDEFINE_DEFAULT_ALLOCATOR, USE_STD_ALLOCATORS, and USE_MICROSOFT_STL are defined before post_stl.h.

POST ++ contains the example stltest. cxx using STL ++ class. This example uses two STL classes-string and vector. The row read from the standard input is pushed to the vector, and the program is started again. All vector elements are printed to the standard output. This example is included in the default target of the makefile configured for Microsoft Visual C ++ (it uses the Microsoft STL class included in VC ). You can also try to build this test using STL libraries of other versions, but do not forget the REDEFINE_DEFAULT_ALLOCATOR and USE_STD_ALLOCATORS macros. This example can also be tested with SGI STLport 3.12 and GCC 2.8.1.

Replace Standard Sub-Games

In the previous section, I explained how to use POST ++ with the STL library. However, there are still many other C ++ and C libraries and applications you want to use, and there is no convenient distribution mechanism like STL. In this case, the only possible solution (if you do not want to change any source code of this library) is to replace the standard allocation mechanism with the one provided by POST ++. In this way, all dynamically allocated objects are allocated from the POST ++ memory (except for a memory that cannot be used in this case ).

The postnew. cxx file contained in the POST ++ release package redefines the standard malloc, free, realloc, and calloc functions. When memory is turned on, all objects are allocated in the memory. Otherwise, the sbrk () function is used to allocate objects (the space allocated to these objects is not recycled ). You may not need to access these standard C assignment functions, but only need to overload the default C ++ operators new and delete. The DO_NOT_REDEFINE_MALLOC macro is defined when postnew. cxx is compiled. The target file generated from postnew. cxx must be passed to the link program before the Standard C library.

For the example of using POST ++, see testnew. cxx and testqt. cxx. The first example illustrates how the standard C ++ array is persistent. The second example illustrates how POST ++ works with the Qt class library.

There is no storage class format information in POST ++. Here, some restrictions are imposed on the use of POST ++:

Classes that contain virtual functions are not supported (POST ++ cannot correctly initialize the pointer to the virtual function table ). Implicit Memory release (Garbage Collector) is impossible-POST ++ has no information about the internal pointer position of the object. The memory must always be mapped to the same virtual address, because the pointer cannot be adjusted if the base address changes POST ++.

If all these restrictions are not necessary for your application, you can make them persistent without any code changes. This method can be used in C and C ++ programs.

How to Use POST ++

Here are several examples of POST ++ classes and applications. The simplest of them is the game "Guess animals ". The game's algorithms are very simple and the results seem impressive (some like artificial intelligence ). In addition, this game is a good example to illustrate the benefits of Persistent Object Storage. The source code of this game is in the file guess. cxx. Create this game to be included in the default make target. Run guess to run it.

Unix specific: do not forget to recompile the comptime. cxx file and include it in the link list when you are preparing to link your Unix application to the POST ++ library and persist objects. This file is required for POST ++ to provide the time stamp of the executable file, stored in memory to determine when the application is changed and re-initialize the virtual function table in the object as needed. Attention! This file must be re-compiled every time you re-link your application. I suggest you have the compiler call the linked program for you and include the comptime. cxx source file in the object file list (see makefile) provided for the target file of the running image ).

Debug POST ++ application details

The content of this section is very meaningful for the application that uses transactions. POST ++ uses the page protection mechanism to generate a shadow page when the source page is modified. The images of all file pages are read-only when the memory is opened or the transaction is committed. Therefore, any attempt to modify the content of objects allocated to these pages will result in an access violation exception. This exception is handled by the specified POST ++ handle. However, if you use the debugger, it will first capture this exception and stop the application. If you want to debug your application, you must make some preparations:

In Unix, you can tell the debugger not to capture SIGSEGV signals. For example, for GDB, you can run the command handle SIGSEGV nostop noprint pass. If the SIGSEGV signal is not generated by the storage page Protection violation, but is an error in the program, the POST ++ exception handler "understands" that it is not its own exception and sends a SIGABRT signal to its own process, which can be captured by the debugger. In Windows POST ++, the Unhandled Exception Filter is used to handle Memory Page protection violations. Unfortunately, Microsoft Debugger cannot ignore exceptions without handling them. If you are going to debug your application, you must encapsulate all your program code (main or WinMain function) as structured exception blocking. You must always use structured Exception handling in Borland C ++ because the Unhandled Exception Filter is not correctly called in Borland. Use two macros SEN_TRY and SEN_ACCESS_VIOLATION_HANDLER () to encapsulate the function bodies of main (or WinMain:

Main () {SEN_TRY {... } SEN_ACCESS_VIOLATION_HANDLER (); return 0 ;}

Make sure that the debugger stops this exception if it has not been processed (instead of always stopping) (you can check it in the Debug/Exceptions menu ). In the file testrans. cxx, you can find an example of using structured exception handling.

More information about POST ++

POST ++ is freeware. Developing her hopes is useful. With her, you can do anything you want (there are no restrictions on using POST ++ in development products ). I will be glad to help you use POST ++ and get any type of information about POST ++ (error reports, suggestions ...). POST ++'s free software does not mean the lack of support. I promise I will try to correct any reported errors. It also supports e-mail. POST ++ has several purposes: saving information during different periods, saving object systems, snapshots, and information systems in files... However, if you feel that you need to use a more important object-oriented Database in your application to provide concurrent, distributed, and transaction processing, visit the GOODS (Generic Object Oriented Database System) home page.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.