source: trunk/Library/SharedMemoryUnit.pas@ 495

Last change on this file since 495 was 394, checked in by RBRi, 9 years ago

+ copyright

  • Property svn:eol-style set to native
File size: 5.0 KB
Line 
1Unit SharedMemoryUnit;
2
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
10Interface
11
12uses
13 BseDos,
14 Semaphores;
15
16type
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
57Implementation
58
59uses
60 OS2Def, BseErr,
61 SysUtils,
62 ACLUtility;
63
64constructor TSharedMemory.Create( const Name: string;
65 const Size: longword );
66var
67 rc: APIRET;
68 szName: cstring;
69begin
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
96end;
97
98destructor TSharedMemory.Destroy;
99begin
100 DosFreeMem( FPointer ); // will free the shared mem once nobody has a ref.
101 inherited Destroy;
102end;
103
104constructor TSuballocatedSharedMemory.Create( const Name: string;
105 const Size: longint;
106 const ReserveSize: longword );
107var
108 rc: APIRET;
109 ActualSize: longword;
110 ActualReserveSize: longword;
111 Flags: ULONG;
112 StartupSemaphore: TMutex;
113begin
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
152end;
153
154destructor TSuballocatedSharedMemory.Destroy;
155begin
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;
162end;
163
164procedure TSuballocatedSharedMemory.Allocate( Var p: pointer;
165 const Size: longword );
166var
167 rc: APIRET;
168begin
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 ) );
178end;
179
180procedure TSuballocatedSharedMemory.Free( Var p: pointer );
181var
182 rc: APIRET;
183 Size: longword;
184begin
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' );
194end;
195
196Initialization
197End.
Note: See TracBrowser for help on using the repository browser.