source: branches/2.20_branch/Library/SharedMemoryUnit.pas

Last change on this file was 200, checked in by RBRi, 18 years ago

small format fix

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