ACE_Pagefile_Memory_Pool Class Reference

Make a memory pool that is based on "anonymous" memory regions allocated from the Win32 page file. More...

#include <Pagefile_Memory_Pool.h>

Collaboration diagram for ACE_Pagefile_Memory_Pool:

Collaboration graph
[legend]
List of all members.

Public Types

typedef ACE_Pagefile_Memory_Pool_Options OPTIONS

Public Member Functions

 ACE_Pagefile_Memory_Pool (const ACE_TCHAR *backing_store_name=0, const OPTIONS *options=0)
 Initialize the pool.

void * init_acquire (size_t nbytes, size_t &rounded_bytes, int &first_time)
 Ask system for initial chunk of shared memory.

void * acquire (size_t nbytes, size_t &rounded_bytes)
int release (int destroy=1)
 Instruct the memory pool to release all of its resources.

virtual int seh_selector (void *)
int remap (void *addr)
size_t round_to_page_size (size_t nbytes)
 Round up to system page size.

size_t round_to_chunk_size (size_t nbytes)
 Round up to the chunk size required by the operation system.

int sync (ssize_t=-1, int=MS_SYNC)
int sync (void *, size_t, int=MS_SYNC)
int protect (ssize_t=-1, int=PROT_RDWR)
int protect (void *, size_t, int=PROT_RDWR)
virtual void * base_addr (void) const
void dump (void) const

Protected Member Functions

int map (int &firstTime, size_t appendBytes=0)
int unmap (void)
 Release the mapping.


Private Attributes

Control_Block local_cb_
 Description of what our process mapped.

Control_Blockshared_cb_
 Shared memory pool statistics.

ACE_HANDLE object_handle_
 File mapping handle.

size_t page_size_
 System page size.

ACE_TCHAR backing_store_name_ [MAXPATHLEN]
 Name of the backing store where the shared memory pool is kept.


Detailed Description

Make a memory pool that is based on "anonymous" memory regions allocated from the Win32 page file.

Definition at line 61 of file Pagefile_Memory_Pool.h.


Member Typedef Documentation

typedef ACE_Pagefile_Memory_Pool_Options ACE_Pagefile_Memory_Pool::OPTIONS
 

Definition at line 64 of file Pagefile_Memory_Pool.h.


Constructor & Destructor Documentation

ACE_Pagefile_Memory_Pool::ACE_Pagefile_Memory_Pool const ACE_TCHAR backing_store_name = 0,
const OPTIONS options = 0
 

Initialize the pool.

Definition at line 50 of file Pagefile_Memory_Pool.cpp.

References ACE_DEFAULT_PAGEFILE_POOL_NAME, ACE_LIB_TEXT, ACE_TCHAR, local_cb_, ACE_Pagefile_Memory_Pool::Control_Block::mapped_base_, page_size_, ACE_Pagefile_Memory_Pool::Control_Block::req_base_, round_to_chunk_size(), ACE_Pagefile_Memory_Pool::Control_Block::sh_, ACE_OS::strcat(), ACE_OS::strlen(), and ACE_OS::strsncpy().

00052   : shared_cb_ (0),
00053     object_handle_ (0),
00054     page_size_ (ACE_Pagefile_Memory_Pool::round_to_page_size (1))
00055 {
00056   // Initialize local copy of pool statistics.
00057   if (options != 0)
00058     {
00059       this->local_cb_.req_base_ = options->base_addr_;
00060       this->local_cb_.mapped_base_ = 0;
00061       this->local_cb_.sh_.max_size_ =
00062         options->max_size_;
00063       this->local_cb_.sh_.mapped_size_ = 0;
00064       this->local_cb_.sh_.free_offset_ =
00065         this->local_cb_.sh_.mapped_size_;
00066       this->local_cb_.sh_.free_size_ = 0;
00067     }
00068   else
00069     {
00070       this->local_cb_.req_base_ = 0;
00071       this->local_cb_.mapped_base_ = 0;
00072       this->local_cb_.sh_.max_size_ =
00073         this->round_to_chunk_size (page_size_) ;
00074       this->local_cb_.sh_.mapped_size_ = 0;
00075       this->local_cb_.sh_.free_offset_ =
00076         this->local_cb_.sh_.mapped_size_;
00077       this->local_cb_.sh_.free_size_ = 0;
00078     }
00079 
00080   int update_backing_store_name = backing_store_name == 0 ? 0 : 1;
00081 
00082   if (backing_store_name == 0)
00083     // Only create a new unique filename for the backing store file if
00084     // the user didn't supply one...
00085     backing_store_name = ACE_DEFAULT_PAGEFILE_POOL_NAME;
00086 
00087   ACE_OS::strsncpy (this->backing_store_name_,
00088                     backing_store_name,
00089                     (sizeof this->backing_store_name_ / sizeof (ACE_TCHAR)));
00090 
00091   if (update_backing_store_name
00092       && ACE_OS::strlen (this->backing_store_name_) < sizeof this->backing_store_name_)
00093       ACE_OS::strcat (this->backing_store_name_,
00094                       ACE_LIB_TEXT ("_"));
00095 }


Member Function Documentation

void * ACE_Pagefile_Memory_Pool::acquire size_t  nbytes,
size_t &  rounded_bytes
 

Acquire at least from the memory pool. is the actual number of bytes allocated.

Definition at line 98 of file Pagefile_Memory_Pool.cpp.

References local_cb_, map(), ACE_Pagefile_Memory_Pool::Control_Block::mapped_base_, round_to_page_size(), ACE_Pagefile_Memory_Pool::Control_Block::sh_, and shared_cb_.

Referenced by init_acquire().

00100 {
00101   rounded_bytes = round_to_page_size (nbytes);
00102   void *result = 0;
00103   int first_time = 0;
00104 
00105   // Check local_cb_ for consistency.  Remap, if extra space is too
00106   // small and/or we didn't map the whole shared memory section
00107   if (this->shared_cb_->sh_.mapped_size_
00108       > this->local_cb_.sh_.mapped_size_
00109       || this->shared_cb_->sh_.free_size_ < rounded_bytes)
00110     {
00111       size_t append = 0;
00112       if (rounded_bytes > this->shared_cb_->sh_.free_size_)
00113         append = rounded_bytes - this->shared_cb_->sh_.free_size_;
00114 
00115       if (this->map (first_time, append) < 0)
00116         return result;
00117     }
00118 
00119   // Get the block from extra space and update shared and local
00120   // control block
00121   if (this->shared_cb_->sh_.free_size_ < rounded_bytes)
00122     return result;
00123 
00124   result = (void *)((char *) this->local_cb_.mapped_base_
00125                     + this->shared_cb_->sh_.free_offset_);
00126   this->shared_cb_->sh_.free_offset_ += rounded_bytes;
00127   this->shared_cb_->sh_.free_size_ -= rounded_bytes;
00128   this->local_cb_.sh_ = this->shared_cb_->sh_;
00129 
00130   return result;
00131 }

virtual void* ACE_Pagefile_Memory_Pool::base_addr void   )  const [virtual]
 

Return the base address of this memory pool, 0 if base_addr never changes.

void ACE_Pagefile_Memory_Pool::dump void   )  const [inline]
 

Definition at line 118 of file Pagefile_Memory_Pool.h.

00118 {}

void * ACE_Pagefile_Memory_Pool::init_acquire size_t  nbytes,
size_t &  rounded_bytes,
int &  first_time
 

Ask system for initial chunk of shared memory.

Definition at line 134 of file Pagefile_Memory_Pool.cpp.

References acquire(), local_cb_, map(), ACE_Pagefile_Memory_Pool::Control_Block::mapped_base_, and round_to_page_size().

00137 {
00138   // Map the shared memory and get information, if we created the
00139   // shared memory.
00140   if (this->map (first_time) < 0)
00141     return 0;
00142 
00143   if (first_time != 0)
00144     // We created the shared memory. So we have to allocate the
00145     // requested memory.
00146     return this->acquire (nbytes, rounded_bytes);
00147   else
00148     // We just mapped the memory and return the base address
00149     return (void *)((char *) this->local_cb_.mapped_base_
00150                     + ACE_Pagefile_Memory_Pool::round_to_page_size
00151                     ((int) sizeof (Control_Block)));
00152 }

int ACE_Pagefile_Memory_Pool::map int &  firstTime,
size_t  appendBytes = 0
[protected]
 

Map portions or the entire pool into the local virtual address space. To do this, we compute the new file_offset of the backing store and commit the memory.

Definition at line 223 of file Pagefile_Memory_Pool.cpp.

References ACE_MAP_FILE, local_cb_, ACE_Pagefile_Memory_Pool::Control_Block::mapped_base_, object_handle_, ACE_Pagefile_Memory_Pool::Control_Block::req_base_, round_to_chunk_size(), round_to_page_size(), ACE_Pagefile_Memory_Pool::Control_Block::sh_, and shared_cb_.

Referenced by acquire(), init_acquire(), and remap().

00225 {
00226   size_t map_size;
00227   void *map_addr;
00228 
00229   // Create file mapping, if not yet done
00230   if (object_handle_ == 0)
00231     {
00232 #if (defined (ACE_HAS_WINNT4) && (ACE_HAS_WINNT4 != 0))
00233       // Allow access by all users.
00234       SECURITY_ATTRIBUTES sa;
00235       SECURITY_DESCRIPTOR sd;
00236       ::InitializeSecurityDescriptor (&sd,
00237                                       SECURITY_DESCRIPTOR_REVISION);
00238       ::SetSecurityDescriptorDacl (&sd,
00239                                    TRUE,
00240                                    0,
00241                                    FALSE);
00242       sa.nLength = sizeof (SECURITY_ATTRIBUTES);
00243       sa.lpSecurityDescriptor = &sd;
00244       sa.bInheritHandle = FALSE;
00245 #endif /* (defined (ACE_HAS_WINNT4) && (ACE_HAS_WINNT4 != 0)) */
00246 
00247       // Get an object handle to the named reserved memory object.
00248       DWORD size_high;
00249       DWORD size_low;
00250 #if defined (ACE_WIN64)
00251       size_high = static_cast<DWORD> (this->local_cb_.sh_.max_size_ >> 32);
00252       size_low  = static_cast<DWORD> (this->local_cb_.sh_.max_size_ & 0xFFFFFFFF);
00253 #else
00254       size_high = 0;
00255       size_low = this->local_cb_.sh_.max_size_;
00256 #endif
00257 
00258       object_handle_ =
00259         ACE_TEXT_CreateFileMapping (INVALID_HANDLE_VALUE,
00260 #if (defined (ACE_HAS_WINNT4) && (ACE_HAS_WINNT4 != 0))
00261                                     &sa,
00262 #else
00263                                     0,
00264 #endif /* (defined (ACE_HAS_WINNT4) && (ACE_HAS_WINNT4 != 0)) */
00265                                     PAGE_READWRITE | SEC_RESERVE,
00266                                     size_high,
00267                                     size_low,
00268                                     this->backing_store_name_);
00269       if (object_handle_ == 0)
00270         return -1;
00271       first_time =
00272         ::GetLastError () == ERROR_ALREADY_EXISTS
00273         ? 0
00274         : 1;
00275     }
00276 
00277   // Do the initial mapping.
00278   if (this->shared_cb_ == 0)
00279     {
00280       // Map a view to the shared memory.  Note: <MapViewOfFile[Ex]>
00281       // does *not* commit the pages!
00282       this->shared_cb_ = (ACE_Pagefile_Memory_Pool::Control_Block *)
00283         ACE_MAP_FILE (this->object_handle_,
00284                       FILE_MAP_WRITE,
00285                       0,
00286                       0,
00287                       this->local_cb_.sh_.max_size_,
00288                       this->local_cb_.req_base_);
00289       if (this->shared_cb_ == 0)
00290         return -1;
00291 
00292       // There was no previous mapping, so we map the first chunk and
00293       // initialize the shared pool statistics.
00294       if (first_time)
00295         {
00296           // 1st block is used to keep shared memory statistics.
00297           map_size =
00298             ACE_Pagefile_Memory_Pool::round_to_chunk_size
00299             (ACE_Pagefile_Memory_Pool::round_to_page_size
00300              ((int) sizeof(Control_Block))
00301              + append_bytes);
00302 
00303           if (::VirtualAlloc ((void *) this->shared_cb_,
00304                               map_size,
00305                               MEM_COMMIT,
00306                               PAGE_READWRITE) == 0)
00307             return -1;
00308 
00309           this->shared_cb_->req_base_ = 0;
00310           this->shared_cb_->mapped_base_ = 0;
00311           this->local_cb_.mapped_base_ = this->shared_cb_;
00312           this->local_cb_.sh_.mapped_size_ = map_size;
00313           this->local_cb_.sh_.free_offset_ =
00314             round_to_page_size ((int) sizeof (Control_Block));
00315           this->local_cb_.sh_.free_size_ =
00316             this->local_cb_.sh_.mapped_size_ -
00317             this->local_cb_.sh_.free_offset_;
00318           this->shared_cb_->sh_ = this->local_cb_.sh_;
00319         }
00320 
00321       // The shared memory exists, so we map the first chunk to the
00322       // base address of the pool to get the shared pool statistics.
00323       else
00324         {
00325           // 1st block is used to keep shared memory statistics.
00326           map_size =
00327             ACE_Pagefile_Memory_Pool::round_to_chunk_size
00328             ((int) sizeof (Control_Block));
00329 
00330           if (::VirtualAlloc ((void *) this->shared_cb_,
00331                               map_size,
00332                               MEM_COMMIT,
00333                               PAGE_READWRITE) == 0)
00334             return -1;
00335           this->local_cb_.mapped_base_ = this->shared_cb_;
00336           this->local_cb_.sh_.mapped_size_ = map_size;
00337         }
00338     }
00339 
00340   // If the shared memory is larger than the part we've already
00341   // committed, we have to remap it.
00342   if (this->shared_cb_->sh_.mapped_size_ >
00343       this->local_cb_.sh_.mapped_size_
00344       || append_bytes > 0)
00345     {
00346       map_size =
00347         (this->shared_cb_->sh_.mapped_size_ -
00348          this->local_cb_.sh_.mapped_size_)
00349         + ACE_Pagefile_Memory_Pool::round_to_chunk_size
00350         (append_bytes);
00351 
00352       map_addr = (void *)((char *) this->shared_cb_ +
00353                           this->local_cb_.sh_.mapped_size_);
00354 
00355       if (::VirtualAlloc (map_addr,
00356                           map_size,
00357                           MEM_COMMIT,
00358                           PAGE_READWRITE) == 0)
00359         return -1;
00360       else if (append_bytes > 0)
00361         {
00362           this->shared_cb_->sh_.mapped_size_ +=
00363             round_to_chunk_size (append_bytes);
00364           this->shared_cb_->sh_.free_size_ =
00365             this->shared_cb_->sh_.mapped_size_ -
00366             this->shared_cb_->sh_.free_offset_;
00367         }
00368     }
00369 
00370   // Update local copy of the shared memory statistics.
00371   this->local_cb_.sh_ =
00372     this->shared_cb_->sh_;
00373 #if (ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1)
00374   ACE_BASED_POINTER_REPOSITORY::instance ()->bind
00375     (this->local_cb_.mapped_base_,
00376      this->local_cb_.sh_.mapped_size_);
00377 #endif /* ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1 */
00378 
00379   return 0;
00380 }

int ACE_Pagefile_Memory_Pool::protect void *  ,
size_t  ,
int  = PROT_RDWR
 

int ACE_Pagefile_Memory_Pool::protect ssize_t  = -1,
int  = PROT_RDWR
 

int ACE_Pagefile_Memory_Pool::release int  destroy = 1  ) 
 

Instruct the memory pool to release all of its resources.

Definition at line 45 of file Pagefile_Memory_Pool.cpp.

References unmap().

00046 {
00047   return this->unmap ();
00048 }

int ACE_Pagefile_Memory_Pool::remap void *  addr  ) 
 

Try to extend the virtual address space so that is now covered by the address mapping. The method succeeds and returns 0 if the backing store has adequate memory to cover this address. Otherwise, it returns -1. This method is typically called by an exception handler for a Win32 structured exception when another process has grown the backing store (and its mapping) and our process now incurs a fault because our mapping isn't in range (yet).

Definition at line 172 of file Pagefile_Memory_Pool.cpp.

References local_cb_, map(), ACE_Pagefile_Memory_Pool::Control_Block::mapped_base_, ACE_Pagefile_Memory_Pool::Control_Block::sh_, and shared_cb_.

Referenced by seh_selector().

00173 {
00174   // If the shared memory is not mapped or the address, that caused
00175   // the memory fault is outside of the commited range of chunks, we
00176   // return.
00177   if (this->shared_cb_ == 0
00178       || addr < this->local_cb_.mapped_base_
00179       || addr >= (void *)((char *) this->local_cb_.mapped_base_
00180                           + this->shared_cb_->sh_.mapped_size_))
00181     return -1;
00182 
00183   // We can solve the problem by committing additional chunks.
00184   int first_time = 0;
00185   return this->map (first_time);
00186 }

size_t ACE_Pagefile_Memory_Pool::round_to_chunk_size size_t  nbytes  ) 
 

Round up to the chunk size required by the operation system.

Referenced by ACE_Pagefile_Memory_Pool(), and map().

size_t ACE_Pagefile_Memory_Pool::round_to_page_size size_t  nbytes  ) 
 

Round up to system page size.

Referenced by acquire(), init_acquire(), and map().

int ACE_Pagefile_Memory_Pool::seh_selector void *   )  [virtual]
 

Win32 Structural exception selector. The return value decides how to handle memory pool related structural exceptions. Returns 1, 0, or , -1.

Definition at line 155 of file Pagefile_Memory_Pool.cpp.

References remap().

00156 {
00157   DWORD ecode = ((EXCEPTION_POINTERS *) ep)->ExceptionRecord->ExceptionCode;
00158 
00159   if (ecode == EXCEPTION_ACCESS_VIOLATION)
00160     {
00161       void * fault_addr = (void *)
00162         ((EXCEPTION_POINTERS *) ep)->ExceptionRecord->ExceptionInformation[1];
00163 
00164       if (this->remap (fault_addr) == 0)
00165         return 1;
00166     }
00167 
00168   return 0;
00169 }

int ACE_Pagefile_Memory_Pool::sync void *  ,
size_t  ,
int  = MS_SYNC
 

int ACE_Pagefile_Memory_Pool::sync ssize_t  = -1,
int  = MS_SYNC
 

int ACE_Pagefile_Memory_Pool::unmap void   )  [protected]
 

Release the mapping.

Definition at line 189 of file Pagefile_Memory_Pool.cpp.

References ACE_DEFAULT_PAGEFILE_POOL_BASE, ACE_DEFAULT_PAGEFILE_POOL_SIZE, local_cb_, ACE_Pagefile_Memory_Pool::Control_Block::mapped_base_, object_handle_, ACE_Pagefile_Memory_Pool::Control_Block::req_base_, ACE_Pagefile_Memory_Pool::Control_Block::sh_, and shared_cb_.

Referenced by release().

00190 {
00191 #if (ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1)
00192   ACE_BASED_POINTER_REPOSITORY::instance ()->unbind
00193     (this->local_cb_.mapped_base_);
00194 #endif /* ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1 */
00195 
00196   // Cleanup cached pool pointer.
00197   this->shared_cb_ = 0;
00198 
00199   if (this->local_cb_.sh_.mapped_size_ > 0)
00200     ::UnmapViewOfFile (this->local_cb_.mapped_base_);
00201 
00202   // Reset local pool statistics.
00203   this->local_cb_.req_base_ =
00204     ACE_DEFAULT_PAGEFILE_POOL_BASE;
00205   this->local_cb_.mapped_base_ = 0;
00206   this->local_cb_.sh_.max_size_ =
00207     ACE_DEFAULT_PAGEFILE_POOL_SIZE;
00208   this->local_cb_.sh_.mapped_size_ = 0;
00209   this->local_cb_.sh_.free_offset_ =
00210     this->local_cb_.sh_.mapped_size_;
00211   this->local_cb_.sh_.free_size_ = 0;
00212 
00213   // Release the pool
00214   if (this->object_handle_ != 0)
00215     {
00216       ::CloseHandle (this->object_handle_);
00217       this->object_handle_ = 0;
00218     }
00219   return 0;
00220 }


Member Data Documentation

ACE_TCHAR ACE_Pagefile_Memory_Pool::backing_store_name_[MAXPATHLEN] [private]
 

Name of the backing store where the shared memory pool is kept.

Definition at line 189 of file Pagefile_Memory_Pool.h.

Control_Block ACE_Pagefile_Memory_Pool::local_cb_ [private]
 

Description of what our process mapped.

Definition at line 177 of file Pagefile_Memory_Pool.h.

Referenced by ACE_Pagefile_Memory_Pool(), acquire(), init_acquire(), map(), remap(), and unmap().

ACE_HANDLE ACE_Pagefile_Memory_Pool::object_handle_ [private]
 

File mapping handle.

Definition at line 183 of file Pagefile_Memory_Pool.h.

Referenced by map(), and unmap().

size_t ACE_Pagefile_Memory_Pool::page_size_ [private]
 

System page size.

Definition at line 186 of file Pagefile_Memory_Pool.h.

Referenced by ACE_Pagefile_Memory_Pool().

Control_Block* ACE_Pagefile_Memory_Pool::shared_cb_ [private]
 

Shared memory pool statistics.

Definition at line 180 of file Pagefile_Memory_Pool.h.

Referenced by acquire(), map(), remap(), and unmap().


The documentation for this class was generated from the following files:
Generated on Thu Nov 9 11:26:18 2006 for ACE by doxygen 1.3.6