Added SharedMemoryChannel and its comparison with other methods

This commit is contained in:
ftc
2023-02-26 16:12:04 +03:00
parent 81000fb1f4
commit 59589e4017
8 changed files with 668 additions and 34 deletions
+88
View File
@@ -0,0 +1,88 @@
#ifndef SHAREDMEMORYCHANNEL_H
#define SHAREDMEMORYCHANNEL_H
#include <string>
#include <sys/types.h>
#include <sys/ipc.h>
#include <set>
#include <pthread.h>
#include <semaphore.h>
class SharedMemoryChannelID
{
public:
time_t reuse_at;
int internal_id;
std::string id;
};
bool operator<(const SharedMemoryChannelID &a, const SharedMemoryChannelID &b);
class SharedMemoryChannelIDProvider
{
// Таймаут, после которого считается, что id канала безопасно переиспользовать.
// В секундах.
const int ID_REUSE_TIMEOUT = 60;
int last_id;
pthread_mutex_t access_mutex;
std::string prefix;
std::set<SharedMemoryChannelID> used_ids;
public:
SharedMemoryChannelIDProvider();
SharedMemoryChannelID GetID();
void ReleaseID(const SharedMemoryChannelID &id);
};
/*
* Обмен с PHP-клиентом через shared memory.
* Управляется двумя семафорами. Общий цикл выглядит так:
* 1) Оба семафора залочены, мы ждем semaphore_receive.
* 2) Клиент кладет в shared mem сообщение, разлочивает semaphore_receive.
* 3) Мы получаем semaphore_receive, читаем сообщение. Клиент ждет semaphore_send.
* 4) Разлочим semaphore_send, клиент лочит semaphore_send и получает сообщение,
*
* Итого общий принцип - при получении сообщения получатель
* лочит семафор, ответственный за передачу в его сторону. И
* не разлочивает его, задача разлочивать - на отправителе.
* Отправитель соответственно когда готова отправка разлочивает
* семафор передачи "от него".
*/
class SharedMemoryChannel
{
const static int TIMEOUT_MSEC = 100;
// через вот такое количество времени считаем, что канал уже не используется и его можно прибивать
const static int CHANNEL_CLEAR_TIMEOUT_SEC = 10;
// Храним использованные id-шники
// с тем, чтобы разные каналы использовали разные
// id, но при этом набор id-шников оставался
// бы неизменным при повторных запусках.
// Это чинит неприятную проблему, связанную с
// прибиванием процесса, который пользуется семафорами.
static SharedMemoryChannelIDProvider id_provider;
// 4 bytes for length
key_t shared_mem_key;
int shared_mem;
void *shared;
std::string semaphore_send_key;
sem_t* semaphore_send;
std::string semaphore_receive_key;
sem_t* semaphore_receive;
//
void AcquireSemaphore(sem_t *semaphore);
void ReleaseSemaphore(sem_t *semaphore);
//
SharedMemoryChannelID id;
public:
const static int MAX_LEN = 1048076 - 4;
std::string GetSendKey() const;
std::string GetReceiveKey() const;
key_t GetSharedMemKey() const;
SharedMemoryChannel();
~SharedMemoryChannel();
std::string Receive();
void Send(const std::string &s);
};
#endif // SHAREDMEMORYCHANNEL_H