-
This commit is contained in:
@@ -10,13 +10,14 @@
|
||||
#include <sys/stat.h>
|
||||
#include <sys/mman.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <semaphore.h>
|
||||
|
||||
typedef struct __shm_item__ {
|
||||
|
||||
struct __shm_item__ *next;
|
||||
struct __shm_item__ *prev;
|
||||
size_t size;
|
||||
ShmPlace next;
|
||||
ShmPlace prev;
|
||||
size_t size;
|
||||
|
||||
} ShmItem;
|
||||
|
||||
@@ -34,10 +35,9 @@ private:
|
||||
char *_sem_name;
|
||||
|
||||
size_t *_used;
|
||||
ShmItem **__first;
|
||||
ShmItem **__free_list;
|
||||
|
||||
ShmPlace *_slots;
|
||||
ShmPlace *_first;
|
||||
ShmPlace *_free_list;
|
||||
|
||||
int _in_critical;
|
||||
|
||||
@@ -66,57 +66,82 @@ public:
|
||||
return _mem_name;
|
||||
}
|
||||
|
||||
public:
|
||||
template <class T> void ref(int place, T** p) {
|
||||
if (place == SHM_NULL) {
|
||||
*p = nullptr;
|
||||
} else {
|
||||
*p = reinterpret_cast<T *>(reinterpret_cast<char *>(_mem) + place);
|
||||
}
|
||||
}
|
||||
|
||||
inline void *ref(int place)
|
||||
{
|
||||
if (place == SHM_NULL) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return reinterpret_cast<char *>(_mem) + place;
|
||||
}
|
||||
|
||||
public:
|
||||
int alloc(size_t bytes) {
|
||||
enterCritical();
|
||||
|
||||
ShmItem *_free_list = *__free_list;
|
||||
ShmItem *_first = *__first;
|
||||
|
||||
ShmItem *i = _free_list;
|
||||
ShmPlace p_i = *_free_list;
|
||||
ShmItem *i;
|
||||
ref(p_i, &i);
|
||||
|
||||
while (i != nullptr && i->size < bytes) {
|
||||
i = i->next;
|
||||
p_i = i->next;
|
||||
ref(p_i, &i);
|
||||
}
|
||||
|
||||
int place;
|
||||
if (i != nullptr) {
|
||||
if (i->prev != nullptr) {
|
||||
i->prev->next = i->next;
|
||||
if (i->prev != SHM_NULL) {
|
||||
ShmItem *prev_i;
|
||||
ref(i->prev, &prev_i);
|
||||
prev_i->next = i->next;
|
||||
}
|
||||
if (i->next != nullptr) {
|
||||
i->next->prev = i->prev;
|
||||
if (i->next != SHM_NULL) {
|
||||
ShmItem *next_i;
|
||||
ref(i->next, &next_i);
|
||||
next_i->prev = i->prev;
|
||||
}
|
||||
if (i->prev == nullptr) {
|
||||
_free_list = i->next;
|
||||
if (i->prev == SHM_NULL) {
|
||||
*_free_list = i->next;
|
||||
}
|
||||
i->next = _first;
|
||||
if (_first != nullptr) {
|
||||
_first->prev = i;
|
||||
i->next = *_first;
|
||||
if (*_first != SHM_NULL) {
|
||||
ShmItem *first_i;
|
||||
ref(*_first, &first_i);
|
||||
first_i->prev = p_i;
|
||||
}
|
||||
i->prev = nullptr;
|
||||
i->prev = SHM_NULL;
|
||||
|
||||
_first = i;
|
||||
*__first = _first;
|
||||
*__free_list = _free_list;
|
||||
|
||||
place = (reinterpret_cast<char *>(i) + sizeof(ShmItem)) - reinterpret_cast<char *>(_mem);
|
||||
*_first = p_i;
|
||||
place = p_i + sizeof(ShmItem);
|
||||
} else {
|
||||
i = reinterpret_cast<ShmItem *>(reinterpret_cast<char *>(_mem) + *_used);
|
||||
ShmPlace p_i = *_used;
|
||||
i = reinterpret_cast<ShmItem *>(reinterpret_cast<char *>(_mem) + p_i);
|
||||
size_t u = *_used + sizeof(ShmItem) + bytes;
|
||||
|
||||
if (u >= _size) {
|
||||
place = -1;
|
||||
place = SHM_NULL;
|
||||
} else {
|
||||
*_used = u;
|
||||
i->prev = nullptr;
|
||||
i->prev = SHM_NULL;
|
||||
i->size = bytes;
|
||||
i->next = _first;
|
||||
i->next = *_first;
|
||||
if (*_first != SHM_NULL) {
|
||||
ShmItem *first_i;
|
||||
ref(*_first, &first_i);
|
||||
first_i->prev = p_i;
|
||||
}
|
||||
|
||||
_first = i;
|
||||
*__first = _first;
|
||||
|
||||
place = (reinterpret_cast<char *>(i) + sizeof(ShmItem)) - reinterpret_cast<char *>(_mem);
|
||||
*_first = p_i;
|
||||
place = p_i + sizeof(ShmItem);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -124,39 +149,42 @@ public:
|
||||
return place;
|
||||
}
|
||||
|
||||
void free(int place) {
|
||||
void free(ShmPlace place) {
|
||||
if (place == SHM_NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
enterCritical();
|
||||
ShmItem *i = reinterpret_cast<ShmItem *>(reinterpret_cast<char *>(_mem) + place - sizeof(ShmItem));
|
||||
|
||||
ShmItem *_free_list = *__free_list;
|
||||
ShmItem *_first = *__first;
|
||||
ShmPlace p_i = place - sizeof(ShmItem);
|
||||
ShmItem *i;
|
||||
ref(p_i, &i);
|
||||
|
||||
if (i->prev != nullptr) {
|
||||
i->prev->next = i->next;
|
||||
if (i->prev != SHM_NULL) {
|
||||
ShmItem *prev_i;
|
||||
ref(i->prev, &prev_i);
|
||||
prev_i->next = i->next;
|
||||
}
|
||||
if (i->next != nullptr) {
|
||||
i->next->prev = i->prev;
|
||||
if (i->next != SHM_NULL) {
|
||||
ShmItem *next_i;
|
||||
ref(i->next, &next_i);
|
||||
next_i->prev = i->prev;
|
||||
}
|
||||
if (i->prev == nullptr) {
|
||||
_first = i->next;
|
||||
if (i->prev == SHM_NULL) {
|
||||
*_first = i->next;
|
||||
}
|
||||
i->next = _free_list;
|
||||
if (_free_list != nullptr) {
|
||||
_free_list->prev = i;
|
||||
i->next = *_free_list;
|
||||
if (*_free_list != SHM_NULL) {
|
||||
ShmItem *fl;
|
||||
ref(*_free_list, &fl);
|
||||
fl->prev = p_i;
|
||||
}
|
||||
i->prev = nullptr;
|
||||
_free_list = i;
|
||||
i->prev = SHM_NULL;
|
||||
*_free_list = p_i;
|
||||
|
||||
*__first = _first;
|
||||
*__free_list = _free_list;
|
||||
leaveCritical();
|
||||
}
|
||||
|
||||
inline void *ref(int place)
|
||||
{
|
||||
return reinterpret_cast<char *>(_mem) + place;
|
||||
}
|
||||
|
||||
void enterCritical() {
|
||||
if (_in_critical > 0) {
|
||||
_in_critical++;
|
||||
@@ -188,25 +216,28 @@ public:
|
||||
size_t slots_size = sizeof(ShmPlace) * SHM_MAX_SLOTS;
|
||||
size += slots_size;
|
||||
|
||||
_sem = sem_open(_sem_name, O_CREAT);
|
||||
_shm_fd = shm_open(name, O_CREAT | O_RDWR, 0600);
|
||||
ftruncate(_shm_fd, size);
|
||||
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);
|
||||
} else {
|
||||
_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(ShmItem *) + sizeof(ShmItem *));
|
||||
|
||||
_slots = reinterpret_cast <ShmPlace *>(reinterpret_cast<char *>(_mem) + sizeof(size_t) + sizeof(ShmPlace) + sizeof(ShmPlace));
|
||||
_used = reinterpret_cast<size_t *>(_mem);
|
||||
|
||||
__first = reinterpret_cast<ShmItem **>(reinterpret_cast<char *>(_mem) + sizeof(size_t));
|
||||
|
||||
__free_list = reinterpret_cast<ShmItem **>(reinterpret_cast<char *>(_mem) + sizeof(size_t) + sizeof(ShmItem *));
|
||||
_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;
|
||||
|
||||
if (_owner) {
|
||||
*__first = nullptr;
|
||||
*__free_list = nullptr;
|
||||
*_first = SHM_NULL;
|
||||
*_free_list = SHM_NULL;
|
||||
*_used = sizeof(size_t) + sizeof(ShmItem *) + sizeof(ShmItem *) + slots_size;
|
||||
sem_post(_sem);
|
||||
}
|
||||
@@ -320,26 +351,38 @@ Shm::~Shm()
|
||||
delete _shm_api;
|
||||
}
|
||||
|
||||
template<class T> void ref(Shm *shm, int place, T **p)
|
||||
{
|
||||
*p = reinterpret_cast<T *>(shm->ref(place));
|
||||
}
|
||||
|
||||
|
||||
void ShmSem::post() {
|
||||
sem_post(reinterpret_cast<sem_t *>(_sem));
|
||||
}
|
||||
|
||||
void ShmSem::wait() {
|
||||
sem_wait(reinterpret_cast<sem_t *>(_sem));
|
||||
int r = sem_wait(reinterpret_cast<sem_t *>(_sem));
|
||||
if (r != 0) {
|
||||
fprintf(stderr, "sem_wait error: %d, %s\n", errno, strerror(errno));
|
||||
}
|
||||
}
|
||||
|
||||
bool ShmSem::trywait() {
|
||||
return sem_trywait(reinterpret_cast<sem_t *>(_sem)) == 0;
|
||||
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);
|
||||
}
|
||||
|
||||
ShmSem::ShmSem(const char *n, bool owner) {
|
||||
_name = strdup(n);
|
||||
_sem = reinterpret_cast<void *>(sem_open(n, O_CREAT));
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user