windows....sigh

This commit is contained in:
2026-03-26 12:08:55 +01:00
parent 8fe7e726a4
commit b23365b05f
15 changed files with 499 additions and 128 deletions

View File

@@ -1,17 +1,6 @@
#include "shm.h"
#ifdef __linux
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <sys/shm.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <unistd.h>
#include <errno.h>
#include <semaphore.h>
#include <stdio.h>
typedef struct __shm_item__ {
@@ -22,35 +11,26 @@ typedef struct __shm_item__ {
} ShmItem;
class ShmApi
class ShmApiBase
{
private:
int _shm_fd;
size_t _size;
bool _owner;
void *_mem;
sem_t *_sem;
protected:
char *_mem;
char *_mem_name;
char *_sem_name;
size_t *_used;
int *_used;
ShmPlace *_slots;
ShmPlace *_first;
ShmPlace *_free_list;
char *_mem_name;
char *_sem_name;
int _in_critical;
private:
void cleanup() {
// We don't need to do anything here.
}
size_t _size;
bool _owner;
public:
ShmSem *makeSem(const char *name, bool owner) {
return new ShmSem(name, owner);
}
virtual void enterCritical() = 0;
virtual void leaveCritical() = 0;
public:
int slot(int s) {
@@ -71,7 +51,7 @@ public:
if (place == SHM_NULL) {
*p = nullptr;
} else {
*p = reinterpret_cast<T *>(reinterpret_cast<char *>(_mem) + place);
*p = reinterpret_cast<T *>(_mem + place);
}
}
@@ -81,7 +61,7 @@ public:
return nullptr;
}
return reinterpret_cast<char *>(_mem) + place;
return _mem + place;
}
public:
@@ -125,7 +105,7 @@ public:
} else {
ShmPlace p_i = *_used;
i = reinterpret_cast<ShmItem *>(reinterpret_cast<char *>(_mem) + p_i);
size_t u = *_used + sizeof(ShmItem) + bytes;
int u = static_cast<int>(*_used + sizeof(ShmItem) + bytes);
if (u >= _size) {
place = SHM_NULL;
@@ -185,6 +165,66 @@ public:
leaveCritical();
}
public:
ShmSem *makeSem(const char *name, bool owner) {
return new ShmSem(name, owner);
}
public:
ShmApiBase(const char *name, size_t size, bool owner) {
char *buf = reinterpret_cast<char *>(malloc(strlen(name) + 50));
sprintf(buf, "sem_%s", name);
_sem_name = _strdup(buf);
_mem_name = _strdup(name);
::free(buf);
_owner = owner;
_size = size;
_used = nullptr;
_slots = nullptr;
_first = nullptr;
_free_list = nullptr;
_mem = nullptr;
_in_critical = 0;
}
virtual ~ShmApiBase()
{
::free(_sem_name);
::free(_mem_name);
}
};
#ifdef __linux
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <sys/shm.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <unistd.h>
#include <errno.h>
#include <semaphore.h>
class ShmApi : public ShmApiBase
{
private:
int _shm_fd;
sem_t *_sem;
private:
void cleanup() {
// We don't need to do anything here.
}
public:
void enterCritical() {
if (_in_critical > 0) {
_in_critical++;
@@ -204,19 +244,17 @@ public:
}
public:
ShmApi(const char *name, size_t size, bool owner) {
{
char buf[strlen(name) + 50];
sprintf(buf, "sem_%s", name);
_sem_name = strdup(buf);
_mem_name = strdup(name);
}
bool isValid() {
return true;
}
public:
ShmApi(const char *name, size_t size, bool owner) : ShmApiBase(name, size, owner)
{
size_t slots_size = sizeof(ShmPlace) * SHM_MAX_SLOTS;
size += slots_size;
if (owner) {
if (_owner) {
_sem = sem_open(_sem_name, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR, 0);
_shm_fd = shm_open(name, O_CREAT | O_RDWR, 0600);
ftruncate(_shm_fd, size);
@@ -224,21 +262,18 @@ public:
_sem = sem_open(_sem_name, O_RDWR, S_IRUSR | S_IWUSR, 0);
_shm_fd = shm_open(name, O_RDWR, 0600);
}
_size = size;
_mem = mmap(nullptr, _size, PROT_READ|PROT_WRITE, MAP_SHARED, _shm_fd, 0);
_slots = reinterpret_cast <ShmPlace *>(reinterpret_cast<char *>(_mem) + sizeof(size_t) + sizeof(ShmPlace) + sizeof(ShmPlace));
_used = reinterpret_cast<size_t *>(_mem);
_slots = reinterpret_cast <ShmPlace *>(_mem + sizeof(int) + sizeof(ShmPlace) + sizeof(ShmPlace));
_used = reinterpret_cast<int *>(_mem);
_first = reinterpret_cast<ShmPlace *>(reinterpret_cast<char *>(_mem) + sizeof(size_t));
_free_list = reinterpret_cast<ShmPlace *>(reinterpret_cast<char *>(_mem) + sizeof(size_t) + sizeof(ShmPlace));
_owner = owner;
_first = reinterpret_cast<ShmPlace *>(_mem + sizeof(int));
_free_list = reinterpret_cast<ShmPlace *>(_mem + sizeof(int) + sizeof(ShmPlace));
if (_owner) {
*_first = SHM_NULL;
*_free_list = SHM_NULL;
*_used = sizeof(size_t) + sizeof(ShmItem *) + sizeof(ShmItem *) + slots_size;
*_used = sizeof(int) + sizeof(ShmItem *) + sizeof(ShmItem *) + slots_size;
sem_post(_sem);
}
@@ -254,44 +289,241 @@ public:
shm_unlink(_mem_name);
sem_unlink(_sem_name);
}
::free(_mem_name);
::free(_sem_name);
}
};
class ShmSemApi {
private:
sem_t *_sem;
char *_name;
bool _owner;
public:
void post() {
sem_post(_sem);
}
void wait() {
int r = sem_wait(_sem);
if (r != 0) {
fprintf(stderr, "sem_wait error: %d, %s\n", errno, strerror(errno));
}
}
bool trywait() {
int r = sem_trywait(reinterpret_cast<sem_t *>(_sem));
if (r != 0 && r != EAGAIN) {
fprintf(stderr, "sem_wait error: %d, %s\n", errno, strerror(errno));
}
return (r == 0);
}
public:
ShmSemApi(const char *n, bool owner) {
_name = strdup(n);
sem_t *s;
if (owner) {
s = sem_open(n, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR, 0);
} else {
s = sem_open(n, O_RDWR, S_IRUSR | S_IWUSR, 0);
}
_sem = s;
_owner = owner;
}
virtual ~ShmSemApi() {
sem_close(_sem);
if (_owner) {
sem_unlink(_name);
}
free(_name);
}
};
};
public:
};
#endif
#ifdef _WIN32
class ShmApi
#include <windows.h>
class ShmApi : public ShmApiBase
{
private:
HANDLE _shm_handle;
HANDLE _sem_handle;
bool _valid;
public:
ShmApi(const char *name, size_t size, bool owner)
ShmApi(const char *name, size_t size, bool owner) : ShmApiBase(name, size, owner)
{
size_t slots_size = sizeof(ShmPlace) * SHM_MAX_SLOTS;
size += slots_size;
_valid = true;
if (_owner) {
_shm_handle = CreateFileMappingA(INVALID_HANDLE_VALUE,
NULL,
PAGE_READWRITE,
0,
static_cast<DWORD>(size), // size must be smaller < 2GB
name);
if (_shm_handle == NULL) {
fprintf(stderr, "Cannot create shared memory with name %s and size %lld\n", name, size);
_valid = false;
}
} else {
_shm_handle = OpenFileMappingA(FILE_MAP_ALL_ACCESS,
FALSE,
name);
if (_shm_handle == NULL) {
fprintf(stderr, "Cannot open shared memory with name %s\n", name);
_valid = false;
}
}
if (_valid) {
_mem = static_cast<LPSTR>(MapViewOfFile(_shm_handle,
FILE_MAP_ALL_ACCESS,
0,
0,
size));
if (_mem == NULL) {
fprintf(stderr, "Cannot map shared memory, errorcode = %ld\n", GetLastError());
_valid = false;
CloseHandle(_shm_handle);
}
}
if (_valid) {
if (_owner) {
_sem_handle = CreateSemaphoreA(NULL,
1,
10000,
_sem_name
);
} else {
_sem_handle = OpenSemaphoreA(SYNCHRONIZE|SEMAPHORE_MODIFY_STATE, FALSE, _sem_name);
}
if (_sem_handle == NULL) {
fprintf(stderr, "Cannot create or open semaphore with name '%s' (%ld)\n", _sem_name, GetLastError());
UnmapViewOfFile(_mem);
CloseHandle(_shm_handle);
_valid = false;
}
}
if (_valid) {
_slots = reinterpret_cast <ShmPlace *>(_mem + sizeof(int) + sizeof(ShmPlace) + sizeof(ShmPlace));
_used = reinterpret_cast<int *>(_mem);
_first = reinterpret_cast<ShmPlace *>(_mem + sizeof(int));
_free_list = reinterpret_cast<ShmPlace *>(_mem + sizeof(int) + sizeof(ShmPlace));
if (_owner) {
*_first = SHM_NULL;
*_free_list = SHM_NULL;
*_used = sizeof(int) + sizeof(ShmItem *) + sizeof(ShmItem *) + slots_size;
}
}
}
~ShmApi()
{
if (_valid) {
UnmapViewOfFile(_mem);
CloseHandle(_shm_handle);
CloseHandle(_sem_handle);
}
}
bool isValid() {
return _valid;
}
void enterCritical()
{
if (_in_critical > 0) {
_in_critical++;
} else {
WaitForSingleObject(_sem_handle, INFINITE);
_in_critical = 1;
}
}
void leaveCritical()
{
if (_in_critical > 1) {
_in_critical--;
} else {
_in_critical = 0;
ReleaseSemaphore(_sem_handle, 1, NULL);
}
}
void *alloc(size_t bytes)
ShmSem *sem(const char *name, bool owner)
{
return malloc(bytes);
return nullptr;
}
};
class ShmSemApi {
private:
HANDLE _sem;
char *_name;
bool _owner;
public:
void post() {
ReleaseSemaphore(_sem, 1, NULL);
}
void free(void *mem)
{
free(mem);
void wait() {
DWORD r = WaitForSingleObject(_sem, INFINITE);
if (r != WAIT_OBJECT_0) {
fprintf(stderr, "sem_wait error: %ld\n", r);
}
}
}
bool trywait() {
DWORD r = WaitForSingleObject(_sem , 0);
if (r != WAIT_OBJECT_0 && r != WAIT_TIMEOUT) {
fprintf(stderr, "sem_wait error: %ld\n", r);
}
return r == WAIT_OBJECT_0;
}
public:
ShmSemApi(const char *n, bool owner) {
_name = _strdup(n);
if (owner) {
_sem = CreateSemaphoreA(NULL,
0,
10000,
_name);
} else {
_sem = OpenSemaphoreA(SYNCHRONIZE|SEMAPHORE_MODIFY_STATE, FALSE, _name);
}
if (_sem == NULL) {
fprintf(stderr, "Cannot create or open semaphore with name '%s'\n", _name);
}
_owner = owner;
}
virtual ~ShmSemApi() {
if (_sem != NULL) {
CloseHandle(_sem);
}
}
};
#endif
@@ -326,6 +558,11 @@ ShmSem *Shm::sem(const char *name, bool owner)
return _shm_api->makeSem(name, owner);
}
bool Shm::isValid()
{
return _shm_api->isValid();
}
const char *Shm::name()
{
return _shm_api->name();
@@ -352,44 +589,22 @@ Shm::~Shm()
}
void ShmSem::post() {
sem_post(reinterpret_cast<sem_t *>(_sem));
_api->post();
}
void ShmSem::wait() {
int r = sem_wait(reinterpret_cast<sem_t *>(_sem));
if (r != 0) {
fprintf(stderr, "sem_wait error: %d, %s\n", errno, strerror(errno));
}
_api->wait();
}
bool ShmSem::trywait() {
int r = sem_trywait(reinterpret_cast<sem_t *>(_sem));
if (r != 0 && r != EAGAIN) {
fprintf(stderr, "sem_wait error: %d, %s\n", errno, strerror(errno));
}
return (r == 0);
return _api->trywait();
}
ShmSem::ShmSem(const char *n, bool owner) {
_name = strdup(n);
sem_t *s;
if (owner) {
s = sem_open(n, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR, 0);
} else {
s = sem_open(n, O_RDWR, S_IRUSR | S_IWUSR, 0);
}
_sem = reinterpret_cast<void *>(s);
_owner = owner;
_api = new ShmSemApi(n, owner);
}
ShmSem::~ShmSem() {
sem_close(reinterpret_cast<sem_t *>(_sem));
if (_owner) {
sem_unlink(_name);
}
free(_name);
delete _api;
}