mirror of
https://github.com/MaskRay/ccls.git
synced 2025-02-20 15:40:57 +00:00
Remove platform specific mutex/shared memory
This commit is contained in:
parent
f68e70f5b7
commit
0b53c871dc
@ -94,32 +94,4 @@ TEST_SUITE("Platform") {
|
||||
std::vector<std::string> expected{"a", "b", "c"};
|
||||
REQUIRE(actual == expected);
|
||||
}
|
||||
|
||||
TEST_CASE("Mutex lock/unlock (single process)") {
|
||||
auto m1 = CreatePlatformMutex("indexer-platformmutexttest");
|
||||
auto l1 = CreatePlatformScopedMutexLock(m1.get());
|
||||
auto m2 = CreatePlatformMutex("indexer-platformmutexttest");
|
||||
|
||||
int value = 0;
|
||||
|
||||
volatile bool did_run = false;
|
||||
std::thread t([&]() {
|
||||
did_run = true;
|
||||
auto l2 = CreatePlatformScopedMutexLock(m2.get());
|
||||
value = 1;
|
||||
});
|
||||
while (!did_run)
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
|
||||
// Other thread has had a chance to run, but it should not have
|
||||
// written to value yet (ie, it should be waiting).
|
||||
REQUIRE(value == 0);
|
||||
|
||||
// Release the lock, wait for other thread to finish. Verify it
|
||||
// wrote the expected value.
|
||||
l1.reset();
|
||||
t.join();
|
||||
REQUIRE(value == 1);
|
||||
}
|
||||
}
|
||||
|
@ -19,13 +19,6 @@ struct PlatformSharedMemory {
|
||||
std::string name;
|
||||
};
|
||||
|
||||
std::unique_ptr<PlatformMutex> CreatePlatformMutex(const std::string& name);
|
||||
std::unique_ptr<PlatformScopedMutexLock> CreatePlatformScopedMutexLock(
|
||||
PlatformMutex* mutex);
|
||||
std::unique_ptr<PlatformSharedMemory> CreatePlatformSharedMemory(
|
||||
const std::string& name,
|
||||
size_t size);
|
||||
|
||||
void PlatformInit();
|
||||
|
||||
std::string GetExecutablePath();
|
||||
|
@ -111,107 +111,6 @@ optional<std::string> RealPathNotExpandSymlink(std::string path) {
|
||||
|
||||
} // namespace
|
||||
|
||||
struct PlatformMutexLinux : public PlatformMutex {
|
||||
sem_t* sem_ = nullptr;
|
||||
|
||||
PlatformMutexLinux(const std::string& name) {
|
||||
std::cerr << "PlatformMutexLinux name=" << name << std::endl;
|
||||
sem_ = sem_open(name.c_str(), O_CREAT, 0666 /*permission*/,
|
||||
1 /*initial_value*/);
|
||||
}
|
||||
|
||||
~PlatformMutexLinux() override { sem_close(sem_); }
|
||||
};
|
||||
|
||||
struct PlatformScopedMutexLockLinux : public PlatformScopedMutexLock {
|
||||
sem_t* sem_ = nullptr;
|
||||
|
||||
PlatformScopedMutexLockLinux(sem_t* sem) : sem_(sem) { sem_wait(sem_); }
|
||||
|
||||
~PlatformScopedMutexLockLinux() override { sem_post(sem_); }
|
||||
};
|
||||
|
||||
void* checked(void* result, const char* expr) {
|
||||
if (!result) {
|
||||
std::cerr << "FAIL errno=" << errno << " in |" << expr << "|" << std::endl;
|
||||
std::cerr << "errno => " << strerror(errno) << std::endl;
|
||||
exit(1);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
int checked(int result, const char* expr) {
|
||||
if (result == -1) {
|
||||
std::cerr << "FAIL errno=" << errno << " in |" << expr << "|" << std::endl;
|
||||
std::cerr << "errno => " << strerror(errno) << std::endl;
|
||||
exit(1);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
#define CHECKED(expr) checked(expr, #expr)
|
||||
|
||||
struct PlatformSharedMemoryLinux : public PlatformSharedMemory {
|
||||
std::string name_;
|
||||
size_t size_;
|
||||
int fd_;
|
||||
|
||||
PlatformSharedMemoryLinux(const std::string& name, size_t size)
|
||||
: name_(name), size_(size) {
|
||||
std::cerr << "PlatformSharedMemoryLinux name=" << name << ", size=" << size
|
||||
<< std::endl;
|
||||
|
||||
// Try to create shared memory but only if it does not already exist. Since
|
||||
// we created the memory, we need to initialize it.
|
||||
fd_ = shm_open(name_.c_str(), O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR);
|
||||
if (fd_ >= 0) {
|
||||
std::cerr << "Calling ftruncate fd_=" << fd_ << std::endl;
|
||||
CHECKED(ftruncate(fd_, size));
|
||||
}
|
||||
|
||||
// Otherwise, we just open existing shared memory. We don't need to
|
||||
// create or initialize it.
|
||||
else {
|
||||
fd_ = CHECKED(shm_open(
|
||||
name_.c_str(), O_RDWR, /* memory is read/write, create if needed */
|
||||
S_IRUSR | S_IWUSR /* user read/write */));
|
||||
}
|
||||
|
||||
// Map the shared memory to an address.
|
||||
data = CHECKED(mmap(nullptr /*kernel assigned starting address*/, size,
|
||||
PROT_READ | PROT_WRITE, MAP_SHARED, fd_, 0 /*offset*/));
|
||||
capacity = size;
|
||||
|
||||
std::cerr << "Open shared memory name=" << name << ", fd=" << fd_
|
||||
<< ", shared=" << data << ", capacity=" << capacity << std::endl;
|
||||
}
|
||||
|
||||
~PlatformSharedMemoryLinux() override {
|
||||
CHECKED(munmap(data, size_));
|
||||
CHECKED(shm_unlink(name_.c_str()));
|
||||
|
||||
data = nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
std::unique_ptr<PlatformMutex> CreatePlatformMutex(const std::string& name) {
|
||||
std::string name2 = "/" + name;
|
||||
return MakeUnique<PlatformMutexLinux>(name2);
|
||||
}
|
||||
|
||||
std::unique_ptr<PlatformScopedMutexLock> CreatePlatformScopedMutexLock(
|
||||
PlatformMutex* mutex) {
|
||||
return MakeUnique<PlatformScopedMutexLockLinux>(
|
||||
static_cast<PlatformMutexLinux*>(mutex)->sem_);
|
||||
}
|
||||
|
||||
std::unique_ptr<PlatformSharedMemory> CreatePlatformSharedMemory(
|
||||
const std::string& name,
|
||||
size_t size) {
|
||||
std::string name2 = "/" + name;
|
||||
return MakeUnique<PlatformSharedMemoryLinux>(name2, size);
|
||||
}
|
||||
|
||||
void PlatformInit() {}
|
||||
|
||||
#ifdef __APPLE__
|
||||
@ -357,7 +256,6 @@ bool IsSymLink(const std::string& path) {
|
||||
std::vector<std::string> GetPlatformClangArguments() {
|
||||
return {};
|
||||
}
|
||||
#undef CHECKED
|
||||
|
||||
void FreeUnusedMemory() {
|
||||
#if defined(__linux__)
|
||||
|
@ -18,107 +18,6 @@
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
namespace {
|
||||
|
||||
DWORD CheckForError(std::vector<DWORD> allow) {
|
||||
DWORD error = GetLastError();
|
||||
if (error == ERROR_SUCCESS ||
|
||||
std::find(allow.begin(), allow.end(), error) != allow.end())
|
||||
return error;
|
||||
|
||||
// See http://stackoverflow.com/a/17387176
|
||||
LPSTR message_buffer = nullptr;
|
||||
size_t size = FormatMessageA(
|
||||
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
|
||||
FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||
NULL, error, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
||||
(LPSTR)&message_buffer, 0, NULL);
|
||||
std::string message(message_buffer, size);
|
||||
LocalFree(message_buffer);
|
||||
|
||||
std::cerr << "Windows error code=" << error << ", message=" << message
|
||||
<< std::endl;
|
||||
|
||||
assert(false); // debugger break
|
||||
exit(1);
|
||||
}
|
||||
|
||||
struct PlatformMutexWin : public PlatformMutex {
|
||||
HANDLE raw_mutex = INVALID_HANDLE_VALUE;
|
||||
|
||||
PlatformMutexWin(const std::string& name) {
|
||||
std::cerr << "[win] Creating mutex with name " << name << std::endl;
|
||||
raw_mutex = CreateMutex(nullptr, false /*initial_owner*/, name.c_str());
|
||||
CheckForError({ERROR_ALREADY_EXISTS});
|
||||
}
|
||||
|
||||
~PlatformMutexWin() override {
|
||||
CloseHandle(raw_mutex);
|
||||
CheckForError({} /*allow*/);
|
||||
raw_mutex = INVALID_HANDLE_VALUE;
|
||||
}
|
||||
};
|
||||
|
||||
struct PlatformScopedMutexLockWin : public PlatformScopedMutexLock {
|
||||
HANDLE raw_mutex;
|
||||
|
||||
PlatformScopedMutexLockWin(HANDLE raw_mutex) : raw_mutex(raw_mutex) {
|
||||
DWORD result = WaitForSingleObject(raw_mutex, INFINITE);
|
||||
assert(result == WAIT_OBJECT_0);
|
||||
CheckForError({ERROR_NO_MORE_FILES, ERROR_ALREADY_EXISTS} /*allow*/);
|
||||
}
|
||||
|
||||
~PlatformScopedMutexLockWin() override {
|
||||
ReleaseMutex(raw_mutex);
|
||||
CheckForError({ERROR_NO_MORE_FILES, ERROR_ALREADY_EXISTS} /*allow*/);
|
||||
}
|
||||
};
|
||||
|
||||
struct PlatformSharedMemoryWin : public PlatformSharedMemory {
|
||||
HANDLE shmem_;
|
||||
|
||||
PlatformSharedMemoryWin(const std::string& name, size_t capacity) {
|
||||
std::cerr << "[win] Creating shared memory with name " << name
|
||||
<< " and capacity " << capacity << std::endl;
|
||||
this->name = name;
|
||||
|
||||
shmem_ = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0,
|
||||
(DWORD)capacity, name.c_str());
|
||||
CheckForError({ERROR_ALREADY_EXISTS} /*allow*/);
|
||||
|
||||
data = MapViewOfFile(shmem_, FILE_MAP_ALL_ACCESS, 0, 0, capacity);
|
||||
CheckForError({ERROR_ALREADY_EXISTS} /*allow*/);
|
||||
|
||||
this->capacity = capacity;
|
||||
}
|
||||
|
||||
~PlatformSharedMemoryWin() override {
|
||||
UnmapViewOfFile(data);
|
||||
CheckForError({} /*allow*/);
|
||||
|
||||
data = nullptr;
|
||||
capacity = 0;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
std::unique_ptr<PlatformMutex> CreatePlatformMutex(const std::string& name) {
|
||||
return MakeUnique<PlatformMutexWin>(name);
|
||||
}
|
||||
|
||||
std::unique_ptr<PlatformScopedMutexLock> CreatePlatformScopedMutexLock(
|
||||
PlatformMutex* mutex) {
|
||||
return MakeUnique<PlatformScopedMutexLockWin>(
|
||||
static_cast<PlatformMutexWin*>(mutex)->raw_mutex);
|
||||
}
|
||||
|
||||
std::unique_ptr<PlatformSharedMemory> CreatePlatformSharedMemory(
|
||||
const std::string& name,
|
||||
size_t size) {
|
||||
return MakeUnique<PlatformSharedMemoryWin>(name, size);
|
||||
}
|
||||
|
||||
void PlatformInit() {
|
||||
// We need to write to stdout in binary mode because in Windows, writing
|
||||
// \n will implicitly write \r\n. Language server API will ignore a
|
||||
|
Loading…
Reference in New Issue
Block a user