[17] | 1 | Unit SharedMemoryUnit;
|
---|
| 2 |
|
---|
[394] | 3 | // NewView - a new OS/2 Help Viewer
|
---|
| 4 | // Copyright 2003-2006 Aaron Lawrence
|
---|
| 5 | // Copyright 2006-2009 Ronald Brill (rbri at rbri dot de)
|
---|
| 6 | // This software is released under the GNU Public License - see readme.txt
|
---|
| 7 |
|
---|
| 8 | // Helper functions to work with SharedMemory
|
---|
| 9 |
|
---|
[17] | 10 | Interface
|
---|
| 11 |
|
---|
| 12 | uses
|
---|
[389] | 13 | BseDos,
|
---|
| 14 | Semaphores;
|
---|
[17] | 15 |
|
---|
| 16 | type
|
---|
| 17 | // Encapsulates a basic shared memory block. After creating,
|
---|
| 18 | // the Data pointer can be used to read or write the data
|
---|
| 19 | // in the memory.
|
---|
| 20 | TSharedMemory = class
|
---|
| 21 | protected
|
---|
| 22 | FPointer: pointer;
|
---|
| 23 | FFirst: boolean; // true if this object created the shared mem block
|
---|
| 24 |
|
---|
| 25 | public
|
---|
| 26 | constructor Create( const Name: string;
|
---|
| 27 | const Size: longword );
|
---|
| 28 | destructor Destroy; override;
|
---|
| 29 |
|
---|
| 30 | property Data: pointer read FPointer;
|
---|
| 31 | end;
|
---|
| 32 |
|
---|
| 33 | // Encapsulates a shared memory block which can be suballocated
|
---|
| 34 | // into smaller areas.
|
---|
| 35 | // Allocate and Free are used to allocate these areas.
|
---|
| 36 | // A space can be reserved for using as a normal shared mem block.
|
---|
| 37 | // Otherwise the Data property should not be used.
|
---|
| 38 | TSuballocatedSharedMemory = class( TSharedMemory )
|
---|
| 39 | protected
|
---|
| 40 | FAllocationArea: pointer;
|
---|
| 41 | public
|
---|
| 42 | constructor Create( const Name: string;
|
---|
| 43 | const Size: longint;
|
---|
| 44 | const ReserveSize: longword ); // size to reserve at start of memory
|
---|
| 45 | // for direct access using Data
|
---|
| 46 |
|
---|
| 47 | // suballocate space of the given size
|
---|
| 48 | procedure Allocate( Var p: pointer;
|
---|
| 49 | const Size: longword );
|
---|
| 50 |
|
---|
| 51 | // free the given space.
|
---|
| 52 | procedure Free( Var p: pointer );
|
---|
| 53 |
|
---|
| 54 | destructor Destroy; override;
|
---|
| 55 | end;
|
---|
| 56 |
|
---|
| 57 | Implementation
|
---|
| 58 |
|
---|
| 59 | uses
|
---|
| 60 | OS2Def, BseErr,
|
---|
| 61 | SysUtils,
|
---|
| 62 | ACLUtility;
|
---|
| 63 |
|
---|
| 64 | constructor TSharedMemory.Create( const Name: string;
|
---|
| 65 | const Size: longword );
|
---|
| 66 | var
|
---|
| 67 | rc: APIRET;
|
---|
| 68 | szName: cstring;
|
---|
| 69 | begin
|
---|
| 70 | inherited Create;
|
---|
| 71 |
|
---|
| 72 | FFirst := true;
|
---|
| 73 |
|
---|
| 74 | Assert( Size > 0 );
|
---|
| 75 |
|
---|
| 76 | szName := '\SHAREMEM\' + Name;
|
---|
| 77 | rc := DosAllocSharedMem( FPointer,
|
---|
| 78 | szName,
|
---|
| 79 | Size,
|
---|
| 80 | PAG_READ + PAG_WRITE + PAG_COMMIT );
|
---|
| 81 |
|
---|
| 82 | if rc <> 0 then
|
---|
| 83 | begin
|
---|
| 84 | if rc = ERROR_ALREADY_EXISTS then
|
---|
| 85 | begin
|
---|
| 86 | // memory already exists, just get it
|
---|
| 87 | FFirst := false;
|
---|
| 88 | rc := DosGetNamedSharedMem( FPointer,
|
---|
| 89 | szName,
|
---|
| 90 | PAG_READ + PAG_WRITE );
|
---|
| 91 | end;
|
---|
| 92 |
|
---|
| 93 | CheckSystemError( rc, 'Error getting shared mem' );
|
---|
| 94 | end;
|
---|
| 95 |
|
---|
| 96 | end;
|
---|
| 97 |
|
---|
| 98 | destructor TSharedMemory.Destroy;
|
---|
| 99 | begin
|
---|
| 100 | DosFreeMem( FPointer ); // will free the shared mem once nobody has a ref.
|
---|
| 101 | inherited Destroy;
|
---|
| 102 | end;
|
---|
| 103 |
|
---|
| 104 | constructor TSuballocatedSharedMemory.Create( const Name: string;
|
---|
| 105 | const Size: longint;
|
---|
| 106 | const ReserveSize: longword );
|
---|
| 107 | var
|
---|
| 108 | rc: APIRET;
|
---|
| 109 | ActualSize: longword;
|
---|
| 110 | ActualReserveSize: longword;
|
---|
| 111 | Flags: ULONG;
|
---|
| 112 | StartupSemaphore: TMutex;
|
---|
| 113 | begin
|
---|
| 114 | ActualSize := Size;
|
---|
| 115 | if ActualSize < 256 then
|
---|
| 116 | ActualSize := 256; // make sure the suballoc info will fit.
|
---|
| 117 |
|
---|
| 118 | // Ensure that only one process inits the suballocation
|
---|
| 119 | StartupSemaphore := TMutex.CreateNamed( Name );
|
---|
| 120 | StartupSemaphore.Get;
|
---|
| 121 |
|
---|
| 122 | inherited Create( Name, ActualSize );
|
---|
| 123 |
|
---|
| 124 | // round reserve size up to nearest 8 bytes
|
---|
| 125 | ActualReserveSize := ( ( ReserveSize + 7 ) div 8 ) * 8;
|
---|
| 126 |
|
---|
| 127 | Assert( ActualReserveSize < ActualSize );
|
---|
| 128 |
|
---|
| 129 | if FFirst then
|
---|
| 130 | begin
|
---|
| 131 | // initialise reserved memory
|
---|
| 132 | FillMem( FPointer, ActualReserveSize, 0 );
|
---|
| 133 | end;
|
---|
| 134 |
|
---|
| 135 | FAllocationArea := FPointer + ActualReserveSize;
|
---|
| 136 |
|
---|
| 137 | Flags := DOSSUB_SERIALIZE;
|
---|
| 138 | if FFirst then
|
---|
| 139 | Flags := Flags + DOSSUB_INIT;
|
---|
| 140 | // otherwise just attach
|
---|
| 141 |
|
---|
| 142 | // set up suballocation, with serialisation for multi-process access
|
---|
| 143 | rc := DosSubSetMem( FAllocationArea,
|
---|
| 144 | Flags,
|
---|
| 145 | ActualSize - ReserveSize );
|
---|
| 146 |
|
---|
| 147 | CheckSystemError( rc, 'Error initialising suballocation' );
|
---|
| 148 |
|
---|
| 149 | StartupSemaphore.Release;
|
---|
| 150 | StartupSemaphore.Destroy;
|
---|
| 151 |
|
---|
| 152 | end;
|
---|
| 153 |
|
---|
| 154 | destructor TSuballocatedSharedMemory.Destroy;
|
---|
| 155 | begin
|
---|
| 156 | // DosSubUnsetMem( FAllocationArea );
|
---|
| 157 | // to do this requires manual reference counting
|
---|
| 158 | // it's easy just to not worry and the suballoc stuff
|
---|
| 159 | // will be freed when the shared memory is freed
|
---|
| 160 |
|
---|
| 161 | inherited Destroy;
|
---|
| 162 | end;
|
---|
| 163 |
|
---|
| 164 | procedure TSuballocatedSharedMemory.Allocate( Var p: pointer;
|
---|
| 165 | const Size: longword );
|
---|
| 166 | var
|
---|
| 167 | rc: APIRET;
|
---|
| 168 | begin
|
---|
| 169 | rc := DosSubAllocMem( FAllocationArea,
|
---|
| 170 | p,
|
---|
| 171 | Size + sizeof( longword ) );
|
---|
| 172 |
|
---|
| 173 | CheckSystemError( rc, 'Error suballocating memory' );
|
---|
| 174 |
|
---|
| 175 | // Store size at start of block
|
---|
| 176 | PULONG( p )^ := Size;
|
---|
| 177 | inc( p, sizeof( longword ) );
|
---|
| 178 | end;
|
---|
| 179 |
|
---|
| 180 | procedure TSuballocatedSharedMemory.Free( Var p: pointer );
|
---|
| 181 | var
|
---|
| 182 | rc: APIRET;
|
---|
| 183 | Size: longword;
|
---|
| 184 | begin
|
---|
| 185 | // retrieve size from start of block
|
---|
| 186 | dec( p, sizeof( longword ) );
|
---|
| 187 | Size := PULONG( p )^;
|
---|
| 188 |
|
---|
| 189 | rc := DosSubFreeMem( FAllocationArea,
|
---|
| 190 | p,
|
---|
| 191 | Size );
|
---|
| 192 |
|
---|
| 193 | CheckSystemError( rc, 'Error freeing suballocated memory' );
|
---|
| 194 | end;
|
---|
| 195 |
|
---|
| 196 | Initialization
|
---|
| 197 | End.
|
---|