Skip to content

Commit

Permalink
Merge pull request #3 from jowillianto/feat/2/moderna-file-lock
Browse files Browse the repository at this point in the history
Feat/2/moderna file lock
  • Loading branch information
jowillianto committed May 31, 2024
2 parents fe51d96 + 03316be commit 0b7bf5a
Show file tree
Hide file tree
Showing 12 changed files with 356 additions and 135 deletions.
8 changes: 2 additions & 6 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
[submodule "lib/test-lib"]
path = lib/test-lib
url = https://github.com/jowillianto/test-lib
[submodule "lib/pybind11"]
[submodule "pybind11"]
path = lib/pybind11
url = ../../pybind/pybind11
branch = stable
url = https://github.com/pybind/pybind11
66 changes: 32 additions & 34 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,67 +1,65 @@
cmake_minimum_required(VERSION 3.28)
project(multiprocessing_file_lock)
project(moderna_file_lock)
set (CMAKE_CXX_STANDARD 23)
set (CMAKE_CXX_STANDARD_REQUIRED true)
set (CMAKE_CXX_SCAN_FOR_MODULES true)

find_package(Python3 3.7 REQUIRED COMPONENTS Interpreter Development)

add_library(multiprocessing_file_lock)
add_library(moderna_file_lock)
file (
GLOB file_lock_ccm
GLOB moderna_file_lock_src
"${CMAKE_CURRENT_LIST_DIR}/src/*.ccm"
)

target_sources(multiprocessing_file_lock
target_sources(moderna_file_lock
PUBLIC
FILE_SET CXX_MODULES FILES ${file_lock_ccm}
FILE_SET CXX_MODULES FILES ${moderna_file_lock_src}
)

# PYTHON TARGET
if (EXISTS ${CMAKE_CURRENT_LIST_DIR}/lib/pybind11/CMakeLists.txt)
add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/lib/pybind11 EXCLUDE_FROM_ALL)
add_library(multiprocessing_file_lock_python SHARED EXCLUDE_FROM_ALL)
target_sources(multiprocessing_file_lock_python
add_library(moderna_file_lock_python SHARED EXCLUDE_FROM_ALL)
target_sources(moderna_file_lock_python
PUBLIC
${CMAKE_CURRENT_LIST_DIR}/python_wrapper/file_lock.cpp
PUBLIC FILE_SET CXX_MODULES FILES ${file_lock_ccm}
PUBLIC FILE_SET CXX_MODULES FILES ${moderna_file_lock_src}
)
target_include_directories(multiprocessing_file_lock_python
target_include_directories(moderna_file_lock_python
PUBLIC
${pybind11_INCLUDE_DIRS}
${Python_INCLUDE_DIRS}
)
target_link_libraries(multiprocessing_file_lock_python
target_link_libraries(moderna_file_lock_python
${pybind11_LIBRARIES}
pybind11::module
)
set_target_properties(multiprocessing_file_lock_python PROPERTIES PREFIX "")
set_target_properties(multiprocessing_file_lock_python PROPERTIES OUTPUT_NAME file_lock)
set_target_properties(multiprocessing_file_lock_python PROPERTIES SUFFIX ".so")
target_compile_options(multiprocessing_file_lock_python PRIVATE "-fPIC")
set_target_properties(moderna_file_lock_python PROPERTIES PREFIX "")
set_target_properties(moderna_file_lock_python PROPERTIES OUTPUT_NAME file_lock)
set_target_properties(moderna_file_lock_python PROPERTIES SUFFIX ".so")
target_compile_options(moderna_file_lock_python PRIVATE "-fPIC")
endif()

# TEST TARGET
if(EXISTS ${CMAKE_CURRENT_LIST_DIR}/lib/test-lib/CMakeLists.txt)
add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/lib/test-lib EXCLUDE_FROM_ALL)
add_executable(multiprocessing_file_lock_test
EXCLUDE_FROM_ALL
${CMAKE_CURRENT_LIST_DIR}/tests/tests.cpp
)
target_link_libraries(multiprocessing_file_lock_test
PRIVATE
test_lib
multiprocessing_file_lock
)
add_executable(multiprocessing_file_lock_test_leak_check
EXCLUDE_FROM_ALL
if(
EXISTS ${CMAKE_CURRENT_LIST_DIR}/../test-lib/CMakeLists.txt
AND EXISTS ${CMAKE_CURRENT_LIST_DIR}/../../cmake/CMakeLists.txt
AND PROJECT_IS_TOP_LEVEL
)
add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/../test-lib test-lib)
add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/../thread_plus thread_plus)
add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/../process process)
include (CTest)
include (${CMAKE_CURRENT_LIST_DIR}/../../cmake/CMakeLists.txt)
add_test_asan_tsan_usan_ubsan (
moderna_file_lock_tests
${CMAKE_CURRENT_LIST_DIR}/tests/tests.cpp
"moderna_file_lock;moderna_test_lib;moderna_thread_plus;moderna_process"
"TEST_CHILD=\"${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/test_child\""
)
target_link_libraries(multiprocessing_file_lock_test_leak_check
PRIVATE
test_lib
multiprocessing_file_lock
)
target_compile_options(multiprocessing_file_lock_test_leak_check PRIVATE "-fsanitize=address")
target_link_options(multiprocessing_file_lock_test_leak_check PRIVATE "-fsanitize=address")
add_executable(test_child ${CMAKE_CURRENT_LIST_DIR}/tests/test_child.cpp)
target_link_libraries(test_child moderna_file_lock)
else()
message("Test with moderna full library")
endif()
1 change: 0 additions & 1 deletion lib/test-lib
Submodule test-lib deleted from 52c2ed
4 changes: 2 additions & 2 deletions python_wrapper/file_lock.cpp
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
#include <pybind11/pybind11.h>
#include <filesystem>
#include <string>
import file_lock;
import moderna.file_lock;
namespace py = pybind11;
class PythonMutex{
file_lock::LargeFileMutex _internal_mutex;
moderna::file_lock::LargeFileMutex _internal_mutex;
std::string _file_path;
public:
PythonMutex(const std::string& file_path) :
Expand Down
2 changes: 1 addition & 1 deletion src/file_lock.ccm
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export module file_lock;
export module moderna.file_lock;
export import :basic_mutex;
export import :large_file_mutex;
export import :shared_mutex;
Expand Down
4 changes: 2 additions & 2 deletions src/file_mutex.ccm
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,12 @@ module;
#include <mutex>
#include <shared_mutex>
#include <unistd.h>
export module file_lock:basic_mutex;
export module moderna.file_lock:basic_mutex;
import :shared_mutex;
import :sys_file_lock;
import :mutex_store;

namespace file_lock {
namespace moderna::file_lock {
static MutexStore mutex_store;
export class FileMutex {
private:
Expand Down
6 changes: 3 additions & 3 deletions src/large_file_mutex.ccm
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
module;
#include <filesystem>
#include <unistd.h>
export module file_lock:large_file_mutex;
export module moderna.file_lock:large_file_mutex;
import :shared_mutex;
import :sys_file_lock;
import :basic_mutex;

namespace file_lock {
namespace moderna::file_lock {
export class LargeFileMutex {
private:
std::filesystem::path _file_path;
Expand All @@ -16,7 +16,7 @@ namespace file_lock {
public:
LargeFileMutex(const std::filesystem::path &file_path) :
_file_path(file_path),
_lock_file_path(file_path.parent_path() / (file_path.stem().string() + ".sys_lock")),
_lock_file_path(file_path.parent_path() / (file_path.filename().string() + ".sys_lock")),
_file_lock(_lock_file_path) {}

void lock() const {
Expand Down
4 changes: 2 additions & 2 deletions src/mutex_store.ccm
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@ module;
#include <mutex>
#include <iterator>
#include <shared_mutex>
export module file_lock:mutex_store;
export module moderna.file_lock:mutex_store;
import :shared_mutex;

namespace file_lock {
namespace moderna::file_lock {
/*
MutexStore stores the shared mutexes used for FileMutex. This allows multiple
threads to access the same shared_mutex given the same ABSOLUTE file path.
Expand Down
4 changes: 2 additions & 2 deletions src/shared_mutex.ccm
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
module;
#include <concepts>
#include <filesystem>
export module file_lock:shared_mutex;
export module moderna.file_lock:shared_mutex;

namespace file_lock {
namespace moderna::file_lock {
export template <typename Mutex>
concept SharedMutex = requires(Mutex m) {
{ m.lock() };
Expand Down
18 changes: 10 additions & 8 deletions src/sys_file_lock.ccm
Original file line number Diff line number Diff line change
Expand Up @@ -4,24 +4,26 @@ module;
#include <sys/resource.h>
#include <sys/stat.h>
#include <filesystem>
#include <source_location>
#include <system_error>
#include <unistd.h>
export module file_lock:sys_file_lock;
export module moderna.file_lock:sys_file_lock;
import :shared_mutex;

namespace file_lock {
namespace moderna::file_lock {
export class SysFileLock {
private:
std::filesystem::path _file_path;
int _fd;

void _throw_sys_error(int err_no) const {
void _throw_sys_error(int err_no, std::source_location loc = std::source_location::current())
const {
throw std::filesystem::filesystem_error{
_file_path, std::error_code{err_no, std::generic_category()}
loc.function_name(), _file_path, std::error_code{err_no, std::generic_category()}
};
}
void _open_file(int additional_flags) {
_fd = open(_file_path.c_str(), O_RDONLY);
_fd = open(_file_path.c_str(), O_RDWR | O_APPEND | O_CLOEXEC);
if (_fd == -1) _throw_sys_error(errno);
}
void _validate_file_path() {
Expand Down Expand Up @@ -69,12 +71,12 @@ namespace file_lock {
int lock_st = flock(_fd, LOCK_SH | LOCK_NB);
return lock_st != -1;
}

/*
Explicitly delete.
*/
SysFileLock& operator = (const SysFileLock& other) = delete;
SysFileLock& operator = (const SysFileLock&& other) = delete;
SysFileLock &operator=(const SysFileLock &other) = delete;
SysFileLock &operator=(const SysFileLock &&other) = delete;

~SysFileLock() {
if (_fd != -1) {
Expand Down
58 changes: 58 additions & 0 deletions tests/test_child.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
#include <string_view>
#include <filesystem>
#include <exception>
#include <mutex>
#include <iostream>
#include <shared_mutex>
import moderna.file_lock;

template<moderna::file_lock::SharedMutex Mut>
void act_or_exit(const Mut& m, std::string_view act_type) {
if (act_type == "test_shared_lockable") {
if (m.try_lock_shared()) {
m.unlock_shared();
exit(0);
}
exit(1);
}
else if (act_type == "test_not_shared_lockable") {
if (m.try_lock_shared()) {
m.unlock_shared();
exit(1);
}
exit(0);
}
else if (act_type == "test_unique_lockable") {
if (m.try_lock()) {
m.unlock();
exit(0);
}
exit(1);
}
else if (act_type == "test_not_unique_lockable") {
if (m.try_lock()) {
m.unlock();
exit(1);
}
exit(0);
}
else
throw std::bad_exception{ };
}

int main(int argc, char** argv) {
if (argc != 4) {
std::cerr<< "Wrong amount of arguments" <<std::endl;
exit(1);
}
std::filesystem::path file_path { argv[1] };
std::string_view mut_type { argv[2] };
std::string_view act_type { argv[3] };
if (mut_type == "lf_mut") {
act_or_exit(moderna::file_lock::LargeFileMutex{ file_path }, act_type);
}
else if (mut_type == "f_mut") {
act_or_exit(moderna::file_lock::FileMutex{ file_path }, act_type);
}
else throw std::bad_exception{};
}
Loading

0 comments on commit 0b7bf5a

Please sign in to comment.