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
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+16
View File
@@ -142,7 +142,12 @@
(putenv "QTWEBENGINE_LOCALES_PATH"
(path->string (build-path os-lib-dir "translations" "qtwebengine_locales")))
(putenv "RKT_WEBVIEW_PRG"
(let ((p
(path->string (build-path os-lib-dir rktwebview-prg)))
)
(displayln p)
p
))
(when (eq? os 'linux)
(putenv "QT_QPA_PLATFORM" "xcb")
(putenv "LD_LIBRARY_PATH"
@@ -222,8 +227,19 @@
eval_js_failed = 3
no_devtools_on_platform = 4
no_delegate_for_context = 5
webview_missing_dependency = 6
webview_canceled = 7
webview_invalid_state = 8
webview_invalid_argument = 9
webview_unspecified = 10
webview_dispatch_failed = 11
move_failed = 12
resize_failed = 13
choose_dir_failed = 14
open_file_failed = 15
save_file_failed = 16
failed = 17
invalid_handle = 18
)
)
)
+1
View File
@@ -21,6 +21,7 @@ add_library(rktwebview SHARED
rkt_protocol.h
rktwebview_types.h
json.cpp json.h
utils.h
)
add_executable(rktwebview_prg
+9 -7
View File
@@ -62,8 +62,10 @@ int main(int argc, char *argv[])
{
const char *me = argv[0];
fprintf(stderr, "%s runs\n", argv[0]);fflush(stderr);
if (argc < 6) {
fprintf(stderr, "%s: wrong number of arguments\n", me);
fprintf(stderr, "%s: wrong number of arguments\n", me);fflush(stderr);
exit(1);
}
@@ -78,11 +80,11 @@ int main(int argc, char *argv[])
int res_slot = atoi(res_slot_str);
int evt_slot = atoi(evt_slot_str);
fprintf(stderr, "%s %s %s %s %s %s\n", me, shm_name, shm_size_str, cmd_slot_str, res_slot_str, evt_slot_str);
fprintf(stderr, "%s %s %ld %d %d %d\n", me, shm_name, shm_size, cmd_slot, res_slot, evt_slot);
fprintf(stderr, "%s %s %s %s %s %s\n", me, shm_name, shm_size_str, cmd_slot_str, res_slot_str, evt_slot_str);fflush(stderr);
fprintf(stderr, "%s %s %ld %d %d %d\n", me, shm_name, shm_size, cmd_slot, res_slot, evt_slot);fflush(stderr);
if (!(shm_size > 0 && cmd_slot > 0 && res_slot > 0 && evt_slot > 0)) {
fprintf(stderr, "%s: Invalid shm size or slots\n", me);
fprintf(stderr, "%s: Invalid shm size or slots\n", me);fflush(stderr);
exit(2);
}
@@ -98,10 +100,10 @@ int main(int argc, char *argv[])
handler->webview_handler->initApp();
handler->webview_handler->execApp();
fprintf(stderr, "waiting for thread to end\n");
fprintf(stderr, "waiting for thread to end\n");fflush(stderr);
handler->wait();
fprintf(stderr, "cleaning up shm\n");
fprintf(stderr, "cleaning up shm\n");fflush(stderr);
delete handler->webview_handler;
delete handler->command_queue;
@@ -318,7 +320,7 @@ void Handler::run()
}
break;
default: {
fprintf(stderr, "Unknown command: %d\n", cmd);
fprintf(stderr, "Unknown command: %d\n", cmd);fflush(stderr);
}
}
}
+102 -22
View File
@@ -2,13 +2,19 @@
#include <chrono>
#include <stdint.h>
#include <string.h>
#ifdef _WIN32
#include <windows.h>
#include <filesystem>
#else
#include <unistd.h>
#include <spawn.h>
#endif
#include <fcntl.h>
#include "rktwebview.h"
#include "rkt_protocol.h"
#include <spawn.h>
#include "shmqueue.h"
#include "json.h"
#include "utils.h"
#define SHM_SIZE (10 * 1024 * 1024) // 10MB
#define COMMAND_SLOT 1
@@ -28,14 +34,26 @@ typedef struct {
ShmQueue *command_queue;
ShmQueue *command_result_queue;
ShmQueue *event_queue;
#ifdef _WIN32
HANDLE rkt_webview_prg_pid;
#else
pid_t rkt_webview_prg_pid;
#endif
bool rkt_webview_prg_started;
bool valid;
} Handle_t;
Handle_t *handler = nullptr;
static bool fileExists(const char *filename) {
#ifdef _WIN32
DWORD dwAttrib = GetFileAttributes(filename);
return (dwAttrib != INVALID_FILE_ATTRIBUTES &&
!(dwAttrib & FILE_ATTRIBUTE_DIRECTORY));
#else
return access(filename, X_OK) != -1;
#endif
}
uint64_t current_ms() {
@@ -45,29 +63,62 @@ uint64_t current_ms() {
bool runRktWebview(Handle_t *handler)
{
// run rktwebview_prg using the environment variable RKT_WEBVIEW_PRG
#ifdef _WIN32
#else
char *rkt_webview_prg_path = getenv("RKT_WEBVIEW_PRG");
if (rkt_webview_prg_path == nullptr) {
fprintf(stderr, "RKT_WEBVIEW_PRG environment variable not set, cannot start webview program\n");
fprintf(stderr, "RKT_WEBVIEW_PRG environment variable not set, cannot start webview program\n");fflush(stderr);
return false;
}
if (!fileExists(rkt_webview_prg_path)) {
fprintf(stderr, "%s does not exist or is not executable\n", rkt_webview_prg_path);
fprintf(stderr, "%s does not exist or is not executable\n", rkt_webview_prg_path);fflush(stderr);
return false;
}
std::string path = basedir(rkt_webview_prg_path);
char shm_size_str[30];
char command_slot[10];
char command_result_slot[10];
char event_slot[10];
sprintf(shm_size_str, "%ld", handler->shm_size);
sprintf(shm_size_str, "%d", static_cast<int>(handler->shm_size));
sprintf(command_slot, "%d", COMMAND_SLOT);
sprintf(command_result_slot, "%d", COMMAND_RESULT_SLOT);
sprintf(event_slot, "%d", EVENT_SLOT);
// run rktwebview_prg using the environment variable RKT_WEBVIEW_PRG
#ifdef _WIN32
//STARTUPINFO si;
//PROCESS_INFORMATION pi;
//ZeroMemory( &si, sizeof(si) );
//si.cb = sizeof(si);
//ZeroMemory( &pi, sizeof(pi) );
std::string cmdargs = std::string("") + handler->name + " " + shm_size_str + " " + command_slot + " " + command_result_slot + " " + event_slot;
std::string exe = std::string(rkt_webview_prg_path);
const char *td = getenv("TEMP");
if (td == nullptr) { td = "C:\\"; }
std::string tmpdir = td;
std::string logfile = tmpdir + "\\" + "rktwebview.log"; //handler->name + ".log";
std::string errfile = tmpdir + "\\" + "rktwebview.err";
std::string redirect = " ^>" + logfile + " 2^>" + errfile;
std::string cmdline = "start /b \"\" cmd /c \"" + exe + " " + cmdargs + " " + /*redirect*/ + "\"" + redirect;
char *cmdline_str = const_cast<char *>(cmdline.c_str());
auto cwd = std::filesystem::current_path();
std::filesystem::current_path(path);
int r = system(cmdline_str);
std::filesystem::current_path(cwd);
//CreateProcessA(NULL, cmdline_str, NULL, NULL, FALSE, NORMAL_PRIORITY_CLASS, NULL, path.c_str(), &si, &pi);
handler->rkt_webview_prg_pid = 0;
if (r != 0) {
fprintf(stderr, "Cannot create process '%s' (error = %ld)\n", cmdline_str, GetLastError());fflush(stderr);
}
return (r == 0);
#else
char *argv[] = { rkt_webview_prg_path, const_cast<char *>(handler->name.c_str()), shm_size_str, command_slot, command_result_slot, event_slot, nullptr };
int r = posix_spawn(&handler->rkt_webview_prg_pid, rkt_webview_prg_path, nullptr, nullptr, argv, environ);
@@ -108,18 +159,21 @@ void rkt_webview_cleanup()
handler = nullptr;
}
*/
fprintf(stderr, "Sending quit message\n");
handler->command_queue->enqueue(CMD_QUIT);
fprintf(stderr, "Message sent\n");
bool stopped = false;
while(!stopped) {
int cmd;
std::string s;
fprintf(stderr, "Getting result of quit message\n");
handler->command_result_queue->dequeue(cmd, s, true);
fprintf(stderr, "got %d\n", cmd);
if (cmd == RESULT_QUIT) {
stopped = true;
if (handler->valid) {
fprintf(stderr, "Sending quit message\n");fflush(stderr);
handler->command_queue->enqueue(CMD_QUIT);
fprintf(stderr, "Message sent\n");fflush(stderr);
bool stopped = false;
while(!stopped) {
int cmd;
std::string s;
fprintf(stderr, "Getting result of quit message\n");fflush(stderr);
handler->command_result_queue->dequeue(cmd, s, true);
fprintf(stderr, "got %d\n", cmd);fflush(stderr);
if (cmd == RESULT_QUIT) {
stopped = true;
}
}
}
@@ -140,16 +194,23 @@ void rkt_webview_init()
char buf[1024];
#ifdef DEBUG
sprintf(buf, "rktwebview-dbg");
#else
#ifdef _WIN32
DWORD p = GetCurrentProcessId();
sprintf(buf, "rktwebview-%ld", p);
#else
pid_t p = getpid();
sprintf(buf, "rktwebview-%x", p);
#endif
#endif
handler = new Handle_t;
handler->valid = true;
handler->name = buf;
handler->shm_size = SHM_SIZE;
handler->shm = new Shm(handler->name.data(), handler->shm_size, true);
if (!handler->shm->isValid()) { handler->valid = false; }
handler->command_queue = new ShmQueue(handler->shm, COMMAND_SLOT, true);
handler->command_result_queue = new ShmQueue(handler->shm, COMMAND_RESULT_SLOT, true);
handler->event_queue = new ShmQueue(handler->shm, EVENT_SLOT, true);
@@ -157,6 +218,7 @@ void rkt_webview_init()
// Start rktwebview_prg application with the right information
#ifndef DEBUG
handler->rkt_webview_prg_started = runRktWebview(handler);
if (!handler->rkt_webview_prg_started) { handler->valid = false; }
#endif
}
}
@@ -164,7 +226,7 @@ void rkt_webview_init()
bool rkt_webview_valid(rktwebview_t wv)
{
rkt_webview_init();
if (handler != nullptr && handler->rkt_webview_prg_started) {
if (handler != nullptr && handler->valid) {
handler->command_queue->enqueue(CMD_HANDLE_IS_VALID);
int result;
std::string json_result;
@@ -175,9 +237,21 @@ bool rkt_webview_valid(rktwebview_t wv)
}
}
static inline bool validHandle()
{
return (handler != nullptr) && handler->valid;
}
#define FAIL_HANDLE if (!validHandle()) { return result_t::invalid_handle; }
#define FAIL_CONTEXT if (!validHandle()) { return 0; }
#define FAIL_WV if (!validHandle()) { return 0; }
#define NOOP_HANDLE if (!validHandle()) { return; }
#define FAIL_CALL_JS if (!validHandle()) { return nullptr; }
rkt_wv_context_t rkt_webview_new_context(const char *boilerplate_js, const char *optional_server_cert_pem)
{
rkt_webview_init();
FAIL_CONTEXT
JSON j;
@@ -200,6 +274,8 @@ rkt_wv_context_t rkt_webview_new_context(const char *boilerplate_js, const char
int rkt_webview_create(rkt_wv_context_t context, rktwebview_t parent)
{
rkt_webview_init();
FAIL_WV
JSON j;
j["context"] = context;
j["parent"] = parent;
@@ -216,6 +292,7 @@ int rkt_webview_create(rkt_wv_context_t context, rktwebview_t parent)
void rkt_webview_close(rktwebview_t wv)
{
rkt_webview_init();
NOOP_HANDLE
JSON j;
j["wv"] = wv;
@@ -224,6 +301,7 @@ void rkt_webview_close(rktwebview_t wv)
#define CMDRES4(cmd, wv, key, val, key2, val2, key3, val3, key4, val4) \
rkt_webview_init(); \
FAIL_HANDLE \
JSON j; \
j["wv"] = wv; \
j[key] = val; \
@@ -268,6 +346,7 @@ result_t rkt_webview_run_js(rktwebview_t wv, const char *js)
rkt_data_t *rkt_webview_call_js(rktwebview_t wv, const char *js)
{
rkt_webview_init();
FAIL_CALL_JS
JSON j;
j["wv"] = wv;
@@ -380,6 +459,7 @@ result_t rkt_webview_file_save(rktwebview_t w, const char *title, const char *ba
void rkt_webview_set_ou_token(rktwebview_t wv, const char *token)
{
rkt_webview_init();
NOOP_HANDLE
JSON j;
j["wv"] = wv;
@@ -401,7 +481,7 @@ void rkt_webview_free_data(rkt_data_t *d)
free(d->data.js_result.value);
free(d);
} else {
fprintf(stderr, "UNEXPECTED: data kind %d cannot be freed\n", d->kind);
fprintf(stderr, "UNEXPECTED: data kind %d cannot be freed\n", d->kind);fflush(stderr);
}
}
@@ -440,7 +520,7 @@ rkt_data_t *rkt_webview_get_event()
memcpy(d->data.event.event, data.c_str(), ds);
d->data.event.event[ds] = '\0';
d->data.event.wv = wv;
fprintf(stderr, "event: %d - '%s'\n", d->data.event.wv, d->data.event.event);
//fprintf(stderr, "event: %d - '%s'\n", d->data.event.wv, d->data.event.event);fflush(stderr);
return d;
} else {
return nullptr;
+3
View File
@@ -31,6 +31,7 @@ void Rktwebview_qt::processCommand(Command *cmd)
switch(cmd->cmd) {
case COMMAND_QUIT: { // Quit application
_app->quit();
cmd->done = true;
}
break;
case COMMAND_NEW_CONTEXT: {
@@ -640,6 +641,8 @@ void Rktwebview_qt::rktQuit()
{
Command c(COMMAND_QUIT);
postCommand(&c);
while(!c.done) { doEvents(); }
}
result_t Rktwebview_qt::fileDlg(rktwebview_t w, const char *title, const char *base, const char *filters,QFileDialog::FileMode mode, QFileDialog::AcceptMode am, QString evt_ok, QString evt_cancel)
+25 -3
View File
@@ -1,16 +1,34 @@
#include "rktwebview.h"
#include <string>
#ifdef _WIN32
#include <windows.h>
#else
#include <unistd.h>
#endif
#include "utils.h"
int main(int argc, char *argv[])
{std::string me = argv[0];
int idx = me.rfind("/");
{
std::string me = argv[0];
std::string loc = me.substr(0, idx);
std::string loc = basedir(me);
#ifdef _WIN32
std::string prg = loc + "\\rktwebview_prg.exe";
SetDllDirectoryA("C:\\Qt\\6.10.2\\msvc2022_64\\bin");
#else
std::string prg = loc + "/rktwebview_prg";
#endif
#ifdef _WIN32
{
std::string e = std::string("RKT_WEBVIEW_PRG=") + prg;
_putenv(e.c_str());
}
#else
setenv("RKT_WEBVIEW_PRG", prg.c_str(), true);
setenv("LD_LIBRARY_PATH", loc.c_str(), true);
#endif
int context = rkt_webview_new_context("", nullptr);
@@ -24,7 +42,11 @@ int main(int argc, char *argv[])
rkt_data_t *d = rkt_webview_get_event();
rkt_webview_free_data(d);
}
#ifdef _WIN32
Sleep(10);
#else
sleep(10);
#endif
rkt_webview_close(wv);
+2 -1
View File
@@ -30,7 +30,8 @@ typedef enum {
choose_dir_failed = 14,
open_file_failed = 15,
save_file_failed = 16,
failed = 17
failed = 17,
invalid_handle = 18
} result_t;
typedef struct {
+306 -91
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;
}
+5 -3
View File
@@ -4,6 +4,7 @@
#include <stdlib.h>
class ShmApi;
class ShmSemApi;
typedef int ShmPlace;
typedef int ShmSlot;
@@ -12,9 +13,7 @@ typedef int ShmSlot;
class ShmSem {
private:
void *_sem;
char *_name;
bool _owner;
ShmSemApi *_api;
public:
void post();
@@ -44,6 +43,9 @@ public:
public:
ShmSem *sem(const char *name, bool owner);
public:
bool isValid();
public:
const char *name();
+29
View File
@@ -0,0 +1,29 @@
#ifndef UTILS_H
#define UTILS_H
#include <string>
inline std::string basedir(const std::string &path)
{
int idx1 = path.rfind("/");
int idx2 = path.rfind("\\");
std::string r;
if (idx1 == std::string::npos && idx2 == std::string::npos) {
r = "";
} else {
int idx;
if (idx1 == std::string::npos) {
idx = idx2;
} else if (idx2 == std::string::npos) {
idx = idx1;
} else if (idx1 < idx2) {
idx = idx2;
} else {
idx = idx1;
}
r = path.substr(0, idx);
}
return r;
}
#endif // UTILS_H