277 lines
5.9 KiB
C++
277 lines
5.9 KiB
C++
#include "hg_ipc.h"
|
|
#include "../../sdk/hginclude/hg_log.h"
|
|
#include "huagao/hgscanner_error.h"
|
|
|
|
#ifdef WIN32
|
|
#include "scanner_manager.h"
|
|
#else
|
|
#include <string.h>
|
|
#include <sys/types.h>
|
|
#include <unistd.h>
|
|
#endif
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
// windows event ...
|
|
#ifdef WIN32
|
|
int __stdcall sem_init(sem_t* handle, int, int)
|
|
{
|
|
if (!handle)
|
|
{
|
|
errno = EINVAL;
|
|
return -1;
|
|
}
|
|
|
|
*handle = CreateEvent(NULL, TRUE, FALSE, NULL);
|
|
if (*handle)
|
|
return 0;
|
|
else
|
|
{
|
|
errno = GetLastError();
|
|
|
|
return -1;
|
|
}
|
|
}
|
|
void __stdcall sem_destroy(sem_t* handle)
|
|
{
|
|
if (*handle)
|
|
{
|
|
CloseHandle(*handle);
|
|
*handle = NULL;
|
|
}
|
|
}
|
|
int __stdcall sem_trywait(sem_t* handle)
|
|
{
|
|
return WaitForSingleObject(*handle, 1) == WAIT_TIMEOUT ? -1 : 0;
|
|
}
|
|
void __stdcall sem_wait(sem_t* handle)
|
|
{
|
|
if(WaitForSingleObject(*handle, INFINITE) == WAIT_OBJECT_0)
|
|
ResetEvent(*handle);
|
|
}
|
|
int __stdcall sem_timedwait(sem_t* handle, struct timespec* to)
|
|
{
|
|
DWORD elapse = to->tv_sec * 1000;
|
|
elapse += to->tv_nsec / (1000 * 1000);
|
|
|
|
int ret = WaitForSingleObject(*handle, elapse) == WAIT_TIMEOUT ? -1 : 0;
|
|
|
|
if(ret == 0)
|
|
ResetEvent(*handle);
|
|
|
|
return ret;
|
|
}
|
|
void __stdcall sem_post(sem_t* handle)
|
|
{
|
|
SetEvent(*handle);
|
|
}
|
|
|
|
#define pid_t int
|
|
|
|
#endif
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
// platform_event (base on semaphore)
|
|
platform_event::platform_event() : waiting_(false), dbg_info_("")
|
|
{
|
|
int err = sem_init(&sem_, 0, 0);
|
|
|
|
if (err == -1)
|
|
{
|
|
err = errno;
|
|
HG_VLOG_MINI_2(HG_LOG_LEVEL_FATAL, "(%s)sem_init failed: %d\n", hg_log::format_ptr(this).c_str(), err);
|
|
}
|
|
}
|
|
platform_event::~platform_event()
|
|
{
|
|
sem_destroy(&sem_);
|
|
}
|
|
|
|
bool platform_event::try_wait(void)
|
|
{
|
|
return sem_trywait(&sem_) == 0;
|
|
}
|
|
bool platform_event::wait(unsigned timeout)
|
|
{
|
|
bool waited = true;
|
|
|
|
HG_VLOG_MINI_2(HG_LOG_LEVEL_DEBUG_INFO, "platform_event(%s - %s) --> waiting...\n", hg_log::format_ptr(this).c_str(), dbg_info_.c_str());
|
|
waiting_ = true;
|
|
if (timeout == USB_TIMEOUT_INFINITE)
|
|
sem_wait(&sem_);
|
|
else
|
|
{
|
|
struct timespec to;
|
|
to.tv_sec = timeout / 1000;
|
|
to.tv_nsec = (long)((timeout % 1000) * 1000 * 1000);
|
|
waited = sem_timedwait(&sem_, &to) == 0;
|
|
}
|
|
HG_VLOG_MINI_3(HG_LOG_LEVEL_DEBUG_INFO, "platform_event(%s - %s) --> %s.\n", hg_log::format_ptr(this).c_str(), dbg_info_.c_str(), waited ? "waited" : "wait timeout");
|
|
waiting_ = false;
|
|
|
|
return waited;
|
|
}
|
|
void platform_event::notify(void)
|
|
{
|
|
sem_post(&sem_);
|
|
}
|
|
bool platform_event::is_waiting(void)
|
|
{
|
|
return waiting_;
|
|
}
|
|
void platform_event::set_debug_info(const char* info)
|
|
{
|
|
dbg_info_ = info ? info : "";
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
// shared_memory
|
|
shared_memory::shared_memory(unsigned long long key, size_t size) : key_(key), obj_((void*)-1), first_(true), bytes_(size), len_(0)
|
|
{
|
|
unsigned int* ptr = (unsigned int*)&key_;
|
|
HG_VLOG_MINI_2(HG_LOG_LEVEL_DEBUG_INFO, "shared memory key = 0x%x%08x\n", ptr[1], ptr[0]);
|
|
|
|
init();
|
|
}
|
|
shared_memory::~shared_memory()
|
|
{
|
|
clear();
|
|
}
|
|
|
|
void shared_memory::init(void)
|
|
{
|
|
#ifdef WIN32
|
|
char name[40] = { 0 };
|
|
DWORD* key = (DWORD*)&key_;
|
|
HANDLE h = NULL;
|
|
|
|
sprintf(name, "scanner_0x%08x-%08x", key[1], key[0]);
|
|
h = CreateFileMappingA(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, bytes_, name);
|
|
if (h == NULL)
|
|
return;
|
|
|
|
first_ = !(GetLastError() == ERROR_ALREADY_EXISTS);
|
|
obj_ = (void*)h;
|
|
#else
|
|
int obj = shmget(key_, bytes_, IPC_EXCL | IPC_CREAT | 0600);
|
|
if (obj < 0)
|
|
{
|
|
if (errno == EEXIST)
|
|
{
|
|
first_ = false;
|
|
obj = shmget(key_, bytes_, 0600);
|
|
if(read().empty())
|
|
{
|
|
first_ = true;
|
|
clear();
|
|
obj = shmget(key_, bytes_, IPC_EXCL | IPC_CREAT | 0600);
|
|
HG_VLOG_MINI_1(HG_LOG_LEVEL_DEBUG_INFO, "shared memory id(%d) already exists but is not accessible, close and reopen it\n", obj);
|
|
}
|
|
}
|
|
else
|
|
return;
|
|
}
|
|
obj_ = (void*)obj;
|
|
HG_VLOG_MINI_2(HG_LOG_LEVEL_DEBUG_INFO, "shared memory id = %d[%s], \n", obj, first_ ? "created" : "opened");
|
|
#endif
|
|
|
|
if(first_)
|
|
{
|
|
pid_t pid = getpid();
|
|
std::string me("");
|
|
char buf[40] = { 0 };
|
|
unsigned int* pn = (unsigned int*)&pid;
|
|
|
|
if (sizeof(pid) > 4 && pn[1])
|
|
sprintf(buf, "(pid: 0x%x%08x)", pn[1], pn[0]);
|
|
else
|
|
sprintf(buf, "(pid: %u)", pn[0]);
|
|
hg_log::pe_path(&me);
|
|
me += buf;
|
|
write(me.c_str(), me.length());
|
|
}
|
|
}
|
|
void shared_memory::clear(void)
|
|
{
|
|
if (obj_ != (void*)-1)
|
|
#ifdef WIN32
|
|
CloseHandle((HANDLE)obj_);
|
|
#else
|
|
{
|
|
if (first_)
|
|
{
|
|
struct shmid_ds ds = { 0 };
|
|
int* h = (int*)&obj_;
|
|
shmctl(*h, IPC_RMID, &ds);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
obj_ = (void*)-1;
|
|
}
|
|
char* shared_memory::get_buf(void)
|
|
{
|
|
#ifdef WIN32
|
|
char* buf = (char*)MapViewOfFile((HANDLE)obj_, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0);
|
|
if (!buf)
|
|
buf = (char*)-1;
|
|
#else
|
|
int* h = (int*)&obj_;
|
|
char* buf = (char*)shmat(*h, 0, 0);
|
|
HG_VLOG_MINI_3(HG_LOG_LEVEL_DEBUG_INFO, "shared memory %d buffer = %s, error = %d\n", *h, hg_log::format_ptr(buf).c_str(), errno);
|
|
#endif
|
|
|
|
return buf;
|
|
}
|
|
void shared_memory::release_buf(void* buf)
|
|
{
|
|
#ifdef WIN32
|
|
UnmapViewOfFile(buf);
|
|
#else
|
|
shmdt(buf);
|
|
#endif
|
|
}
|
|
|
|
bool shared_memory::is_ok(void)
|
|
{
|
|
return obj_ != nullptr;
|
|
}
|
|
bool shared_memory::is_first(void)
|
|
{
|
|
return is_ok() && first_;
|
|
}
|
|
std::string shared_memory::read(void)
|
|
{
|
|
if (obj_ == (void*)-1)
|
|
return "";
|
|
|
|
char* buf = get_buf();
|
|
if (buf == (char*)-1)
|
|
return "";
|
|
|
|
std::string ret("");
|
|
size_t len = 0;
|
|
int off = sizeof(size_t);
|
|
|
|
memcpy(&len, buf, off);
|
|
ret = std::string(buf + off, len);
|
|
release_buf(buf);
|
|
|
|
return ret;
|
|
}
|
|
int shared_memory::write(const char* data, size_t len)
|
|
{
|
|
if (len > bytes_)
|
|
return HG_ERR_INSUFFICIENT_MEMORY;
|
|
|
|
char* buf = get_buf();
|
|
int off = sizeof(len);
|
|
if (buf == (char*)-1)
|
|
return errno;
|
|
|
|
memcpy(buf, &len, off);
|
|
memcpy(buf + off, data, len);
|
|
len_ = len;
|
|
release_buf(buf);
|
|
}
|