source: branches/2.19.1/Library/SharedMemoryUnit.pas@ 265

Last change on this file since 265 was 17, checked in by RBRi, 19 years ago

+ Library

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