Merge branch 'master' into V2MultiWear

This commit is contained in:
Aleric Inglewood
2012-06-27 04:26:44 +02:00
9 changed files with 242 additions and 46 deletions

View File

@@ -49,7 +49,10 @@
template<typename T> struct AIReadAccessConst;
template<typename T> struct AIReadAccess;
template<typename T> struct AIWriteAccess;
template<typename T> struct AIAccessConst;
template<typename T> struct AIAccess;
template<typename T> struct AISTAccessConst;
template<typename T> struct AISTAccess;
#if LL_WINDOWS
template<typename T> class AIThreadSafeBits;
@@ -398,6 +401,7 @@ class AIThreadSafeSimple : public AIThreadSafeBits<T>
{
protected:
// Only this one may access the object (through ptr()).
friend struct AIAccessConst<T>;
friend struct AIAccess<T>;
// Locking control.
@@ -509,13 +513,13 @@ public:
};
/**
* @brief Write lock object and provide read/write access.
* @brief Write lock object and provide read access.
*/
template<typename T>
struct AIAccess
struct AIAccessConst
{
//! Construct a AIAccess from a non-constant AIThreadSafeSimple.
AIAccess(AIThreadSafeSimple<T>& wrapper) : mWrapper(wrapper)
//! Construct a AIAccessConst from a constant AIThreadSafeSimple.
AIAccessConst(AIThreadSafeSimple<T> const& wrapper) : mWrapper(const_cast<AIThreadSafeSimple<T>&>(wrapper))
#if AI_NEED_ACCESS_CC
, mIsCopyConstructed(false)
#endif
@@ -524,12 +528,12 @@ struct AIAccess
}
//! Access the underlaying object for (read and) write access.
T* operator->() const { return this->mWrapper.ptr(); }
T const* operator->() const { return this->mWrapper.ptr(); }
//! Access the underlaying object for (read and) write access.
T& operator*() const { return *this->mWrapper.ptr(); }
T const& operator*() const { return *this->mWrapper.ptr(); }
~AIAccess()
~AIAccessConst()
{
#if AI_NEED_ACCESS_CC
if (mIsCopyConstructed) return;
@@ -538,17 +542,204 @@ struct AIAccess
}
protected:
AIThreadSafeSimple<T>& mWrapper; //!< Reference to the object that we provide access to.
AIThreadSafeSimple<T>& mWrapper; //!< Reference to the object that we provide access to.
#if AI_NEED_ACCESS_CC
bool mIsCopyConstructed;
public:
AIAccess(AIAccess const& orig) : mWrapper(orig.mWrapper), mIsCopyConstructed(true) { }
AIAccessConst(AIAccessConst const& orig) : mWrapper(orig.mWrapper), mIsCopyConstructed(true) { }
#else
private:
// Disallow copy constructing directly.
AIAccess(AIAccess const&);
AIAccessConst(AIAccessConst const&);
#endif
};
/**
* @brief Write lock object and provide read/write access.
*/
template<typename T>
struct AIAccess : public AIAccessConst<T>
{
//! Construct a AIAccess from a non-constant AIThreadSafeSimple.
AIAccess(AIThreadSafeSimple<T>& wrapper) : AIAccessConst<T>(wrapper) { }
//! Access the underlaying object for (read and) write access.
T* operator->() const { return this->mWrapper.ptr(); }
//! Access the underlaying object for (read and) write access.
T& operator*() const { return *this->mWrapper.ptr(); }
};
/**
* @brief A wrapper class for objects that should only be accessed by a single thread.
*
* Use AITHREADSAFESINGLETHREAD to define instances of any type, and use AISTAccess
* to get access to the instance.
*
* For example,
*
* <code>
* class Foo { public: Foo(int, int); };
*
* AITHREADSAFESINGLETHREAD(Foo, foo, (2, 3));
*
* AISTAccess<Foo> foo_w(foo);
* // Use foo_w-> for read and write access.
*/
template<typename T>
class AIThreadSafeSingleThread : public AIThreadSafeBits<T>
{
protected:
// Only these one may access the object (through ptr()).
friend struct AISTAccessConst<T>;
friend struct AISTAccess<T>;
// For use by AIThreadSafeSingleThreadDC.
AIThreadSafeSingleThread(void)
#ifdef LL_DEBUG
: mAccessed(false)
#endif
{ }
#ifdef LL_DEBUG
mutable bool mAccessed;
mutable apr_os_thread_t mTheadID;
void accessed(void) const
{
if (!mAccessed)
{
mAccessed = true;
mTheadID = apr_os_thread_current();
}
else
{
llassert_always(apr_os_thread_equal(mTheadID, apr_os_thread_current()));
}
}
#endif
public:
// Only for use by AITHREADSAFESINGLETHREAD, see below.
AIThreadSafeSingleThread(T* object)
#ifdef LL_DEBUG
: mAccessed(false)
#endif
{
llassert(object == AIThreadSafeBits<T>::ptr());
}
};
/**
* @brief A wrapper class for objects that should only be accessed by a single thread.
*
* This class is the same as an AIThreadSafeSingleThread wrapper, except that it can only
* be used for default constructed objects.
*
* For example, instead of
*
* <code>
* Foo foo;
* </code>
*
* One would use
*
* <code>
* AIThreadSafeSingleThreadDC<Foo> foo;
* </code>
*
* The advantage over AITHREADSAFESINGLETHREAD is that this object can be allocated with
* new on the heap. For example:
*
* <code>
* AIThreadSafeSingleThreadDC<Foo>* ptr = new AIThreadSafeSingleThreadDC<Foo>;
* </code>
*
* which is not possible with AITHREADSAFESINGLETHREAD.
*/
template<typename T>
class AIThreadSafeSingleThreadDC : public AIThreadSafeSingleThread<T>
{
public:
// Construct a wrapper around a default constructed object.
AIThreadSafeSingleThreadDC(void) { new (AIThreadSafeSingleThread<T>::ptr()) T; }
};
/**
* @brief Instantiate a static, global or local object of a given type wrapped in AIThreadSafeSingleThread, using an arbitrary constructor.
*
* For example, instead of doing
*
* <code>
* Foo foo(x, y);
* static Bar bar;
* </code>
*
* One can instantiate a thread-safe instance with
*
* <code>
* AITHREADSAFESINGLETHREAD(Foo, foo, (x, y));
* static AITHREADSAFESINGLETHREAD(Bar, bar, );
* </code>
*
* Note: This macro does not allow to allocate such object on the heap.
* If that is needed, have a look at AIThreadSafeSingleThreadDC.
*/
#define AITHREADSAFESINGLETHREAD(type, var, paramlist) AIThreadSafeSingleThread<type> var(new (var.memory()) type paramlist)
/**
* @brief Access single threaded object for read access.
*/
template<typename T>
struct AISTAccessConst
{
//! Construct a AISTAccessConst from a constant AIThreadSafeSingleThread.
AISTAccessConst(AIThreadSafeSingleThread<T> const& wrapper) : mWrapper(const_cast<AIThreadSafeSingleThread<T>&>(wrapper))
{
#if LL_DEBUG
wrapper.accessed();
#endif
}
//! Access the underlaying object for read access.
T const* operator->() const { return this->mWrapper.ptr(); }
//! Access the underlaying object for read write access.
T const& operator*() const { return *this->mWrapper.ptr(); }
protected:
AIThreadSafeSingleThread<T>& mWrapper; //!< Reference to the object that we provide access to.
#if AI_NEED_ACCESS_CC
public:
AISTAccessConst(AISTAccessConst const& orig) : mWrapper(orig.mWrapper) { }
#else
private:
// Disallow copy constructing directly.
AISTAccessConst(AISTAccessConst const&);
#endif
};
/**
* @brief Access single threaded object for read/write access.
*/
template<typename T>
struct AISTAccess : public AISTAccessConst<T>
{
//! Construct a AISTAccess from a non-constant AIThreadSafeSingleThread.
AISTAccess(AIThreadSafeSingleThread<T>& wrapper) : AISTAccessConst<T>(wrapper)
{
#if LL_DEBUG
wrapper.accessed();
#endif
}
//! Access the underlaying object for (read and) write access.
T* operator->() const { return this->mWrapper.ptr(); }
//! Access the underlaying object for (read and) write access.
T& operator*() const { return *this->mWrapper.ptr(); }
};
#endif

View File

@@ -88,7 +88,7 @@ bool ll_apr_warn_status(apr_status_t status)
void ll_apr_assert_status(apr_status_t status)
{
llassert(ll_apr_warn_status(status) == false);
llassert(!ll_apr_warn_status(status));
}
//---------------------------------------------------------------------
@@ -146,7 +146,7 @@ apr_status_t LLAPRFile::open(std::string const& filename, apr_int32_t flags, acc
apr_status_t status;
{
apr_pool_t* apr_file_open_pool;
apr_pool_t* apr_file_open_pool; // The use of apr_pool_t is OK here.
// This is a temporary variable for a pool that is passed directly to apr_file_open below.
if (access_type == short_lived)
{
@@ -199,7 +199,6 @@ apr_status_t LLAPRFile::open(const std::string& filename, apr_int32_t flags, BOO
// File I/O
S32 LLAPRFile::read(void *buf, S32 nbytes)
{
//llassert_always(mFile); (ASC-TUDCC) -HgB
if(!mFile)
{
llwarns << "apr mFile is removed by somebody else. Can not read." << llendl ;
@@ -222,7 +221,6 @@ S32 LLAPRFile::read(void *buf, S32 nbytes)
S32 LLAPRFile::write(const void *buf, S32 nbytes)
{
// llassert_always(mFile); (ASC-TUDCC) -HgB
if(!mFile)
{
llwarns << "apr mFile is removed by somebody else. Can not write." << llendl ;

View File

@@ -113,7 +113,7 @@ typedef LLAtomic32<U32> LLAtomicU32;
typedef LLAtomic32<S32> LLAtomicS32;
// File IO convenience functions.
// Returns NULL if the file fails to openm sets *sizep to file size of not NULL
// Returns NULL if the file fails to open, sets *sizep to file size if not NULL
// abbreviated flags
#define LL_APR_R (APR_READ) // "r"
#define LL_APR_W (APR_CREATE|APR_TRUNCATE|APR_WRITE) // "w"
@@ -131,7 +131,7 @@ typedef LLAtomic32<S32> LLAtomicS32;
// especially do not put some time-costly operations between open() and close().
// otherwise it might lock the APRFilePool.
//there are two different apr_pools the APRFile can use:
// 1, a temperary pool passed to an APRFile function, which is used within this function and only once.
// 1, a temporary pool passed to an APRFile function, which is used within this function and only once.
// 2, a global pool.
//
@@ -189,7 +189,7 @@ public:
};
/**
* @brief Function which approprately logs error or remains quiet on
* @brief Function which appropriately logs error or remains quiet on
* APR_SUCCESS.
* @return Returns <code>true</code> if status is an error condition.
*/

View File

@@ -1,5 +1,5 @@
/**
* @file LLAPRPool.cpp
* @file llaprpool.cpp
*
* Copyright (c) 2010, Aleric Inglewood.
*

View File

@@ -1,5 +1,5 @@
/**
* @file LLAPRPool.h
* @file llaprpool.h
* @brief Implementation of LLAPRPool.
*
* Copyright (c) 2010, Aleric Inglewood.
@@ -60,9 +60,9 @@ extern void ll_init_apr();
class LL_COMMON_API LLAPRPool
{
protected:
apr_pool_t* mPool; //!< Pointer to the underlaying pool. NULL if not initialized.
apr_pool_t* mPool; //!< Pointer to the underlaying pool. NULL if not initialized.
LLAPRPool* mParent; //!< Pointer to the parent pool, if any. Only valid when mPool is non-zero.
apr_os_thread_t mOwner; //!< The thread that owns this memory pool. Only valid when mPool is non-zero.
apr_os_thread_t mOwner; //!< The thread that owns this memory pool. Only valid when mPool is non-zero.
public:
//! Construct an uninitialized (destructed) pool.

View File

@@ -402,6 +402,15 @@ LLMutexBase::LLMutexBase() :
{
}
bool LLMutexBase::isSelfLocked() const
{
#if LL_DARWIN
return mLockingThread == LLThread::currentID();
#else
return mLockingThread == local_thread_ID;
#endif
}
void LLMutexBase::lock()
{
#if LL_DARWIN
@@ -435,15 +444,6 @@ void LLMutexBase::unlock()
apr_thread_mutex_unlock(mAPRMutexp);
}
bool LLMutexBase::isSelfLocked()
{
#if LL_DARWIN
return mLockingThread == LLThread::currentID();
#else
return mLockingThread == local_thread_ID;
#endif
}
//----------------------------------------------------------------------------
//static

View File

@@ -41,6 +41,9 @@
#ifdef SHOW_ASSERT
extern LL_COMMON_API bool is_main_thread(void);
#define ASSERT_SINGLE_THREAD do { static apr_os_thread_t first_thread_id = apr_os_thread_current(); llassert(apr_os_thread_equal(first_thread_id, apr_os_thread_current())); } while(0)
#else
#define ASSERT_SINGLE_THREAD do { } while(0)
#endif
class LLThread;
@@ -74,7 +77,7 @@ class LL_COMMON_API LLThread
private:
static U32 sIDIter;
static LLAtomicS32 sCount;
public:
typedef enum e_thread_status
{
@@ -181,15 +184,18 @@ public:
LLMutexBase() ;
void lock(); //blocks
void lock(); // blocks
void unlock();
// Returns true if lock was obtained successfully.
bool tryLock() { return !APR_STATUS_IS_EBUSY(apr_thread_mutex_trylock(mAPRMutexp)); }
// non-blocking, but does do a lock/unlock so not free
bool isLocked() { bool is_not_locked = tryLock(); if (is_not_locked) unlock(); return !is_not_locked; }
// Returns true if locked by this thread.
bool isSelfLocked() const;
// get ID of locking thread
bool isSelfLocked(); //return true if locked in a same thread
U32 lockingThread() const { return mLockingThread; }
protected:

View File

@@ -1372,13 +1372,13 @@ void LLVertexBuffer::setupVertexArray()
//glVertexattribIPointer requires GLSL 1.30 or later
if (gGLManager.mGLSLVersionMajor > 1 || gGLManager.mGLSLVersionMinor >= 30)
{
glVertexAttribIPointer(i, attrib_size[i], attrib_type[i], sTypeSize[i], (void*) mOffsets[i]);
glVertexAttribIPointer(i, attrib_size[i], attrib_type[i], sTypeSize[i], reinterpret_cast<void*>(mOffsets[i]));
}
#endif
}
else
{
glVertexAttribPointerARB(i, attrib_size[i], attrib_type[i], attrib_normalized[i], sTypeSize[i], (void*) mOffsets[i]);
glVertexAttribPointerARB(i, attrib_size[i], attrib_type[i], attrib_normalized[i], sTypeSize[i], reinterpret_cast<void*>(mOffsets[i]));
}
}
else

View File

@@ -38,6 +38,7 @@
#endif
#include "linden_common.h"
#include "llaprpool.h"
extern "C" {
#include <dbus/dbus-glib.h>
@@ -55,8 +56,8 @@ extern "C" {
#undef LL_DBUS_SYM
static bool sSymsGrabbed = false;
static apr_pool_t *sSymDBUSDSOMemoryPool = NULL;
static apr_dso_handle_t *sSymDBUSDSOHandleG = NULL;
static LLAPRPool sSymDBUSDSOMemoryPool; // Used for sSymDBUSDSOHandleG (and what it is pointing at?)
static apr_dso_handle_t* sSymDBUSDSOHandleG = NULL;
bool grab_dbus_syms(std::string dbus_dso_name)
{
@@ -74,12 +75,12 @@ bool grab_dbus_syms(std::string dbus_dso_name)
#define LL_DBUS_SYM(REQUIRED, DBUSSYM, RTN, ...) do{rv = apr_dso_sym((apr_dso_handle_sym_t*)&ll##DBUSSYM, sSymDBUSDSOHandle, #DBUSSYM); if (rv != APR_SUCCESS) {INFOMSG("Failed to grab symbol: %s", #DBUSSYM); if (REQUIRED) sym_error = true;} else DEBUGMSG("grabbed symbol: %s from %p", #DBUSSYM, (void*)ll##DBUSSYM);}while(0)
//attempt to load the shared library
apr_pool_create(&sSymDBUSDSOMemoryPool, NULL);
sSymDBUSDSOMemoryPool.create();
#ifdef LL_STANDALONE
void *dso_handle = dlopen(dbus_dso_name.c_str(), RTLD_NOW | RTLD_GLOBAL);
rv = (!dso_handle)?APR_EDSOOPEN:apr_os_dso_handle_put(&sSymDBUSDSOHandle,
dso_handle, sSymDBUSDSOMemoryPool);
dso_handle, sSymDBUSDSOMemoryPool());
if ( APR_SUCCESS == rv )
#else
@@ -113,6 +114,10 @@ bool grab_dbus_syms(std::string dbus_dso_name)
#undef LL_DBUS_SYM
sSymsGrabbed = rtn;
if (!sSymsGrabbed)
{
sSymDBUSDSOMemoryPool.destroy();
}
return rtn;
}
@@ -127,13 +132,9 @@ void ungrab_dbus_syms()
apr_dso_unload(sSymDBUSDSOHandleG);
sSymDBUSDSOHandleG = NULL;
}
if ( sSymDBUSDSOMemoryPool )
{
apr_pool_destroy(sSymDBUSDSOMemoryPool);
sSymDBUSDSOMemoryPool = NULL;
}
sSymDBUSDSOMemoryPool.destroy();
// NULL-out all of the symbols we'd grabbed
#define LL_DBUS_SYM(REQUIRED, DBUSSYM, RTN, ...) do{ll##DBUSSYM = NULL;}while(0)
#include "llappviewerlinux_api_dbus_syms_raw.inc"