Board index » cppbuilder » Re: read/write semiphores?

Re: read/write semiphores?


2007-03-02 11:09:29 AM
cppbuilder69
"Robert G. Hoover" < XXXX@XXXXX.COM >wrote in
message news:45e797e2$ XXXX@XXXXX.COM ...
Quote
What's the best way to guard against one program writing
to a file when another program is reading the same file?
Open the file with writing access denied to other processes.
LoadFromFile() opens the file with writing access denied. If another
program already has the file open for writing, LoadFromFile() will
fail with an exception thrown. If another program tries to open the
file for writing after LoadFromFile() has it open, the other program
will fail.
SaveToFile() creates the file with exclusive access. If another
program already has the file open for any reason, SaveToFile() will
fail. If another program tries to open the file for any reason after
SaveToFile() has opened the file, the other program will fail.
Quote
I need to make sure that no additions are lost because it
happens at just the wrong time after my first app reads the
file but before my first app saves the revised file.
Then you should re-think your design. Having both programs accessing
the same file at the same time is not a good choice. They need to
communicate with each other so that they can coordinate their access.
Otherwise, you should offload the file access to another dedicated
process that they share so that they do not access the file directly.
Gambit
 
 

Re:Re: read/write semiphores?

Hi,
What's the best way to guard against one program writing to a file when another
program is reading the same file?
In my app, I use TStringList::LoadFromFile() to read in the contents of a
particular file. I manipulate the contents to my liking and then save the file
back to the disk using TStringList::SaveToFile(). In another app, I also read in
the contents of the same file, append additional contents to it, and then save
the amended file to the disk under the same name. I need to make sure that no
additions are lost because it happens at just the wrong time after my first app
reads the file but before my first app saves the revised file. I'm pretty sure I
can use a marker file, but I was hoping for a more elegant method.
Thanks!
Rob
 

Re:Re: read/write semiphores?

"Robert G. Hoover" < XXXX@XXXXX.COM >wrote in message
Quote
Hi,

What's the best way to guard against one program writing to a file when
another
program is reading the same file?

In my app, I use TStringList::LoadFromFile() to read in the contents of a
particular file. I manipulate the contents to my liking and then save the
file
back to the disk using TStringList::SaveToFile(). In another app, I also
read in
the contents of the same file, append additional contents to it, and then
save
the amended file to the disk under the same name. I need to make sure that
no
additions are lost because it happens at just the wrong time after my
first app
reads the file but before my first app saves the revised file. I'm pretty
sure I
can use a marker file, but I was hoping for a more elegant method.
Reading and appending are two separate tasks, and the time between their
invocation is the time during which you don't want to allow reading by your
other app. So, instead of using two separate tasks, you effectively need
one task -- one that will prevent all access to the file beginning at the
time it is opened, and ending only after it has been closed.
Remy suggested that you have the applications communicate with each other to
coordinate access. One way you could do that (as you've already hinted by
your subject line) is to use a named semaphore.
Another way to accomplish the same task without a semaphore would be to let
the file system do the work for you, if you don't mind doing a little
polling. For your read/append process, instead of using TStringList's
ReadFromFile and SaveToFile methods (which is two tasks, separated by some
period of time, during which your other process could lock the file), use a
TFileStream to open and close the file with the appropriate access, and do
your reading and appending with the TFileStream:
1) Open the file with exclusive access (TFileStream *fs = new TFileStream(
filename, fmOpenReadWrite | fmShareExclusive ) )
1a) If the file cannot be opened, the reading process is using it (see
blow). Sleep for a short time (50ms?) and try again until access is
granted.
2) Read the file into the stream (TFileStream::ReadBuffer())
3) Load your stringlist from the stream (TStringList::LoadFromStream())
4) Manipulate your stringlist as necessary
5) Write the stringlist back to the stream (TStringList::SaveToStream())
6) Save the file back to disk (TFileStream::WriteBuffer())
7) Close the file (delete fs)
Then, in your reading process, try to open the file. If it fails to open
(an exception will be thrown), sleep for a short time (say 50ms), then try
again, repeating until the file can be opened (the following snippet is
copied from one of my apps):
while ( true )
{
try
{
pFileStream.reset( new TFileStream( FileName, fmOpenRead |
fmShareExclusive ) );
// if the file can be opened for exclusive access, the writer has
// finished writing to it and closed it; break out of the while
loop
// and allow processing to begin
break;
}
catch(...)
{
// exception will be thrown if the file could not be opened for
// exclusive access; wait a bit and try again
::Sleep( 50 );
}
}
Hope this helps.
- Dennis
 

{smallsort}