Skip to content

Commit

Permalink
File lock (#4734)
Browse files Browse the repository at this point in the history
* add RWLock implementation for file [posix]

* add implementation FileStreamRWLock for windows
replace FileStreamRWLock to the Process package

* add files FileStreamRWLock* into makefile and vcproj

* remove unnecessary file from makefile

* use absolute path to the TesApp with ProcessRunner

* fix vc*.proj

* add new test files into vc.proj.filters

* fix comments

* fix spelling fo PR #4723
add atomic_bool _locked and check if FileStreamRWLock is locked on
destruction for force unlock

* add atomic header

* File lock (#4740)

* throw error on any errno not only on EDEADLK

* fix function naming

* fix windows build

* fix windows build

---------

Co-authored-by: Alexander B <ale.bychuk@gmail.com>
Co-authored-by: bas524 <bas524@ya.ru>
  • Loading branch information
3 people authored Oct 16, 2024
1 parent 6f34ec8 commit e5752a5
Show file tree
Hide file tree
Showing 18 changed files with 1,141 additions and 8 deletions.
34 changes: 33 additions & 1 deletion Foundation/Foundation_vs160.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -977,6 +977,35 @@
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release_static_mt|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release_static_mt|x64'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="src\FileStreamRWLock.cpp" />
<ClCompile Include="src\FileStreamRWLock_POSIX.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug_shared|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug_shared|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug_static_md|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug_static_md|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug_static_mt|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug_static_mt|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release_shared|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release_shared|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release_static_md|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release_static_md|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release_static_mt|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release_static_mt|x64'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="src\FileStreamRWLock_WIN32.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug_shared|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug_shared|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug_static_md|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug_static_md|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug_static_mt|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug_static_mt|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release_shared|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release_shared|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release_static_md|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release_static_md|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release_static_mt|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release_static_mt|x64'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="src\NamedMutex.cpp" />
<ClCompile Include="src\NamedMutex_UNIX.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug_shared|Win32'">true</ExcludedFromBuild>
Expand Down Expand Up @@ -1613,6 +1642,9 @@
<ClInclude Include="include\Poco\FileStreamFactory.h" />
<ClInclude Include="include\Poco\FileStream_POSIX.h" />
<ClInclude Include="include\Poco\FileStream_WIN32.h" />
<ClInclude Include="include\Poco\FileStreamRWLock.h" />
<ClInclude Include="include\Poco\FileStreamRWLock_POSIX.h" />
<ClInclude Include="include\Poco\FileStreamRWLock_WIN32.h" />
<ClInclude Include="include\Poco\File_UNIX.h" />
<ClInclude Include="include\Poco\File_WIN32U.h" />
<ClInclude Include="include\Poco\Format.h" />
Expand Down Expand Up @@ -1891,4 +1923,4 @@
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets" />
</Project>
</Project>
46 changes: 45 additions & 1 deletion Foundation/Foundation_vs170.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -1415,6 +1415,47 @@
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release_static_mt|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release_static_mt|ARM64'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="src\FileStreamRWLock.cpp" />
<ClCompile Include="src\FileStreamRWLock_POSIX.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug_shared|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug_shared|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug_shared|ARM64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug_static_md|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug_static_md|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug_static_md|ARM64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug_static_mt|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug_static_mt|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug_static_mt|ARM64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release_shared|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release_shared|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release_shared|ARM64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release_static_md|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release_static_md|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release_static_md|ARM64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release_static_mt|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release_static_mt|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release_static_mt|ARM64'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="src\FileStreamRWLock_WIN32.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug_shared|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug_shared|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug_shared|ARM64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug_static_md|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug_static_md|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug_static_md|ARM64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug_static_mt|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug_static_mt|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug_static_mt|ARM64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release_shared|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release_shared|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release_shared|ARM64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release_static_md|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release_static_md|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release_static_md|ARM64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release_static_mt|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release_static_mt|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release_static_mt|ARM64'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="src\NamedMutex.cpp" />
<ClCompile Include="src\NamedMutex_UNIX.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug_shared|Win32'">true</ExcludedFromBuild>
Expand Down Expand Up @@ -2231,6 +2272,9 @@
<ClInclude Include="include\Poco\FileStreamFactory.h" />
<ClInclude Include="include\Poco\FileStream_POSIX.h" />
<ClInclude Include="include\Poco\FileStream_WIN32.h" />
<ClInclude Include="include\Poco\FileStreamRWLock.h" />
<ClInclude Include="include\Poco\FileStreamRWLock_POSIX.h" />
<ClInclude Include="include\Poco\FileStreamRWLock_WIN32.h" />
<ClInclude Include="include\Poco\File_UNIX.h" />
<ClInclude Include="include\Poco\File_WIN32U.h" />
<ClInclude Include="include\Poco\Format.h" />
Expand Down Expand Up @@ -2533,4 +2577,4 @@
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets" />
</Project>
</Project>
2 changes: 1 addition & 1 deletion Foundation/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ objects = ArchiveStrategy Ascii ASCIIEncoding AsyncChannel AsyncNotificationCent
FileStreamFactory URIStreamFactory URIStreamOpener UTF32Encoding UTF16Encoding UTF8Encoding UTF8String \
Unicode UnicodeConverter Windows1250Encoding Windows1251Encoding Windows1252Encoding \
UUID UUIDGenerator Void Var VarHolder VarIterator VarVisitor Format Pipe PipeImpl PipeStream SharedMemory \
MemoryStream FileStream AtomicCounter DataURIStream DataURIStreamFactory
MemoryStream FileStream AtomicCounter DataURIStream DataURIStreamFactory FileStreamRWLock

zlib_objects = adler32 compress crc32 deflate \
infback inffast inflate inftrees trees zutil
Expand Down
204 changes: 204 additions & 0 deletions Foundation/include/Poco/FileStreamRWLock.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,204 @@
//
// FileStreamRWLock.h
//
// Library: Foundation
// Package: Processes
// Module: FileStreamRWLock
//
// Definition of the FileStreamRWLock class.
//
// Copyright (c) 2004-2024, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// SPDX-License-Identifier: BSL-1.0
//


#ifndef Foundation_FileStreamRWLock_INCLUDED
#define Foundation_FileStreamRWLock_INCLUDED


#include "Poco/Foundation.h"
#include "Poco/Exception.h"
#include "Poco/FileStream.h"
#include <atomic>

#if defined(POCO_OS_FAMILY_WINDOWS)
#include "Poco/FileStreamRWLock_WIN32.h"
#else
#include "Poco/FileStreamRWLock_POSIX.h"
#endif


namespace Poco {


class ScopedFStreamRWLock;
class ScopedFStreamReadRWLock;
class ScopedFStreamWriteRWLock;


class Foundation_API FileStreamRWLock: private FileStreamRWLockImpl
/// A reader writer lock on the file region allows multiple concurrent
/// process-readers or one exclusive process-writer.
{
public:
using ScopedLock = ScopedFStreamRWLock;
using ScopedReadLock = ScopedFStreamReadRWLock;
using ScopedWriteLock = ScopedFStreamWriteRWLock;

FileStreamRWLock(const FileStream &fs, Poco::UInt64 offset, Poco::UInt64 size);
/// Creates the Reader/Writer lock on the file region.
/// offset - from start of the file
/// size - size of the locker region

~FileStreamRWLock();
/// Destroys the Reader/Writer lock on the file region.

void readLock();
/// Acquires a read lock. If another process currently holds a write lock,
/// waits until the write lock is released.

bool tryReadLock();
/// Tries to acquire a read lock. Immediately returns true if successful, or
/// false if another process currently holds a write lock.

void writeLock();
/// Acquires a write lock on the file region. If one or more other processes currently hold
/// locks, waits until all locks are released.

bool tryWriteLock();
/// Tries to acquire a write lock on the file region. Immediately returns true if successful,
/// or false if one or more other processes currently hold
/// locks.

void unlock();
/// Releases the read or write lock.

private:
std::atomic_bool _locked = false;
FileStreamRWLock(const FileStreamRWLock&);
FileStreamRWLock& operator = (const FileStreamRWLock&);
};


class Foundation_API ScopedFStreamRWLock
/// A variant of ScopedLock for reader/writer locks.
{
public:
ScopedFStreamRWLock(FileStreamRWLock& rwl, bool write = false);
~ScopedFStreamRWLock();

private:
FileStreamRWLock& _rwl;

ScopedFStreamRWLock();
ScopedFStreamRWLock(const ScopedFStreamRWLock&);
ScopedFStreamRWLock& operator = (const ScopedFStreamRWLock&);
};


class Foundation_API ScopedFStreamReadRWLock : public ScopedFStreamRWLock
/// A variant of ScopedLock for reader locks.
{
public:
ScopedFStreamReadRWLock(FileStreamRWLock& rwl);
~ScopedFStreamReadRWLock();
};


class Foundation_API ScopedFStreamWriteRWLock : public ScopedFStreamRWLock
/// A variant of ScopedLock for writer locks.
{
public:
ScopedFStreamWriteRWLock(FileStreamRWLock& rwl);
~ScopedFStreamWriteRWLock();
};


//
// inlines
//
inline void FileStreamRWLock::readLock()
{
readLockImpl();
_locked = true;
}


inline bool FileStreamRWLock::tryReadLock()
{
bool locked = tryReadLockImpl();
if (locked) _locked = true; // assign only if success lock
return locked;
}


inline void FileStreamRWLock::writeLock()
{
writeLockImpl();
_locked = true;
}


inline bool FileStreamRWLock::tryWriteLock()
{
bool locked = tryWriteLockImpl();
if (locked) _locked = true; // assign only if success lock
return locked;
}


inline void FileStreamRWLock::unlock()
{
unlockImpl();
_locked = false;
}


inline ScopedFStreamRWLock::ScopedFStreamRWLock(FileStreamRWLock& rwl, bool write): _rwl(rwl)
{
if (write)
_rwl.writeLock();
else
_rwl.readLock();
}


inline ScopedFStreamRWLock::~ScopedFStreamRWLock()
{
try
{
_rwl.unlock();
}
catch (...)
{
poco_unexpected();
}
}


inline ScopedFStreamReadRWLock::ScopedFStreamReadRWLock(FileStreamRWLock& rwl): ScopedFStreamRWLock(rwl, false)
{
}


inline ScopedFStreamReadRWLock::~ScopedFStreamReadRWLock()
{
}


inline ScopedFStreamWriteRWLock::ScopedFStreamWriteRWLock(FileStreamRWLock& rwl): ScopedFStreamRWLock(rwl, true)
{
}


inline ScopedFStreamWriteRWLock::~ScopedFStreamWriteRWLock()
{
}


} // namespace Poco


#endif // Foundation_FileStreamRWLock_INCLUDED
Loading

0 comments on commit e5752a5

Please sign in to comment.