🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: borland.public.cppbuilder.nativeapi
Article #2427

Re: read/write semiphores?

#2427
From: Dennis Jones
Date: Fri, 02 Mar 2007 16:33
82 lines
4412 bytes
"Robert G. Hoover" <not.a.real.address@anywhere.sorry> wrote in message 
news:45e797e2$1@newsgroups.borland.com...
> 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 
Technical Details
Message-ID: <45e851b4$1@newsgroups.borland.com>
Path: arc1-ca.pugleaf.net!g2news2.google.com!news1.google.com!news3.google.com!border1.nntp.dca.giganews.com!nntp.giganews.com!newsfeed00.sul.t-online.de!newsfeed01.sul.t-online.de!t-online.de!newsgroups.borland.com!not-for-mail
References: <45e797e2$1@newsgroups.borland.com>

Show Full Headers
Complete Article Headers
X-Google-Thread: 10cc67,425c3313c9d5dcd8
X-Google-Attributes: gid10cc67,public
X-Google-Language: ENGLISH,ASCII-7-bit
From: "Dennis Jones" <nospam@nospam.com>
Newsgroups: borland.public.cppbuilder.nativeapi
References: <45e797e2$1@newsgroups.borland.com>
Subject: Re: read/write semiphores?
Date: Fri, 2 Mar 2007 08:33:06 -0800
Lines: 84
X-Priority: 3
X-MSMail-Priority: Normal
X-Newsreader: Microsoft Outlook Express 6.00.2900.3028
X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2900.3028
X-RFC2646: Format=Flowed; Original
NNTP-Posting-Host: 71.245.109.58
Message-ID: <45e851b4$1@newsgroups.borland.com>
X-Trace: newsgroups.borland.com 1172853172 71.245.109.58 (2 Mar 2007 08:32:52 -0800)
Path: arc1-ca.pugleaf.net!g2news2.google.com!news1.google.com!news3.google.com!border1.nntp.dca.giganews.com!nntp.giganews.com!newsfeed00.sul.t-online.de!newsfeed01.sul.t-online.de!t-online.de!newsgroups.borland.com!not-for-mail