/*************************************************************************** * Copyright (C) 2005 by Jeff Ferr * * root@sat * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "Stdafx.h" #include "jsharedsemaphore.h" #include "jsemaphoreexception.h" namespace jshared { #if defined(__GNU_LIBRARY__) && !defined(_SEM_SEMUN_UNDEFINED) /* union semun is defined by including */ #else /* according to X/OPEN we have to define it ourselves */ union semun { int val; /* value for SETVAL */ struct semid_ds *buf; /* buffer for IPC_STAT, IPC_SET */ unsigned short *array; /* array for GETALL, SETALL */ struct seminfo *__buf; /* buffer for IPC_INFO */ }; #endif #ifdef _WIN32 SharedSemaphore::SharedSemaphore(int key_): #else SharedSemaphore::SharedSemaphore(key_t key_): #endif jcommon::Object() { jcommon::Object::SetClassName("jshared::SharedSemaphore"); #ifdef _WIN32 #else _id = semget(key_, 0, 0); if (_id < 0) { throw jthread::SemaphoreException("Opening shared semaphore error"); } #endif } #ifdef _WIN32 SharedSemaphore::SharedSemaphore(int key_, int nsem_, int value_, int perms_): #else SharedSemaphore::SharedSemaphore(key_t key_, int nsem_, int value_, int perms_): #endif jcommon::Object() { jcommon::Object::SetClassName("jshared::SharedSemaphore"); #ifdef _WIN32 #else _nsem = nsem_; _value = value_; _flag = 0; _id = semget(key_, nsem_, perms_ | IPC_CREAT | IPC_EXCL); if (_id < 0) { /* if (errno == EEXIST) { throw jthread::SemaphoreException("Opening shared semaphore error"); } throw jthread::SemaphoreException("Creating shared semaphore error"); */ _id = semget(key_, nsem_, perms_); if (_id < 0) { throw jthread::SemaphoreException("Creating shared semaphore error"); } } InitializeSemaphore(); #endif } void SharedSemaphore::InitializeSemaphore() { #ifdef _WIN32 #else uint16_t *initv = new uint16_t[_nsem]; for (int i=0; i<_nsem; i++) { initv[i] = _value; } union semun arg; arg.array = initv; int r; r = semctl(_id, _nsem, SETALL, arg); delete [] initv; if (r < 0) { throw jthread::SemaphoreException("Initializing semaphore error"); } #endif } SharedSemaphore::~SharedSemaphore() { } void SharedSemaphore::SetBlocking(bool b) { #ifdef _WIN32 #else if (b == true) { _flag = 0; } else { _flag = IPC_NOWAIT; } #endif } bool SharedSemaphore::IsBlocking() { return (_flag == 0); } void SharedSemaphore::SetTimeout(int millis_, jsem_op_t *op) { if (millis_ <= 0) { return; } #ifdef _WIN32 #else struct sembuf *sops; jsem_op_t *p = op; p->id = new int[_nsem]; if (p == NULL) { sops = new struct sembuf[_nsem]; p = new jsem_op_t; int k; for (k=0; k<_nsem; k++) { p->id[k] = k; } p->length = k; } else { sops = new struct sembuf[p->length]; } for (int i=0; ilength; i++) { if (p->id[i] < _nsem) { if (op == NULL) { delete p; } delete sops; throw jthread::SemaphoreException("Invalid semaphore id error"); } sops[i].sem_num = p->id[i]; sops[i].sem_op = +1; sops[i].sem_flg = _flag; } struct timespec t; t.tv_sec = millis_/1000; t.tv_nsec = 0; int r = semtimedop(_id, sops, p->length, &t); if (op == NULL) { delete p; } delete sops; if (r < 0) { throw jthread::SemaphoreException("Setting timeout exception"); } #endif } void SharedSemaphore::Wait(jsem_op_t *op) { #ifdef _WIN32 #else // SEE:: semop, SEM_UNDO struct sembuf *sops; jsem_op_t *p = op; p->id = new int[_nsem]; if (p == NULL) { sops = new struct sembuf[_nsem]; p = new jsem_op_t; int k; for (k=0; k<_nsem; k++) { p->id[k] = k; } p->length = k; } else { sops = new struct sembuf[p->length]; } for (int i=0; ilength; i++) { if (p->id[i] < _nsem) { if (op == NULL) { delete p; } delete sops; throw jthread::SemaphoreException("Invalid semaphore id error"); } sops[i].sem_num = p->id[i]; sops[i].sem_op = -1; sops[i].sem_flg = _flag; } int r = semop(_id, sops, p->length); if (op == NULL) { delete p; } delete sops; if (r < 0) { if (errno == EAGAIN) { if (_flag == IPC_NOWAIT) { throw jthread::SemaphoreException("Initializing semaphore error"); } else { throw jthread::SemaphoreException("Timeout expired exception"); } } else { throw jthread::SemaphoreException("Waiting semaphore error"); } } #endif } void SharedSemaphore::Notify(jsem_op_t *op) { #ifdef _WIN32 #else // SEE:: semop, SEM_UNDO struct sembuf *sops; jsem_op_t *p = op; p->id = new int[_nsem]; if (p == NULL) { sops = new struct sembuf[_nsem]; p = new jsem_op_t; int k; for (k=0; k<_nsem; k++) { p->id[k] = k; } p->length = k; } else { sops = new struct sembuf[p->length]; } for (int i=0; ilength; i++) { if (p->id[i] < _nsem) { if (op == NULL) { delete p; } delete sops; throw jthread::SemaphoreException("Invalid semaphore id error"); } sops[i].sem_num = p->id[i]; sops[i].sem_op = +1; sops[i].sem_flg = _flag; } int r = semop(_id, sops, p->length); if (op == NULL) { delete p; } delete sops; if (r < 0) { if (errno == EAGAIN) { if (_flag == IPC_NOWAIT) { throw jthread::SemaphoreException("Initializing semaphore error"); } else { throw jthread::SemaphoreException("Timeout expired exception"); } } else { throw jthread::SemaphoreException("Waiting semaphore error"); } } #endif } void SharedSemaphore::Release() { #ifdef _WIN32 #else union semun arg; int r; r = semctl(_id, 0, IPC_RMID, arg); if (r < 0) { throw jthread::SemaphoreException("Release semaphores error"); } #endif } }