mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-01-23 22:03:03 +01:00
Uncouple Mutex and RefMutex. This resolves the circular dependency: "AtomicCounter->Mutex->RefCounted->AtomicCounter" and thus enables all non-x86 POSIX builds.
This commit is contained in:
parent
f764f68630
commit
8e72ece026
@ -89,7 +89,7 @@ namespace Firebird
|
||||
class RefPtr
|
||||
{
|
||||
public:
|
||||
RefPtr() : ptr(0)
|
||||
RefPtr() : ptr(NULL)
|
||||
{ }
|
||||
|
||||
explicit RefPtr(T* p) : ptr(p)
|
||||
@ -100,7 +100,7 @@ namespace Firebird
|
||||
}
|
||||
}
|
||||
|
||||
RefPtr(RefPtr& r) : ptr(r.ptr)
|
||||
RefPtr(const RefPtr& r) : ptr(r.ptr)
|
||||
{
|
||||
if (ptr)
|
||||
{
|
||||
@ -121,7 +121,7 @@ namespace Firebird
|
||||
return assign(p);
|
||||
}
|
||||
|
||||
T* operator=(RefPtr& r)
|
||||
T* operator=(const RefPtr& r)
|
||||
{
|
||||
return assign(r.ptr);
|
||||
}
|
||||
@ -189,6 +189,7 @@ namespace Firebird
|
||||
|
||||
T* ptr;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
#endif // COMMON_REF_COUNTED_H
|
||||
|
172
src/common/classes/RefMutex.h
Normal file
172
src/common/classes/RefMutex.h
Normal file
@ -0,0 +1,172 @@
|
||||
/*
|
||||
* PROGRAM: Client/Server Common Code
|
||||
* MODULE: RefMutex.h
|
||||
* DESCRIPTION: Reference-counted mutex
|
||||
*
|
||||
* 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 Vlad Khorsun
|
||||
* for the Firebird Open Source RDBMS project.
|
||||
*
|
||||
* Copyright (c) 2004 Vlad Khorsun <hvlad@users.sf.net>
|
||||
* and all contributors signed below.
|
||||
*
|
||||
* All Rights Reserved.
|
||||
* Contributor(s): ______________________________________.
|
||||
*
|
||||
* Alex Peshkov <peshkoff@mail.ru>
|
||||
* Dmitry Yemanov <dimitr@users.sf.net>
|
||||
*/
|
||||
|
||||
#ifndef CLASSES_REF_MUTEX_H
|
||||
#define CLASSES_REF_MUTEX_H
|
||||
|
||||
#include "locks.h"
|
||||
#include "RefCounted.h"
|
||||
|
||||
namespace Firebird
|
||||
{
|
||||
// Mutex with reference counting
|
||||
//
|
||||
// This class is useful if mutex can be "deleted" by the
|
||||
// code between enter and leave calls
|
||||
|
||||
class RefMutex : public RefCounted
|
||||
{
|
||||
public:
|
||||
RefMutex() {}
|
||||
explicit RefMutex(MemoryPool& pool) : mutex(pool) {}
|
||||
|
||||
void enter()
|
||||
{
|
||||
mutex.enter();
|
||||
}
|
||||
|
||||
bool tryEnter()
|
||||
{
|
||||
return mutex.tryEnter();
|
||||
}
|
||||
|
||||
void leave()
|
||||
{
|
||||
mutex.leave();
|
||||
}
|
||||
|
||||
private:
|
||||
Mutex mutex;
|
||||
};
|
||||
|
||||
// RAII holder
|
||||
class RefMutexGuard : public Reference
|
||||
{
|
||||
public:
|
||||
explicit RefMutexGuard(RefMutex& alock)
|
||||
: Reference(alock), lock(&alock)
|
||||
{
|
||||
lock->enter();
|
||||
}
|
||||
|
||||
~RefMutexGuard()
|
||||
{
|
||||
lock->leave();
|
||||
}
|
||||
|
||||
private:
|
||||
// Forbid copying
|
||||
RefMutexGuard(const RefMutexGuard&);
|
||||
RefMutexGuard& operator=(const RefMutexGuard&);
|
||||
|
||||
RefMutex* lock;
|
||||
};
|
||||
|
||||
|
||||
template <typename T>
|
||||
class DefaultRefCounted
|
||||
{
|
||||
public:
|
||||
static int addRef(T* object)
|
||||
{
|
||||
return object->addRef();
|
||||
}
|
||||
|
||||
static int release(T* object)
|
||||
{
|
||||
return object->release();
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class NotRefCounted
|
||||
{
|
||||
public:
|
||||
static int addRef(T*)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int release(T*)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Mtx, typename RefCounted = DefaultRefCounted<Mtx> >
|
||||
class EnsureUnlock
|
||||
{
|
||||
public:
|
||||
explicit EnsureUnlock(Mtx& mutex)
|
||||
{
|
||||
m_mutex = &mutex;
|
||||
RefCounted::addRef(m_mutex);
|
||||
m_locked = 0;
|
||||
}
|
||||
|
||||
~EnsureUnlock()
|
||||
{
|
||||
while (m_locked)
|
||||
leave();
|
||||
RefCounted::release(m_mutex);
|
||||
}
|
||||
|
||||
void enter()
|
||||
{
|
||||
m_mutex->enter();
|
||||
m_locked++;
|
||||
}
|
||||
|
||||
bool tryEnter()
|
||||
{
|
||||
if (m_mutex->tryEnter())
|
||||
{
|
||||
m_locked++;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void leave()
|
||||
{
|
||||
m_mutex->leave();
|
||||
m_locked--;
|
||||
}
|
||||
|
||||
private:
|
||||
Mtx* m_mutex;
|
||||
int m_locked;
|
||||
};
|
||||
|
||||
typedef EnsureUnlock<Mutex, NotRefCounted<Mutex> > MutexEnsureUnlock;
|
||||
typedef EnsureUnlock<RefMutex> RefMutexEnsureUnlock;
|
||||
|
||||
} // namespace
|
||||
|
||||
#endif // CLASSES_REF_MUTEX_H
|
@ -30,8 +30,6 @@
|
||||
#define CLASSES_LOCKS_H
|
||||
|
||||
#include "firebird.h"
|
||||
#include "fb_atomic.h"
|
||||
#include "RefCounted.h"
|
||||
#include "../jrd/gdsassert.h"
|
||||
|
||||
#ifdef WIN_NT
|
||||
@ -288,19 +286,6 @@ public:
|
||||
#endif //WIN_NT
|
||||
|
||||
|
||||
// mutex with reference count
|
||||
// This class is useful if mutex can be "deleted" by the
|
||||
// code between enter and leave calls
|
||||
class RefMutex : public Mutex, public RefCounted
|
||||
{
|
||||
public:
|
||||
RefMutex() {}
|
||||
explicit RefMutex(MemoryPool& pool) : Mutex(pool) {}
|
||||
};
|
||||
|
||||
|
||||
class RefMutexGuard; // forward declaration
|
||||
|
||||
// RAII holder
|
||||
class MutexLockGuard
|
||||
{
|
||||
@ -323,116 +308,13 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
// Forbid copy constructor
|
||||
MutexLockGuard(const MutexLockGuard& source);
|
||||
|
||||
// Forbidden to avoid errors
|
||||
MutexLockGuard(const RefMutex*);
|
||||
|
||||
// This constructor should be available only from RefMutexGuard
|
||||
friend class RefMutexGuard;
|
||||
explicit MutexLockGuard(RefMutex& refLock)
|
||||
: lock(&refLock)
|
||||
{
|
||||
lock->enter();
|
||||
}
|
||||
// Forbid copying
|
||||
MutexLockGuard(const MutexLockGuard&);
|
||||
MutexLockGuard& operator=(const MutexLockGuard&);
|
||||
|
||||
Mutex* lock;
|
||||
};
|
||||
|
||||
|
||||
class RefMutexGuard : public Reference, public MutexLockGuard
|
||||
{
|
||||
public:
|
||||
explicit RefMutexGuard(RefMutex& alock)
|
||||
: Reference(alock), MutexLockGuard(alock)
|
||||
{ }
|
||||
|
||||
private:
|
||||
// Forbid copy constructor
|
||||
RefMutexGuard(const RefMutexGuard& source);
|
||||
};
|
||||
|
||||
|
||||
template <typename T>
|
||||
class DefaultRefCounted
|
||||
{
|
||||
public:
|
||||
static int addRef(T* object)
|
||||
{
|
||||
return object->addRef();
|
||||
}
|
||||
|
||||
static int release(T* object)
|
||||
{
|
||||
return object->release();
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class NotRefCounted
|
||||
{
|
||||
public:
|
||||
static int addRef(T*)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int release(T*)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <typename Mtx, typename RefCounted = DefaultRefCounted<Mtx> >
|
||||
class EnsureUnlock
|
||||
{
|
||||
public:
|
||||
explicit EnsureUnlock(Mtx& mutex)
|
||||
{
|
||||
m_mutex = &mutex;
|
||||
RefCounted::addRef(m_mutex);
|
||||
m_locked = 0;
|
||||
}
|
||||
|
||||
~EnsureUnlock()
|
||||
{
|
||||
while (m_locked)
|
||||
leave();
|
||||
RefCounted::release(m_mutex);
|
||||
}
|
||||
|
||||
void enter()
|
||||
{
|
||||
m_mutex->enter();
|
||||
m_locked++;
|
||||
}
|
||||
|
||||
bool tryEnter()
|
||||
{
|
||||
if (m_mutex->tryEnter())
|
||||
{
|
||||
m_locked++;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void leave()
|
||||
{
|
||||
m_mutex->leave();
|
||||
m_locked--;
|
||||
}
|
||||
|
||||
private:
|
||||
Mtx* m_mutex;
|
||||
int m_locked;
|
||||
};
|
||||
|
||||
typedef EnsureUnlock<Mutex, NotRefCounted<Mutex> > MutexEnsureUnlock;
|
||||
typedef EnsureUnlock<RefMutex> RefMutexEnsureUnlock;
|
||||
|
||||
} //namespace Firebird
|
||||
|
||||
#endif // CLASSES_LOCKS_H
|
||||
|
@ -124,6 +124,7 @@
|
||||
#include "../jrd/IntlManager.h"
|
||||
#include "../common/classes/fb_tls.h"
|
||||
#include "../common/classes/ClumpletReader.h"
|
||||
#include "../common/classes/RefMutex.h"
|
||||
#include "../common/utils_proto.h"
|
||||
#include "../jrd/DebugInterface.h"
|
||||
|
||||
|
@ -38,6 +38,7 @@
|
||||
#include "../auth/trusted/AuthSspi.h"
|
||||
#include "../common/classes/fb_string.h"
|
||||
#include "../common/classes/ClumpletWriter.h"
|
||||
#include "../common/classes/RefMutex.h"
|
||||
#include "../common/StatusHolder.h"
|
||||
|
||||
#if !defined(SUPERCLIENT) && !defined(EMBEDDED)
|
||||
@ -571,14 +572,11 @@ struct rem_port : public Firebird::GlobalStorage, public Firebird::RefCounted
|
||||
#endif
|
||||
|
||||
// sync objects
|
||||
Firebird::RefMutex* const port_sync;
|
||||
Firebird::Reference port_sync_reference;
|
||||
Firebird::RefPtr<Firebird::RefMutex> port_sync;
|
||||
#ifdef REM_SERVER
|
||||
Firebird::RefMutex* const port_que_sync;
|
||||
Firebird::Reference port_que_reference;
|
||||
Firebird::RefPtr<Firebird::RefMutex> port_que_sync;
|
||||
#endif
|
||||
Firebird::RefMutex* const port_write_sync;
|
||||
Firebird::Reference port_write_reference;
|
||||
Firebird::RefPtr<Firebird::RefMutex> port_write_sync;
|
||||
|
||||
// port function pointers (C "emulation" of virtual functions)
|
||||
int (*port_accept)(rem_port*, const p_cnct*);
|
||||
@ -654,13 +652,10 @@ struct rem_port : public Firebird::GlobalStorage, public Firebird::RefCounted
|
||||
public:
|
||||
rem_port(rem_port_t t, size_t rpt) :
|
||||
port_sync(FB_NEW(getPool()) Firebird::RefMutex()),
|
||||
port_sync_reference(*port_sync),
|
||||
#ifdef REM_SERVER
|
||||
port_que_sync(FB_NEW(getPool()) Firebird::RefMutex()),
|
||||
port_que_reference(*port_que_sync),
|
||||
#endif
|
||||
port_write_sync(FB_NEW(getPool()) Firebird::RefMutex()),
|
||||
port_write_reference(*port_write_sync),
|
||||
port_accept(0), port_disconnect(0), port_receive_packet(0), port_send_packet(0),
|
||||
port_send_partial(0), port_connect(0), port_request(0), port_select_multi(0),
|
||||
port_type(t), port_state(PENDING), port_client_arch(arch_generic),
|
||||
@ -802,7 +797,7 @@ public:
|
||||
bool select_multi(UCHAR* buffer, SSHORT bufsize, SSHORT* length, RemPortPtr& port);
|
||||
|
||||
#ifdef REM_SERVER
|
||||
bool haveRecvData() const
|
||||
bool haveRecvData()
|
||||
{
|
||||
Firebird::RefMutexGuard queGuard(*port_que_sync);
|
||||
return ((port_receive.x_handy > 0) || (port_qoffset < port_queue.getCount()));
|
||||
|
Loading…
Reference in New Issue
Block a user