//Ждём: // и смотрим чего дождались:
DWORD dwWaitRezult = WaitForSingleObject(pGate->m_hMutex, timeout);
return ((WAIT_OBJECT_0 == dwWaitRezult)||
(WAIT_ABANDONED == dwWaitRezult)) ? TRUE : FALSE;
Таймауты ожидания SysV семафоров
http://forum.codenet.ru/showthread.php?t=43609
темы.
------------------------
Как уже говорил, раньше когда сервер работал под виндой - синхронизацию работы процессов осуществляли Mutex-ы.
Велечина timeout как раз определяла сколько можно дожидаться, пока освободится Mutex.
-------------------
Теперь же у меня используются семафоры, где установив значение
sem_op = 0 можно заставить один процесс ждать завершения
работы другого при операциях c общими ресурсами...
Проблема в том, что мне нужно по истечению некоторого времени -
timeout прекратить ожидание, однако
struct sembuf - позволяет задать над каким семафором выполняем операцию, какую операцию и флаги.... а можно ли как-то задать timeout на ожидание sem_op = 0? Т.е. если через timeout семафор не обнулился
функция semop(...) прекратила ожидание и вернула управление программе...
В продолжение вот этой
темы.
------------------------
Как уже говорил, раньше когда сервер работал под виндой - синхронизацию работы процессов осуществляли Mutex-ы.
Код:
Велечина timeout как раз определяла сколько можно дожидаться, пока освободится Mutex.
-------------------
Теперь же у меня используются семафоры, где установив значение
sem_op = 0 можно заставить один процесс ждать завершения
работы другого при операциях c общими ресурсами...
Проблема в том, что мне нужно по истечению некоторого времени -
timeout прекратить ожидание, однако
struct sembuf - позволяет задать над каким семафором выполняем операцию, какую операцию и флаги.... а можно ли как-то задать timeout на ожидание sem_op = 0? Т.е. если через timeout семафор не обнулился
функция semop(...) прекратила ожидание и вернула управление программе...
Код:
class Semafors {
private:
int sem_id; //Идентификатор множества семафоров
int num_sems;
Semafors(const Semafors&);
Semafors& operator=(const Semafors&);
const MAXSETSIZE = 256;
struct semid_ds semid_ds;
union semun {
int val;
struct semid_ds *buf;
ushort array [MAXSETSIZE];
} arg, *parg;
protected:
inline int createSemafors_arr(key_t key, int nsems, int semflg)
{ return semget(key, nsems, semflg);}
inline int cntl_sem(int cmd, int semnum = 0, union semun a = 0) //Вызов semctl()
{ return semctl(sem_id, semnum, cmd, a);}
public:
Semafors(key_t key, int nsems, int semflg) //Создание множества семафоров или запрос существующего множества через конструктор
{
num_sems = nsems;
parg = new union semun(arg);
parg->buf = new struct semid_ds(semid_ds);
if((sem_id = Semafors::createSemafors_arr(key, nsems, semflg)) == -1)
exit(0);
}
virtual ~Semafors()
{ delete parg->buf; delete parg; Semafors::cntl_sem(IPC_RMID);}
friend class SemaforsLock;
};
class SemaforsLock {
private:
Semafors &_sem;
struct sembuf *sops;
SemaforsLock(const SemaforsLock&);
SemaforsLock& operator=(const SemaforsLock&);
protected:
inline int operations_sem(unsigned int nsops) //Вызов semop()
{ return semop(_sem.sem_id, sops, nsops);}
public:
SemaforsLock(Semafors &sem) : _sem(sem)
{ sops = new struct sembuf[_sem.num_sems];}
/*Назначение аргумента arg зависит от управляющего действия, которое определяется значением аргумента cmd. Допустимы следующие действия:
* GETVAL - получить значение семафора и выдать его в качестве результата;
* SETVAL - установить значение семафора равным arg.val;
* GETPID - получить идентификатор процесса, выполнявшего операцию над семафором последним , и выдать его в качестве результата;
* GETNCNT - получить число процессов, ожидающих увеличения значения семафора, и выдать его в качестве результата;
* GETZCNT - получить число процессов, ожидающих обнуления значения семафора, и выдать его в качестве результата;
* GETALL - прочитать значения всех семафоров множества и поместить их в массив, на который указывает arg.array;
* SETALL - установить значения всех семафоров множества равными значениям элементов массива, на который указывает
* arg.array;
* IPC_STAT - поместить информацию о состоянии множества семафоров, содержащуюся в структуре данных, ассоциированной с идентификатором semid, в пользовательскую структуру, на которую указывает arg.buf;
* IPC_SET - в структуре данных, ассоциированной с идентификатором semid, переустановить значения действующих идентификаторов пользователя и группы, а также прав на операции. Нужные значения извлекаются из структуры данных, на которую указывает arg.buf;
* IPC_RMID - удалить из системы идентификатор semid, ликвидировать множество семафоров и ассоциированную с ним структуру данных.
*/
int cntlSemafors(int semnum , int cmd, int v = 0); //Управление семафорами
int operationsSemafors(unsigned int nsops); //Операции над семафорами
void setSemafors_buf(struct semid_ds *b);
void setSemafors_array(ushort *arr);
void setSemafors_sops(struct sembuf *s);
inline int getSemafors_val(void) { return _sem.parg->val;}
inline struct semid_ds* getSemafors_buf(void) { return _sem.parg->buf;}
inline ushort* getSemafors_array(void) { return _sem.parg->array;}
inline struct sembuf* getSemafors_sops(void) { return sops;}
virtual ~SemaforsLock(){ delete[] sops;}
};
private:
int sem_id; //Идентификатор множества семафоров
int num_sems;
Semafors(const Semafors&);
Semafors& operator=(const Semafors&);
const MAXSETSIZE = 256;
struct semid_ds semid_ds;
union semun {
int val;
struct semid_ds *buf;
ushort array [MAXSETSIZE];
} arg, *parg;
protected:
inline int createSemafors_arr(key_t key, int nsems, int semflg)
{ return semget(key, nsems, semflg);}
inline int cntl_sem(int cmd, int semnum = 0, union semun a = 0) //Вызов semctl()
{ return semctl(sem_id, semnum, cmd, a);}
public:
Semafors(key_t key, int nsems, int semflg) //Создание множества семафоров или запрос существующего множества через конструктор
{
num_sems = nsems;
parg = new union semun(arg);
parg->buf = new struct semid_ds(semid_ds);
if((sem_id = Semafors::createSemafors_arr(key, nsems, semflg)) == -1)
exit(0);
}
virtual ~Semafors()
{ delete parg->buf; delete parg; Semafors::cntl_sem(IPC_RMID);}
friend class SemaforsLock;
};
class SemaforsLock {
private:
Semafors &_sem;
struct sembuf *sops;
SemaforsLock(const SemaforsLock&);
SemaforsLock& operator=(const SemaforsLock&);
protected:
inline int operations_sem(unsigned int nsops) //Вызов semop()
{ return semop(_sem.sem_id, sops, nsops);}
public:
SemaforsLock(Semafors &sem) : _sem(sem)
{ sops = new struct sembuf[_sem.num_sems];}
/*Назначение аргумента arg зависит от управляющего действия, которое определяется значением аргумента cmd. Допустимы следующие действия:
* GETVAL - получить значение семафора и выдать его в качестве результата;
* SETVAL - установить значение семафора равным arg.val;
* GETPID - получить идентификатор процесса, выполнявшего операцию над семафором последним , и выдать его в качестве результата;
* GETNCNT - получить число процессов, ожидающих увеличения значения семафора, и выдать его в качестве результата;
* GETZCNT - получить число процессов, ожидающих обнуления значения семафора, и выдать его в качестве результата;
* GETALL - прочитать значения всех семафоров множества и поместить их в массив, на который указывает arg.array;
* SETALL - установить значения всех семафоров множества равными значениям элементов массива, на который указывает
* arg.array;
* IPC_STAT - поместить информацию о состоянии множества семафоров, содержащуюся в структуре данных, ассоциированной с идентификатором semid, в пользовательскую структуру, на которую указывает arg.buf;
* IPC_SET - в структуре данных, ассоциированной с идентификатором semid, переустановить значения действующих идентификаторов пользователя и группы, а также прав на операции. Нужные значения извлекаются из структуры данных, на которую указывает arg.buf;
* IPC_RMID - удалить из системы идентификатор semid, ликвидировать множество семафоров и ассоциированную с ним структуру данных.
*/
int cntlSemafors(int semnum , int cmd, int v = 0); //Управление семафорами
int operationsSemafors(unsigned int nsops); //Операции над семафорами
void setSemafors_buf(struct semid_ds *b);
void setSemafors_array(ushort *arr);
void setSemafors_sops(struct sembuf *s);
inline int getSemafors_val(void) { return _sem.parg->val;}
inline struct semid_ds* getSemafors_buf(void) { return _sem.parg->buf;}
inline ushort* getSemafors_array(void) { return _sem.parg->array;}
inline struct sembuf* getSemafors_sops(void) { return sops;}
virtual ~SemaforsLock(){ delete[] sops;}
};
Для этой цели необходимо использовать переменные состояния с мьютексами, определяя их область видимости в пределах всей системы (PTHREAD_PROCESS_SHARED) и помещая их в шарёную память для общего доступа процессов, и потоков из разных процессов. В помощь( int pthread_cond_timedwait(pthread_cond_t *cv, pthread_mutex_t *mp, const struct timespec *abstime);)
А вообще, лучше реализовывать подобные вещи в рамках одного процесса с использованием потоков.
Если понадобиться, могу выложить остальные классы для POSIX "инструментов" (на Си код получается корявым и длинным) :)
Ну например я бы не прочь поразглядывать подобные классы в целях повышения профессионального уровня =) Ты можешь выложить их в разделе исходников, а здесь просто оставить ссылку.
Ок, завтра выложу и кину ссылочку или же сюда архивом . Сегодня деньги на инете заканчиваются, сори ....
Вобщем у меня появилась идея создания библиотеки/интерфейса для С++ программ к средствам стандарта Posix. Так скажем вдохновило меня на это, программирование на Python, где все эти привязки реализованны в качестве управления высокоуровневыми объектами. Программы получаются достаточно короткими, функциональными и удобными в плане изменений и расширяемости. Но многие люди даже не зают что такое питон и в основном кодят на С/С++ ну и Java. На Си код получается ужасно уродливым....а представление элементов Posix в качестве объектов, оперируемых с помощью иных структур данных, скажем односвязанный/двухсвязанный простой и кольцевой список, вектора, матрицы, ассоциативный массив, и т.д и.т.п., а так же построение объектов, реализующих различные алгоритмы сортировки и поиска из готовых библиотечных классов дает возможности построения более элегантного кода.
Раньше я просто использовал ограниченный набор классов в своих программах, кот. находились во вкл. заголовочном файле. Теперь же думаю создать полноценную библиотеку/интерфейс ко всем, ну или многим, инструментариям Posix: как к низкоуровневым средствам межпроцессного взаимодейтсия (в вышепреведённых классах не хватает кое-чего - сокетов, труб, очередей FIFO, очередей сообщений, шарёной памяти и RPC. Так же не хватает динамического контроля ошибок. Над этим я работаю), так и к высокоуровневым, а в частности есть идеи реализации интерфейса к библиотеке распределенных межпроцессных коммуникаций DIPC, MPI, ну и посложнее - к библиотеке научных вычислений PETSc (в Python прекрасно реализованно в качестве Numeric Python) и к PVM (для возможности представления высокоуровнего параллелизма в пользовательских приложениях с помощью объектов С++).
После создания первой работоспособной версии библиотеки думаю опубликовать проект допустим на sourseforge.net и кинуть ссылку в созданную тему на этом форуме (возможно кому-то это покажется интересным, а кому-то забавным....не важно =)
Небольшие наработки классов, кот. я кинул сюда, представляют пока ограниченные возможности. оперировать с ними просто:
1) создаём объекты атрибутов для мьютексов, переменных состояния, потоков в необходимом количестве;
2) создаём объекты ключей, мьютексов, переменных состояния и помещаем указатели на них в связанный список Slist или же в Islist(в этом случае необходимо создать производный от slink класс со своей реализацией);
3) создаем объекты потоков (пользовательские потоки библиотеки Pthread. Класс потоков ядра пока не реализован) и так же можно хранить указатели на них в связанном списке;
4) выбор мьютексов, переменных состояния, ключей, потоков легко производить с помощью итератора, "просматривающего" список (у мьютексов, переменных состояния, ключей имеется свой идентификатор в связанном списке, генерируемый с помощью random). В пользовательской программе реализация проста и эффективна.
Любые идеи, предложения, мнения и критику с удовольствием выслушаю в приват. Думаю библиотека будет полезна и интересна многим начинающим и (не только) программерам под UNIX :)
Ух ты... а тема то разрослась пока я в неё не заглядывал :) - правдо я уже у себя всё успел переписать так, что в такой необходимости синхронизации процессов нужда отпала (сейчас вообще не осталось ни одного модуля .cgi написанного на С++) - но всё равно информация думаю будет полезной, спасибо.