PageRenderTime 83ms CodeModel.GetById 41ms app.highlight 11ms RepoModel.GetById 29ms app.codeStats 0ms

/mordor/semaphore.cpp

http://github.com/mozy/mordor
C++ | 129 lines | 117 code | 11 blank | 1 comment | 23 complexity | 7e82c54c54c3f40e27bb04af468a9dd7 MD5 | raw file
  1// Copyright (c) 2009 - Mozy, Inc.
  2
  3#include "semaphore.h"
  4
  5#include "assert.h"
  6#include "exception.h"
  7
  8#ifndef WINDOWS
  9#include <errno.h>
 10#endif
 11
 12#ifdef FREEBSD
 13#include <sys/sem.h>
 14#endif
 15
 16#ifdef OSX
 17#include <mach/mach_init.h>
 18#include <mach/task.h>
 19#endif
 20
 21namespace Mordor {
 22
 23Semaphore::Semaphore(unsigned int count)
 24{
 25#ifdef WINDOWS
 26    m_semaphore = CreateSemaphore(NULL, count, 2147483647, NULL);
 27    if (m_semaphore == NULL) {
 28        MORDOR_THROW_EXCEPTION_FROM_LAST_ERROR_API("CreateSemaphore");
 29    }
 30#elif defined(OSX)
 31    m_task = mach_task_self();
 32    if (semaphore_create(m_task, &m_semaphore, SYNC_POLICY_FIFO, count)) {
 33        MORDOR_THROW_EXCEPTION_FROM_LAST_ERROR_API("semaphore_create");
 34    }
 35#elif defined(FREEBSD)
 36    m_semaphore = semget(IPC_PRIVATE, 1, IPC_CREAT | 0600);
 37    if (m_semaphore < 0) {
 38        MORDOR_THROW_EXCEPTION_FROM_LAST_ERROR_API("semget");
 39    }
 40    semun init;
 41    init.val = count;
 42    if (semctl(m_semaphore, 0, SETVAL, init) < 0) {
 43        semctl(m_semaphore, 0, IPC_RMID);
 44        MORDOR_THROW_EXCEPTION_FROM_LAST_ERROR_API("semctl");
 45    }
 46#else
 47    if (sem_init(&m_semaphore, 0, count)) {
 48        MORDOR_THROW_EXCEPTION_FROM_LAST_ERROR_API("sem_init");
 49    }
 50#endif
 51}
 52
 53Semaphore::~Semaphore()
 54{
 55#ifdef WINDOWS
 56    MORDOR_NOTHROW_VERIFY(CloseHandle(m_semaphore));
 57#elif defined(OSX)
 58    MORDOR_NOTHROW_VERIFY(!semaphore_destroy(m_task, m_semaphore));
 59#elif defined(FREEBSD)
 60    MORDOR_NOTHROW_VERIFY(semctl(m_semaphore, 0, IPC_RMID) >= 0);
 61#else
 62    MORDOR_NOTHROW_VERIFY(!sem_destroy(&m_semaphore));
 63#endif
 64}
 65
 66void
 67Semaphore::wait()
 68{
 69#ifdef WINDOWS
 70    DWORD dwRet = WaitForSingleObject(m_semaphore, INFINITE);
 71    if (dwRet != WAIT_OBJECT_0) {
 72        MORDOR_THROW_EXCEPTION_FROM_LAST_ERROR_API("WaitForSingleObject");
 73    }
 74#elif defined(OSX)
 75    kern_return_t rc;
 76    do {
 77        rc = semaphore_wait(m_semaphore);
 78    } while (rc == KERN_ABORTED);
 79    if (rc != KERN_SUCCESS) {
 80        MORDOR_THROW_EXCEPTION_FROM_LAST_ERROR_API("semaphore_wait");
 81    }
 82#elif defined(FREEBSD)
 83    sembuf op;
 84    op.sem_num = 0;
 85    op.sem_op = -1;
 86    op.sem_flg = 0;
 87    while (true) {
 88        if (!semop(m_semaphore, &op, 1))
 89            return;
 90        if (errno != EINTR) {
 91            MORDOR_THROW_EXCEPTION_FROM_LAST_ERROR_API("semop");
 92        }
 93    }
 94#else
 95    while (true) {
 96        if (!sem_wait(&m_semaphore))
 97            return;
 98        if (errno != EINTR) {
 99            MORDOR_THROW_EXCEPTION_FROM_LAST_ERROR_API("sem_wait");
100        }
101    }
102#endif
103}
104
105void
106Semaphore::notify()
107{
108#ifdef WINDOWS
109    if (!ReleaseSemaphore(m_semaphore, 1, NULL)) {
110        MORDOR_THROW_EXCEPTION_FROM_LAST_ERROR_API("ReleaseSemaphore");
111    }
112#elif defined(OSX)
113    semaphore_signal(m_semaphore);
114#elif defined(FREEBSD)
115    sembuf op;
116    op.sem_num = 0;
117    op.sem_op = 1;
118    op.sem_flg = 0;
119    if (semop(m_semaphore, &op, 1)) {
120        MORDOR_THROW_EXCEPTION_FROM_LAST_ERROR_API("semop");
121    }
122#else
123    if (sem_post(&m_semaphore)) {
124        MORDOR_THROW_EXCEPTION_FROM_LAST_ERROR_API("sem_post");
125    }
126#endif
127}
128
129}