8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-02-01 06:43:03 +01:00
firebird-mirror/src/common/classes/semaphore.h

245 lines
4.8 KiB
C
Raw Normal View History

/*
* PROGRAM: Client/Server Common Code
* MODULE: semaphore.h
* DESCRIPTION: Semaphore lock
*
* The contents of this file are subject to the Initial
* Developer's Public License Version 1.0 (the "License");
* you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
* http://www.ibphoenix.com/main.nfs?a=ibphoenix&page=ibp_idpl.
*
* Software distributed under the License is distributed AS IS,
* WITHOUT WARRANTY OF ANY KIND, either express or implied.
* See the License for the specific language governing rights
* and limitations under the License.
*
* The Original Code was created by Nickolay Samofatov
* for the Firebird Open Source RDBMS project.
*
* Copyright (c) 2004 Nickolay Samofatov <nickolay@broadviewsoftware.com>
* and all contributors signed below.
*
* All Rights Reserved.
* Contributor(s): ______________________________________.
*
*
*/
#ifndef CLASSES_SEMAPHORE_H
#define CLASSES_SEMAPHORE_H
2007-12-19 15:35:52 +01:00
#include "../jrd/gdsassert.h"
2008-01-16 07:24:06 +01:00
#ifdef WIN_NT
// Note: Windows does not need signal safe version of the class
#include <windows.h>
#include <limits.h>
namespace Firebird
{
class MemoryPool;
class Semaphore
{
private:
HANDLE hSemaphore;
void init()
2008-12-05 01:56:15 +01:00
{
hSemaphore = CreateSemaphore(NULL, 0 /*initial count*/, INT_MAX, NULL);
if (hSemaphore == NULL)
system_call_failed::raise("CreateSemaphore");
}
public:
Semaphore() { init(); }
2008-03-02 10:24:11 +01:00
explicit Semaphore(MemoryPool&) { init(); }
~Semaphore()
{
if (hSemaphore && !CloseHandle(hSemaphore))
system_call_failed::raise("CloseHandle");
2008-12-05 01:56:15 +01:00
}
#define CLASSES_SEMAPHORE_H_HAS_TRYENTER 1
2008-07-16 13:15:00 +02:00
bool tryEnter(const int seconds = 0, int milliseconds = 0)
{
milliseconds += seconds * 1000;
2008-12-13 10:26:00 +01:00
DWORD result = WaitForSingleObject(hSemaphore, milliseconds >= 0 ? milliseconds : INFINITE);
if (result == WAIT_FAILED)
system_call_failed::raise("WaitForSingleObject");
return result != WAIT_TIMEOUT;
}
void enter()
{
2008-10-13 21:21:43 +02:00
tryEnter(-1);
}
void release(SLONG count = 1)
{
if (!ReleaseSemaphore(hSemaphore, count, NULL))
system_call_failed::raise("ReleaseSemaphore");
}
};
2007-11-12 16:18:49 +01:00
} // namespace Firebird
#else // WINNT
#ifdef DARWIN
// Mach semaphore
#define COMMON_CLASSES_SEMAPHORE_MACH
#include <mach/mach.h>
#include <mach/semaphore.h>
#include <mach/task.h>
namespace Firebird
{
class MemoryPool;
class SignalSafeSemaphore
{
private:
semaphore_t sem;
static void machErrorCheck(kern_return_t rc, const char* function);
void init();
public:
SignalSafeSemaphore() { init(); }
explicit SignalSafeSemaphore(MemoryPool&) { init(); }
~SignalSafeSemaphore();
void enter()
{
machErrorCheck(semaphore_wait(sem), "semaphore_wait");
}
void release(SLONG count = 1)
{
fb_assert(count >= 0);
while (count--)
{
machErrorCheck(semaphore_signal(sem), "semaphore_signal");
}
}
};
} // namespace Firebird
#else // DARWIN
2007-11-15 12:31:56 +01:00
2007-11-12 16:18:49 +01:00
#ifdef HAVE_SEMAPHORE_H
#define COMMON_CLASSES_SEMAPHORE_POSIX_RT
2007-11-12 16:18:49 +01:00
#include <semaphore.h>
#include <errno.h>
2007-12-19 15:35:52 +01:00
#include <time.h>
2007-12-07 13:19:37 +01:00
#ifndef WORKING_SEM_INIT
#include <fcntl.h>
2007-12-22 01:53:39 +01:00
#endif // WORKING_SEM_INIT
2007-11-12 16:18:49 +01:00
namespace Firebird
{
2007-11-12 16:18:49 +01:00
class SignalSafeSemaphore
{
2007-11-12 16:18:49 +01:00
private:
2007-12-07 13:19:37 +01:00
#ifdef WORKING_SEM_INIT
sem_t sem[1];
#else
sem_t* sem;
2007-12-22 01:53:39 +01:00
#endif // WORKING_SEM_INIT
void init();
2008-12-05 01:56:15 +01:00
public:
SignalSafeSemaphore() { init(); }
2008-03-02 10:24:11 +01:00
explicit SignalSafeSemaphore(MemoryPool&) { init(); }
~SignalSafeSemaphore();
void enter();
2008-12-05 01:56:15 +01:00
void release(SLONG count = 1)
{
2007-11-12 16:18:49 +01:00
for (int i = 0; i < count; i++)
2007-12-28 01:14:00 +01:00
{
2007-12-07 13:50:43 +01:00
if (sem_post(sem) == -1)
2007-12-27 11:55:58 +01:00
{
2007-11-12 16:18:49 +01:00
system_call_failed::raise("semaphore.h: release: sem_post()");
2007-12-27 11:55:58 +01:00
}
2007-12-28 01:14:00 +01:00
}
2007-11-12 16:18:49 +01:00
}
#ifdef HAVE_SEM_TIMEDWAIT
2008-12-05 01:56:15 +01:00
// In case when sem_timedwait() is implemented by host OS,
2007-11-17 01:38:16 +01:00
// class SignalSafeSemaphore may have this function:
#define CLASSES_SEMAPHORE_H_HAS_TRYENTER 1
bool tryEnter(const int seconds = 0, int milliseconds = 0);
2008-01-16 07:24:06 +01:00
#endif // HAVE_SEM_TIMEDWAIT
2007-11-12 16:18:49 +01:00
};
} // namespace Firebird
2008-01-16 07:24:06 +01:00
#endif // HAVE_SEMAPHORE_H
#endif // DARWIN
2007-11-12 16:18:49 +01:00
#ifdef CLASSES_SEMAPHORE_H_HAS_TRYENTER
2007-11-12 16:18:49 +01:00
// In case when sem_timedwait() is implemented by host OS,
// SignalSafeSemaphore and Semaphore are just the same
namespace Firebird
{
typedef SignalSafeSemaphore Semaphore;
}
2007-11-12 16:18:49 +01:00
#else // CLASSES_SEMAPHORE_H_HAS_TRYENTER
// Should implement Semaphore independent from SignalSafeSemaphore.
// In the worst case no SignalSafeSemaphore at all (and no SS for that platform).
#define COMMON_CLASSES_SEMAPHORE_COND_VAR
#include <pthread.h>
#include <errno.h>
namespace Firebird
{
class Semaphore
{
private:
pthread_mutex_t mu;
pthread_cond_t cv;
int value;
void init();
void mtxLock();
void mtxUnlock();
2008-12-05 01:56:15 +01:00
public:
Semaphore() { init(); }
2008-03-02 10:24:11 +01:00
explicit Semaphore(MemoryPool&) { init(); }
~Semaphore();
2008-12-05 01:56:15 +01:00
bool tryEnter(const int seconds = 0, int milliseconds = 0);
void enter();
void release(SLONG count = 1);
};
} // namespace Firebird
#endif // CLASSES_SEMAPHORE_H_HAS_TRYENTER
2007-11-15 12:31:56 +01:00
2008-01-16 07:24:06 +01:00
#endif // WIN_NT
#endif // CLASSES_SEMAPHORE_H