C + + Persistent object Storage (persistent object Storage for C + +)

Source: Internet
Author: User
Tags empty exception handling execution file size flush garbage collection hash variables
c++|object| objects




C + + Persistent object Storage (persistent object Storage for C + +)
Profile Description Object types allocate and release objects from memory the permanent object Protocol memory constructor open memory post++ installation post++ class library and post++ use STL class to replace standard branch gametes How to use post++ S debug post++ application details off More information on post++
Post++ provides a simple and efficient storage of application objects. Post++ is based on the memory file mirroring mechanism and page mirroring processing. post++ eliminates the overhead of permanent object access. In addition, post++ supports multiple storage, virtual functions, Data Update atomic operations, efficient memory allocations, and optional garbage collectors for the specified freed memory mode. Post++ can also work well on multiple inheritance and objects containing pointers.


Describe object type
post++ Storage Management requires some information to enable the persistent object type to support the garbage collector, which is to reposition and initialize the function pointers in the virtual table when loading. Unfortunately, the C + + language does not provide a mechanism for run-time information from classes. To avoid the use of special tools (preprocessor) or "dirty spoofing" (Getting class information from debug information), this information must be indicated by the programmer. These things, called Class registrars, can be implemented simply by using some of the macros provided by post++.

post++ invokes the default constructor when overloading the object from memory to initialize the object. In order for the object handle to be stored, the programmer must include the macro ClassInfo (NAME, Field_list) in the class definition. Name to specify the object's names. Field_list describes a reference field for a class. Three macros are defined in the header file Classinfo.h to describe the field:
REF (x) describes a field. REFS (x) Describes a one-dimensional fixed array field. (for example, a fixed-length array). Vrefs (x) Describes a variable one-dimensional array field. A variable group can only be the last member of a class. When you define a class, you can specify an array that contains only one element. The number of elements in a specific object instance can be specified at build time.
The list of macros must be separated by a space: ref (a) ref (b) REFS (c). The macro ClassInfo defines a default constructor (a constructor with no parameters) and a class descriptor. A class descriptor is a static member of a class named Self_class. The descriptor for this class Foo can be accessed through Foo::self_class. The default constructors for base classes and members are invoked automatically by the compiler, and you don't have to worry about calling them explicitly. However, for struct members in a serialized class, do not forget to use the ClassInfo macro in the structure definition. The class is then registered through storage management to make it accessible. This process is done by the macro REGISTER (NAME). The class name is placed in memory with the object. The class is mirrored between storage and application when the memory is turned on. The class name in the memory is compared to the class name in the program. If a class is not defined by a program or has a different size in the application and in memory, the program assertion fails.

The following examples illustrate 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* ch ILDS[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*) m Y_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 should subtract 1 from n_childs, because one element is already// Present in the fixed part of class. foo* fp = new (Foo:self_class, My_storage, Varying_size) foo (x, y); My_storage.close (); }}


Allocating and releasing objects from memory
Post++ provides a special memory allocation for managing storage memory. This assignment uses two different methods: for assigning small objects and large objects. All storage memory is divided into pages (the size of the page is independent of the page size of the operating system, with 512 bytes in the current version of post++). Small objects are objects whose size is less than or equal to 256 bytes (page size/2). These objects are assigned to a fixed sized block link. Each chain contains blocks of the same size. The size of the allocated object is in 8 bytes. The number of chains assigned to each object that contains these blocks size 256 is best not to be greater than 14 (the number of different balanced pages). post++ assigns an object header before each object, containing the object identity and object size. Considering that the head is exactly 8 bytes, and the size of the object in C + + is always greater than 0, the block chain of size 8 can be discarded. Assigning and freeing small objects is usually very fast: you only have to do an insert/delete operation from the L1 queue. If the chain is empty and we try to allocate a new object, the new page is allocated to store objects such as the current size (the page is divided into chunks added to the list). The space required for large objects (greater than 256 bytes) is allocated from the free page queue. The size of the large object is aligned with the page boundary. post++ uses the first feed random location algorithm to maintain the free page queues (the free segments of all pages are arranged by address and a special pointer follows the current position of the queue). Implementation of storage management See file Storage.cxx

Using explicit or implicit memory release depends on the programmer. Explicit memory deallocation is fast (especially for small objects) but implicitly memory deallocation (garbage collection) is more reliable. Use flags and clean up garbage collection mechanisms in post++. There is a special object in the store: the root object. The garbage collector first flags all objects to be accessed by the root object (that is, it can be reached from the root object and traversed by reference). This allows all unmarked objects to be freed 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 invoke the storage::d O_mark_and_sweep () method to invoke the garbage collector while the program is running. However, it is important to make sure that objects that are not pointed to by program variables are not accessible from the root object (these objects will be freed by GC).

Multiple-Inheritance C + + classes can have a non-0 offset in an object and may also have references within the object. This is why we use special techniques to access object headers. The post++ Maintenance page allocates a bitmap in which each bit corresponds to a page in the memory. If some large objects are assigned to several pages, the corresponding bits of the page occupied by all these objects are set to 1 except the first. All other pages have corresponding clear vacancies in the bitmap. To find the object start address, we first arrange the pointer value by page size. Post++ then looks for the start page of the object from the bitmap (the page has 0 digits in it). It then extracts information about the object size from the header of the object contained at the beginning of the page. If the size is greater than half the page size, we've found the object description: It's at the beginning of the page. Instead we calculate the size of the fixed block used in the page and calculate the pointer offset in the page by block size. This head positioning scheme is used by the garbage collector, which defines the operator delete and is used by methods that resolve object size and class information from the object's head.

A special overloaded new method is provided in post++ for object allocation in storage. This method requires creating a class description of the object, creating the memory of the object, and the size of the variable part of the optional object instance as an additional parameter. Macro new_in (STORAGE, CLASS) provides permanent objects to create "syntactic sugars." Permanent objects can be deleted by the redefined operator delete.
Permanent Object Protocol
The classes of all permanent objects in post++ must inherit from the class object defined in Object.h. This class does not contain any variables and provides methods for allocating/releasing objects and for getting class information and size at run time. Class object can be a base class in multiple inheritance (the order of the base class does not matter). Each permanent class must have a constructor for use by the post++ system (see the Describing Object class section). This means that you cannot initialize using a constructor without parameters. If your class constructor does not even have meaningful parameters, you must add a fictitious one to distinguish it from the constructor created by the macro ClassInfo.

In order to access objects in the permanent storage, the programmer needs some kind of root object, through which you can access every other object using a normal C pointer. The post++ storage provides two methods for specifying and obtaining a reference to the root object:

void Set_root_object (object* obj); object* Get_root_object ();

Get_root_object () returns NULL when you create a new store. You need to create the root object through the Set_root_object () method and save the reference in it. The next time you open the store, the root object can be obtained by Get_root_object ().

Tip: In practical applications, classes are often changed during program development and maintenance. Unfortunately, post++ takes into account simple tools that do not provide automatic object conversion (see the Lazy object Update design example in goods), so to avoid adding new fields to the object, I can only suggest that you keep some space in the object for future use. This is especially important for the root object, because it is the preferred person for the new object to join. You also need to avoid converting the root object's references. If no other object contains a reference to the root object, the root object can be simply changed (through the Set_root_object method) to an instance of the new class. post++ storage provides the means to set up and obtain a village publication identity. This identification can be used to update the memory objects based on the memory and the version of the application.


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


File description Use the time suffix the temporary files that contain the new memory image are used to save the new image in non-transactional mode ". tmp" transaction log files are used in transaction mode to save a mirrored page ". Log" Save storage file backup only for Windows-95 to rename temporary files ". Sav"
Another two parameters of the memory constructor have default values. The first parameter max_file_size indicates the storage file extension limit. If the memory file is larger than storage::max_file_size then it will not be cut off but it cannot be extended further. If the max_file_size is larger than the file size, the behavior depends on the mode of opening the memory. In transaction mode, files are mirrored into memory under read-write protection. WINDOWS-NT/95 extended file size to max_file_size. The file size is shortened to the bounds of the last object in the memory by the Storage::close () method. In Windows, you need to have at least storage::max_file_size free bytes on disk to open the storage in read-write mode even if you are not ready to add new objects to it.

The last parameter of the memory constructor is max_locked_objects, which is used only in transaction mode to provide a buffer for the write transaction record file of the mirrored page. In order to provide data consistency post++ must ensure that the modified page is saved in the transaction log file before refreshing to disk. Post++ uses one of two ways: synchronous record writing (max_locked_objects = = 0) and buffer writes in memory for page locking. By locking the page in memory, we can guarantee that it will buffer the money in the transaction record from being swapped to disk. The mirrored page is written asynchronously in the transaction log file (including enabling operating system buffering). When the number of locked pages exceeds max_locked_pages, the record file buffer is flushed to disk and all locked pages are unlocked. This method can significantly improve transaction processing capacity (5 times times Higher in NT). Unfortunately, different operating systems use different methods to lock pages in memory.
Windows 95 is not supported at all. Each process in Windows NT can lock its pages, but the total number of locked pages cannot exceed the process run configuration limit. By default, a process can lock more than 30 pages. If you specify that the Max_locked_pages parameter is greater than 30, then post++ will attempt to extend the process configuration to suit your needs. But from my experience, the performance gap between 30 and 60 locked pages is very small. Only super users can lock pages in memory under UNIX. This is the reason the file constructor checks that the process has sufficient permissions to use the lock operation. So if you specify that the Max_locked_pages parameter is greater than 0, you will decide whether to use synchronous or asynchronous write transaction log files when the storage class is created. If you want to use the memory lock mechanism to bring benefits (2-5 times according to transaction type), you need to change the owner of your application to root and give Set-user-id permission: chmod +s application.

Open Storage
Post++ uses the memory memory mapping mechanism to access data in the file. Data consistency is provided in post++ through two different methods. First and more advanced is the use of the mirroring page based on the transaction mechanism to provide storage recovery and transaction rollback after an error. Creating an operation in front of a write mirror page is used. This operation is performed as follows: All file map pages are set to read-only protection. Any write access to these pages will cause an access violation exception. This exception is caught by a special handle that changes the page protection to read and write the copy of the page in the transaction log file (the combination of the file name and the ". Log"). All subsequent writes of this page will no longer cause page errors. The memory Method commit () refreshes all changes to the disk and truncates the log file. The Storage::commit () method is invoked implicitly by Storage::close (). If the error occurs before the Storage::commit () operation, all changes will be restored by copying the changed page in the transaction record to the stored data file. Also, all changes can be recovered by explicitly invoking the Storage::rollback () method. Select the schema that the file access transaction is based on by specifying the Storage::use_transaction_log property of the Storage::open () method.

Another means of providing data consistency is based on the write-copy mechanism. In this case the source file is not affected. Any attempt to change the file mirroring page results in a copy of the page, which is allocated from the system swap area and has read and write permission. Files are not updated until you explicitly invoke the Storage::flush () method. This method writes the data to the temporary file (with the suffix ". tmp") and renames the original. Thus this operation forms an atomic update of the file (assuming, of course, that the operating system guarantees the number of atoms that rename () operates).

Note: If you do not use transaction processing, the Storage::close () method does not brush the data into the file. So if you have previously called the Storage::flush () method all the changes since the last flush will be lost.

Windows 95 Details: Renaming to an existing file in Windows 95 is not a good thing, so the source file is first saved as a filename with the suffix ". Sav". The temporary file with the suffix ". tmp" is renamed to the original name and the last old copy is deleted. So if the error occurs in the flush () operation and then you can't find the storage file, please don't panic, just find the file that ends with the suffix ". Sav" and rename it to the original.

Tip: If you plan to save data during program execution I strongly recommend that you use transaction processing. You can also use a write-copy approach, but that requires much more consumption. Also, it is generally better to store very large transactions because generating temporary file copies requires a lot of disk space and time.

Here are a few attributes for use by the storage open () method:
Support_virtual_functions You must set this property if the object in the memory has a virtual function. If this property is not set, post++ assumes that all persistent objects contain only references (for other objects in the storage) in the store. It is only necessary to adjust the reference 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 attempts to image the file to the same address to avoid unnecessary reference adjustments). However, if the object class contains virtual functions, the pointer to the virtual table is placed inside the object. If you recompile your application, the address of the target may change. The post++ library compares the timestamp of the execution object against the timestamp of the database produced by the application. If the timestamp is unequal, the pointer to the virtual table is corrected. In order to get the application timestamp post++ must be able to locate the execution file object. Unfortunately, no easy way to execute the filename was found. Under Unix post++ look at the value of the environment variable "_" set by the command line interpreter. However, this method will not work if the process is not executed from the command line (for example, through System ()) or the working directory is chdir (). The easiest way to do this is to use file Comptime.cxx, which must be compiled and linked to the repository each time you recompile your application. Without this problem in Windows, the name of the execution image can be obtained through the Win32 API. post++ comparing this timestamp and data file when the memory is opened, if they are unequal and specify the Support_virtual_functions attribute, then correct all objects (by calling the default constructor). Read_Only by setting this property the programmer explains that he only needs read access to data files. post++ will create a read-only view of the data file and any attempt to change objects in the storage or assign new objects will result in protection violations. Here is an exception: if the data file cannot be imaged to the same address or the application changes and the support_virtual_functions is specified, the protection of the zone is temporarily changed to write copy and the loaded object is converted. Use_transaction_log set this property to force the use of transactions for all data files to be updated. Shadow pages are used to perform transactions. Transactions are opened after the first modification of the store. An explicit shutdown is done by Storage::commit () or Storage::rollback (). Method Storage::commit () saves all changes to the disk and truncates the transaction record, Storage::rollback () ignores thisAll changes in the second transaction. No_file_mapping By default post++ image data files into process virtual memory. In this case, the time to open the database will be greatly reduced because the file page will be Si cho in when required. However, if the database size is not particularly large or if all data in the database requires immediate access, then it is better to read the file into memory than to use the virtual memory image because there is no additional page overflow error in this case. Flag no_file_mapping blocks post++ image files and reads files based on allocated memory segments. Fault_tolerant This flag is used by applications to protect the consistency of the database in the event of a system or application error. If you use a transaction use_transaction_log this flag does not have to be specified, 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 the file into memory (if no no_file_mapping flag is set) or using the Write copy page for protection. In the latter case, an attempt to change the image to a file will result in a page copy being generated in the system interchange file. The flush () method will save the image of an in-memory database to a temporary file and then rename the source file with an atomic operation. If you do not specify the FAULT_TOLERANT flag, post++ modifies the original location on the database page to provide maximum application performance (because there is no copy to modify the page and the extra overhead of saving the database image to the temporary file). When modifying a page without immediately refreshing to disk, part of the change may be lost due to a system error (the worst thing is that the partially modified pages are saved while others are not saved-so the consistency of the database may be messed up). Do_garbage_collection When this property is set post++ will perform a garbage collection when the store is opened. The garbage collection operation and the pointer alignment are linked together. Using garbage collection is often more secure than manual memory release (taking into account a pending reference problem), but explicit memory-release overhead is less expensive. Garbage collection in post++ has a greater advantage over explicit memory allocations: The memory collector optimizes the pages used by small objects. If there are no allocated small objects on the page, then the garbage collector will include this page in the free page. This is not done on an explicit release, because the idle unit of the small object is chained to a chain and cannot be simply removed from the chain (all the chains in the garbage collector are reconstructed). Even if you use explicit memory release, I recommend that you do garbage collection every once in a while to check for referential consistency and no memory leaks (garbage_collection sidemethod returns the number of objects released, and if you are confident that you have released all the unreachable objects, this value will be 0. Considering that the garbage collector modifies all the objects in the store (setting the mask bit), and the attached chain has idle objects, running the GC in transaction mode may be an operation that consumes time and disk space, because pages in all files will be copied to the transaction log file.
You can specify the maximum size of the storage file by using the File::max_file_size variable. If the data file is larger than the file::max_file_size and the schema is not read_only, then bytes other than the virtual space size_of_file-file::max_file_size will be left behind the file image space. When storage size expands (because new objects are allocated), these pages are committed (in Windows NT) and are used. If the file size is larger than file::max_file_size or the READ_ONLY mode is used, the image area is the same size as the file size. Storage extensions are not possible in the latter case. In Windows I use the GlobalMemoryStatus () method to get information about the real-world-configurable virtual memory of the system and to reduce file::max_file_size to that value. Unfortunately, I've found that there are no lightweight calls in Unix that can be used to achieve the same purpose (Getrlimit does not return exact information about the virtual memory that the user process can use).

The interface of object storage is defined in the file storage.h and the implementation part can be seen in Storage.cxx. The part of the image memory file that relies on the operating system is encapsulated in the file class, and its definition is file.h implemented in File.cxx.


Installation of post++
The installation of post++ is very simple. 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, SCO ...). ) There is no problem. Unfortunately, I have not used these systems. Under Windows I compile using Microsoft Visual C + + 5.0 and Borland 5.02 compilers. The Makefiel of Visual C + + is Makefile,broland C + + makefile is makefile.

The only thing you need to use post++ is the function library (under Unix, Libstorage.a is and Storage.lib under Windows). This library can be generated by running the make command. There's a special make. BAT is used in Microsoft Visual C + +, which uses MAKEFILE.MVC as input to invoke NMAKE (if you are using Borland, edit this file or invoke it by make.exe-f MAKEFILE.BCC command).

Installation under Unix can be done by copying the post++ library and the same files 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 for the Install_lib_path is/usr/local/lib Install_inc_path is/usr/local/include. You can compile and link by explicitly specifying the path to the post++ directory to avoid copying files into the system directory.


post++ Class Library
post++ includes definitions of persistent classes that can be used for your application or as a good example of developing post++ classes. You can see that the implementations of those classes don't 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), text Object (Text object). R-tree provides quick access to space objects (objects that contain space equivalents). The text object contains a revision of the Boyer and Moore algorithm, extending to a multiple-style search composed of or/and relationships. The definitions of these classes can be found in the following files:


Description interface implementation arrays of scalars and references, matrixes and Stringsarray.harray.cxxl2-list and Avl-treeavltree.havltree.cxxhash table with Collision Chainshashtab.hhashab.cxxr-tree and quadratic method of nodes Splittingrtree.hrtree.cxxt-tree (combination of AVL tree and array) Ttree.httree.cxxText object with modified Boyer and Moo Re Search algorithmtextobj.htextobj.cxx
In the paper "A Study of index structures for main memory database management systems" T.J. Lehman and M.J Carey proposed to use T-trees as the primary A valid data structure to be stored in a memory database. T-trees based on the AVL tree is proposed by Adelson-velsky and Landis. In this section, we provide an overview of t-trees as an implementation in post++.

Like the AVL tree, the height of the Saozi right subtree of t-tree is not greater than 1. Unlike the AVL tree, each of the T-tree node permutations holds multiple key values rather than a single key value. The leftmost and rightmost key values in a node define the range of key values that are contained within this node. In this way, a node Zuozi only contains a key value that is smaller than the leftmost key value, while the right subtree contains a key value that is larger than the most right key value for the node. The key value that falls between the minimum and maximum key values in a node is called the node constraint (bounded). Note keywords that are equal to the maximum keyword or the minimum keyword can be considered constrained or unconstrained based on whether the index is globally unique and the lookup condition (e.g. "Greater than" ("Greater-than") relative to "greater than equal" ("Greater-than or equal-to").

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

Looking in T-tree is equivalent to finding directly. For each node, check to see if the key value is between the left and right key values of the node, and if this is the case, then the key value in the node is returned (otherwise the key value is not included in the tree). Otherwise, if the key value is smaller than the leftmost key value, look for the left subtree and search for the right subtree instead. Repeat this process until you find the key value or find the null node.

Inserting and deleting in t-tree is slightly more complicated. For the insert operation, first use the search procedure above to find the node where the constraint inserts the key value. If such a node exists, then the key values in the node are inserted into the node. If there is no spare in the node, the key value is inserted into the node, and the leftmost key value of the node is inserted into the China of the node (if the Zoozi tree is empty, a new node is assigned to insert the leftmost key value). If the constraint node is not found, we use N to represent the last encountered node of the search failure and continue as follows: 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 child node/Tree of n based on the key value and the leftmost key value and the most right key value.

Delete key values start with the node that determines the containing key value, and remove the key values from the node. If the key value is removed and an empty leaf node is left, then the node is deleted. If an internal node or incomplete leaf is left with less than the minimum number of keys, the shortfall will be supplemented by moving the largest key value in the left subtree to the node or merging nodes and the right subtree.

Whether inserted or deleted, allocating/releasing nodes may result in tree imbalance and rotation operations (RR, RL, LL, LR). (The following description of the height of the neutron tree includes the effects of insertions and deletions.) In the Insert case, check the node to the root node along the new assignment node until
A node is found to have two equal subtree (in which case there is no need to rotate), or to discover that the Saozi right subtree of a node has a different height greater than 1 and performs a single rotation of the containing node.
In the case of deletion, check the node along the release node to the root node until a node is found with a 1 difference in its subtree height. And each time a node is encountered the height of the subtree is greater than 1 o'clock, a rotation. Note Releasing a node may cause multiple rotations.

There are several test programs to test the classes in the Post++ Persistence class library, which 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 classes with post++
It is possible to save and obtain STL classes from post++ memory. Post++ provides a special STL assignment and overloads the New/delete operator to keep the STL object. There are several models that allow STL persistence to be controlled by the following macros:
Use_microsoft_stl uses the Microsoft STL class, which is shipped with Microsoft Visual C + +. This class library is not fully compatible with the C + + STL standard. Use_std_allocators uses the same allocations as the C + + standard. The allocation child object is contained in the STL object, and the instance method in the allocation child object is used to allocate/free space. So it is possible to execute a "smart" assignment: Only when an object contains this assignment does the allocation of the child allocate space for the object in the post++ memory and the allocation is also placed in memory. Otherwise, the space occupied by the object will be allocated through the normal path of the standard malloc () function. This option can be used with the SGI STL Library and the Microsoft STL library. Note that compliant standard SGI STL allocations use a number of language features that are not widely implemented. In particular, they rely on member templates, local specialization, method templates for local sorting (sorting), typename keywords, and template members that use the template keyword to refer to dependent types. So only a few C + + compilers can compile the SGI STL library when specifying this macro definition. If this macro is not set, then POST provides an assignment with a static member function and all objects are allocated from the post++ memory. Applications that use this assignment can only open one post++ memory at a time. Redefine_default_allocator There are two ways to make STL objects last, one way is to introduce new types:
typedef Basic_string<char, Char_traits<char>, post_alloc<char> > post_string;

Another way is to make all classes have a lasting capability. When a Redefine_default_allocator macro is defined, any STL class can be allocated in post++ memory. In order to create a new object in the persistent memory, you must specify the memory as an additional parameter to the new operator. If the memory is ignored, the object will use the standard malloc () function.

post++ to the STL interface does not require any changes to the STL class, so you can use any STL you want to perform. But as a result, the STL class does not contain the type description so post++ has no format information for the STL object. So post++ is not able to do 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, then if the memory cannot be mirrored to the same memory address post++ will report an error and return false. If your application uses only one memory and does not mirror other objects into virtual memory, then almost all operations can mirror the memory to the same memory address.

The interface post++ to the STL library is defined in the header file post_stl.h. This file must be included in any STL include file. The same macro redefine_default_allocator,use_std_allocators and use_microsoft_stl are defined before post_stl.h.

post++ contains example stltest.cxx using the stl++ class. This example uses two STL classes-string and vector. Lines that are read from the standard input are pressed into the vector and the program is restarted and all vector elements are printed to the standard output. This example is included in the default target for the makefile configured for Microsoft Visual C + +, which uses the Microsoft STL class that is included with VC. You can also try to build this test with a different version of the STL library but don't forget about Redefine_default_allocator and use_std_allocators macros. This example can also be tested with SGI STLport 3.12 and GCC 2.8.11.


Replace the standard Division gametes
In the previous section I explained how to use post++ with the STL library. But there are still a lot of other C + + and C libraries and applications that you want to use, and there are no easy to accommodate allocation mechanisms like STL. The only possible solution in this case (if you do not want to change any of the source code for this library) is to replace the standard allocation mechanism with a post++. This allows any dynamically allocated object to be allocated from the post++ memory (except for a memory that cannot be used in this case).

The files contained in the post++ release package Postnew.cxx redefine the standard malloc,free,realloc and CALLOC functions. When the memory is turned on, all objects are allocated in memory. Otherwise, the SBRK () function is used to allocate objects (the space allocated for these objects is not reclaimed). You may not need to contact these standard C assignment functions and simply overload the default C + + operator new and delete. When compiling postnew.cxx, define DO_NOT_REDEFINE_MALLOC macros to do so. The target files generated from Postnew.cxx must be passed to the linker before the standard C library.

Examples of such use as a post++ can be seen in Testnew.cxx and Testqt.cxx. The first example illustrates how a standard C + + array is persisted. The second example illustrates how post++ works with the QT class library.

post++ No formatting information about the storage class there are some restrictions on the use of post++:


Classes that contain virtual functions are not supported (post++ are not properly initialized to a pointer to a virtual function table). Implicit memory release (garbage collector) is not possible-post++ does not have information about the position of the internal pointer of the object. The memory must always map to the same virtual address because the pointer cannot be adjusted if the base site changes post++.
If all of these limitations are not necessary for your application, you can make it persistent without requiring any code changes. This method can be used in both C and C + + programs.


How to use post++
Here are a few examples of post++ classes and applications. The simplest of these is the game "guessing animals". The algorithm of this game is very simple and the result seems to give a deep impression (some like artificial intelligence). In addition, this game is a very good example of the benefits of persistent object storage. The source code of this game is in the file guess.cxx. Creating this game is included in the default make target. Execute guess to run it.

Unix specific: When you are ready to link your UNIX application to the post++ library and the persistent object contains virtual functions, please do not forget to recompile the Comptime.cxx file and include it in the list of links. This file is required for post++ to provide an executable timestamp and is placed in memory to determine when the application is changed and reinitialize the virtual function table within the object when needed. attention! This file must be recompiled each time you relink your application. I suggest you let the compiler call the linker for you and include the Comptime.cxx source file in the list of object files provided for the run image destination file (makefile).


Debug the post++ Application details
The content of this section makes sense for applications that use transactions. post++ uses the page protection mechanism to provide a shadow page when the source page is modified, and the image of all file pages is read-only protected when the memory is opened or when the transaction is committed. So any attempt to modify the contents of the objects assigned to these pages will result in an access violation exception. This exception is handled by the specified post++ handle. But if you use a debugger, it will first catch the exception and stop the application. If you want to debug your application you have to make some preparations:
In Unix it is sufficient to tell the debugger not to capture the SIGSEGV signal. For example, for GDB it can be done by command: Handle SIGSEGV nostop noprint pass. If the SIGSEGV signal is not generated by a 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 out a SIGABRT signal to its own process, which can be captured by the debugger. The Windows post++ uses an unhandled exception filter (unhandled Exception filter) to process memory page protection violations. Unfortunately, it is not possible for Microsoft Debugger to ignore exceptions. If you are ready to debug your application, you must encapsulate all your program code (main or WinMain function) as a structured exception block. You must always use structured exception handling in Borland C + + because unhandled Exception Filter is not called correctly in Borland. Use two macros Sen_try and Sen_access_violation_handler () to encapsulate the function body of main (or WinMain):
Main () {sen_try {...} Sen_access_violation_handler (); return 0; }

Make sure that the debugger's behavior for this exception is "stop without processing" rather than "always stop" (You can check it in the Debug/exceptions menu). In file testrans.cxx You can find examples of using structured exception handling.
Some more information about post++
post++ is freeware. Develop what she hopes to be useful. Through her you can do whatever you want (there is no limit to the use of post++ in the development product). I will be happy to help you use post++ and get information about any type of post++ (Error report, recommendations ...). )。 Post++ 's free software scenario does not imply a lack of support. I promise to make an effort to correct any errors reported. e-mail support is also provided. Post++ has several uses: Keep information in different periods, save object System, snapshot, information system in file. But if you feel you need to use a more important object-oriented database in your application to provide concurrency, distributed, and transactional processing, visit the goods (Generic Object oriented database System) home page.

Look to new version at my Homepage | E-mail me about bugs and problems


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.