mirror of
https://github.com/mutouyun/cpp-ipc.git
synced 2025-12-06 16:56:45 +08:00
Testing with threads instead of processes under Windows.
This commit is contained in:
parent
8c643308dd
commit
264608b621
@ -21,7 +21,6 @@ A high-performance inter-process communication using shared memory on Linux/Wind
|
||||
- [ ] IPC:实现基本组件
|
||||
- [x] 共享内存(需要作为后续组件的基础)
|
||||
- [x] 原子锁
|
||||
- [ ] 进程对象
|
||||
- [ ] 互斥量
|
||||
- [ ] 条件变量
|
||||
- [ ] 信号量
|
||||
|
||||
@ -5,6 +5,14 @@ if(NOT MSVC)
|
||||
-Wno-attributes)
|
||||
endif()
|
||||
|
||||
# if(CMAKE_SYSTEM_NAME MATCHES "Windows")
|
||||
# FetchContent_Declare(phnt
|
||||
# GIT_REPOSITORY https://github.com/winsiderss/phnt.git
|
||||
# GIT_TAG master
|
||||
# )
|
||||
# FetchContent_MakeAvailable(phnt)
|
||||
# endif()
|
||||
|
||||
aux_source_directory(${LIBIPC_PROJECT_DIR}/src/libipc SRC_FILES)
|
||||
|
||||
file(GLOB HEAD_FILES
|
||||
@ -47,6 +55,10 @@ else()
|
||||
target_link_libraries(${PROJECT_NAME} PUBLIC imp pmr)
|
||||
endif()
|
||||
|
||||
# if(CMAKE_SYSTEM_NAME MATCHES "Windows")
|
||||
# target_link_libraries(${PROJECT_NAME} PUBLIC phnt)
|
||||
# endif()
|
||||
|
||||
install(
|
||||
TARGETS ${PROJECT_NAME}
|
||||
RUNTIME DESTINATION bin
|
||||
|
||||
71
src/libipc/platform/win/process_impl.h
Normal file
71
src/libipc/platform/win/process_impl.h
Normal file
@ -0,0 +1,71 @@
|
||||
/**
|
||||
* \file libipc/platform/win/process_impl.h
|
||||
* \author mutouyun (orz@orzz.org)
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <phnt_windows.h>
|
||||
#include <phnt.h>
|
||||
|
||||
#include "libimp/log.h"
|
||||
#include "libipc/process.h"
|
||||
|
||||
LIBIPC_NAMESPACE_BEG_
|
||||
using namespace ::LIBIMP;
|
||||
|
||||
/// \brief Experimental fork() on Windows.
|
||||
/// \see https://gist.github.com/Cr4sh/126d844c28a7fbfd25c6
|
||||
/// https://github.com/huntandhackett/process-cloning
|
||||
namespace {
|
||||
|
||||
typedef SSIZE_T pid_t;
|
||||
|
||||
pid_t fork() {
|
||||
LIBIMP_LOG_();
|
||||
|
||||
RTL_USER_PROCESS_INFORMATION process_info;
|
||||
NTSTATUS status;
|
||||
|
||||
/* lets do this */
|
||||
status = RtlCloneUserProcess(RTL_CLONE_PROCESS_FLAGS_INHERIT_HANDLES
|
||||
, NULL, NULL, NULL, &process_info);
|
||||
if (status == STATUS_PROCESS_CLONED) {
|
||||
// Executing inside the clone...
|
||||
// Re-attach to the parent's console to be able to write to it
|
||||
FreeConsole();
|
||||
AttachConsole(ATTACH_PARENT_PROCESS);
|
||||
return 0;
|
||||
} else {
|
||||
// Executing inside the original (parent) process...
|
||||
if (!NT_SUCCESS(status)) {
|
||||
log.error("failed: RtlCloneUserProcess(...)");
|
||||
return -1;
|
||||
}
|
||||
return (pid_t)process_info.ProcessHandle;
|
||||
}
|
||||
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
#define WNOHANG 1 /* Don't block waiting. */
|
||||
|
||||
/// \see https://man7.org/linux/man-pages/man3/wait.3p.html
|
||||
/// https://learn.microsoft.com/en-us/windows/win32/api/winternl/nf-winternl-ntwaitforsingleobject
|
||||
pid_t waitpid(pid_t pid, int */*status*/, int options) {
|
||||
LIBIMP_LOG_();
|
||||
if (pid == -1) {
|
||||
return -1;
|
||||
}
|
||||
if (options & WNOHANG) {
|
||||
return pid;
|
||||
}
|
||||
NTSTATUS status = NtWaitForSingleObject((HANDLE)pid, FALSE, NULL);
|
||||
if (!NT_SUCCESS(status)) {
|
||||
log.error("failed: NtWaitForSingleObject(...)");
|
||||
return -1;
|
||||
}
|
||||
return pid;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
LIBIPC_NAMESPACE_END_
|
||||
@ -3,6 +3,8 @@
|
||||
|
||||
#include "libipc/shm.h"
|
||||
|
||||
#include "test_util.h"
|
||||
|
||||
TEST(shm, open_close) {
|
||||
EXPECT_FALSE(ipc::shm_open("hello-ipc-shm", 1024, ipc::mode::none));
|
||||
|
||||
@ -76,6 +78,22 @@ TEST(shm, shared_memory) {
|
||||
EXPECT_TRUE(ipc::shm_close(*shm_r));
|
||||
}
|
||||
|
||||
TEST(shm, process) {
|
||||
ipc::shared_memory shm{"ipc-shared-memory-process1", 333};
|
||||
ASSERT_TRUE(shm.valid());
|
||||
*shm.as<int>() = 4321;
|
||||
|
||||
auto r1 = test::subproc([] {
|
||||
ipc::shared_memory shm{"ipc-shared-memory-process1"};
|
||||
ASSERT_TRUE(shm.valid());
|
||||
EXPECT_EQ(*shm.as<int>(), 4321);
|
||||
*shm.as<int>() = 1234;
|
||||
});
|
||||
|
||||
test::join_subproc(r1);
|
||||
EXPECT_EQ(*shm.as<int>(), 1234);
|
||||
}
|
||||
|
||||
#include <libimp/detect_plat.h>
|
||||
#if /*defined(LIBIMP_OS_LINUX)*/ 0
|
||||
#include <sys/socket.h>
|
||||
@ -87,8 +105,6 @@ TEST(shm, shared_memory) {
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include "test_util.h"
|
||||
|
||||
TEST(shm, pipe) {
|
||||
auto writer = test::subproc([] {
|
||||
mkfifo("/tmp/shm-pipe.w", S_IFIFO|0666);
|
||||
|
||||
@ -6,7 +6,9 @@
|
||||
# include <sys/wait.h>
|
||||
# include <unistd.h>
|
||||
#else
|
||||
# define pid_t int
|
||||
# include <Windows.h>
|
||||
# include <process.h>
|
||||
# define pid_t uintptr_t
|
||||
#endif
|
||||
|
||||
#include <condition_variable>
|
||||
@ -15,7 +17,7 @@
|
||||
namespace test {
|
||||
|
||||
template <typename Fn>
|
||||
pid_t subproc(Fn&& fn) {
|
||||
pid_t subproc(Fn &&fn) {
|
||||
#ifndef LIBIMP_OS_WIN
|
||||
pid_t pid = fork();
|
||||
if (pid == -1) {
|
||||
@ -31,14 +33,23 @@ pid_t subproc(Fn&& fn) {
|
||||
}
|
||||
return pid;
|
||||
#else
|
||||
return -1;
|
||||
auto runner = [](void* pparam) {
|
||||
auto fn = reinterpret_cast<std::decay_t<Fn> *>(pparam);
|
||||
(*fn)();
|
||||
};
|
||||
return _beginthread(runner, 0, (void *)&fn);
|
||||
#endif
|
||||
}
|
||||
|
||||
inline void join_subproc(pid_t pid) {
|
||||
if (pid == -1) return;
|
||||
#ifndef LIBIMP_OS_WIN
|
||||
int ret_code;
|
||||
waitpid(pid, &ret_code, 0);
|
||||
#else
|
||||
HANDLE hThread = reinterpret_cast<HANDLE>(pid);
|
||||
WaitForSingleObject(hThread, INFINITE);
|
||||
CloseHandle(hThread);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user