diff --git a/extensions/mysql/mysql/MyBasicResults.cpp b/extensions/mysql/mysql/MyBasicResults.cpp index 41e20dc4..44cd499a 100644 --- a/extensions/mysql/mysql/MyBasicResults.cpp +++ b/extensions/mysql/mysql/MyBasicResults.cpp @@ -306,7 +306,6 @@ DBResult MyBasicResults::CopyBlob(unsigned int columnId, void *buffer, size_t ma MyQuery::MyQuery(MyDatabase *db, MYSQL_RES *res) : m_pParent(db), m_rs(res) { - m_pParent->IncReferenceCount(); m_InsertID = m_pParent->GetInsertID(); m_AffectedRows = m_pParent->GetAffectedRows(); } @@ -371,9 +370,6 @@ void MyQuery::Destroy() mysql_free_result(m_rs.m_pRes); } - /* Tell our parent we're done */ - m_pParent->Close(); - /* Self destruct */ delete this; } diff --git a/extensions/mysql/mysql/MyBasicResults.h b/extensions/mysql/mysql/MyBasicResults.h index ac418095..1a14a19e 100644 --- a/extensions/mysql/mysql/MyBasicResults.h +++ b/extensions/mysql/mysql/MyBasicResults.h @@ -1,5 +1,5 @@ /** - * vim: set ts=4 : + * vim: set ts=4 sw=4 tw=99 noet : * ============================================================================= * SourceMod MySQL Extension * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved. @@ -91,7 +91,7 @@ public: // Used by the driver to implement GetInsertIDForQuery()/GetAffectedRows unsigned int GetInsertID(); unsigned int GetAffectedRows(); private: - MyDatabase *m_pParent; + ke::Ref m_pParent; MyBasicResults m_rs; unsigned int m_InsertID; unsigned int m_AffectedRows; diff --git a/extensions/mysql/mysql/MyDatabase.cpp b/extensions/mysql/mysql/MyDatabase.cpp index 9b338ed1..74825bfb 100644 --- a/extensions/mysql/mysql/MyDatabase.cpp +++ b/extensions/mysql/mysql/MyDatabase.cpp @@ -1,5 +1,5 @@ /** - * vim: set ts=4 : + * vim: set ts=4 sw=4 tw=99 noet : * ============================================================================= * SourceMod MySQL Extension * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved. @@ -87,7 +87,7 @@ DBType GetOurType(enum_field_types type) } MyDatabase::MyDatabase(MYSQL *mysql, const DatabaseInfo *info, bool persistent) -: m_mysql(mysql), m_refcount(1), m_pFullLock(NULL), m_bPersistent(persistent) +: m_mysql(mysql), m_bPersistent(persistent) { m_Host.assign(info->host); m_Database.assign(info->database); @@ -101,50 +101,24 @@ MyDatabase::MyDatabase(MYSQL *mysql, const DatabaseInfo *info, bool persistent) m_Info.driver = NULL; m_Info.maxTimeout = info->maxTimeout; m_Info.port = info->port; - - m_pRefLock = threader->MakeMutex(); } MyDatabase::~MyDatabase() { + /* Remove us from the search list */ + if (m_bPersistent) + g_MyDriver.RemoveFromList(this, true); mysql_close(m_mysql); - m_mysql = NULL; - - m_pRefLock->DestroyThis(); - if (m_pFullLock) - { - m_pFullLock->DestroyThis(); - } } void MyDatabase::IncReferenceCount() { - m_pRefLock->Lock(); - m_refcount++; - m_pRefLock->Unlock(); + AddRef(); } bool MyDatabase::Close() { - m_pRefLock->Lock(); - if (m_refcount > 1) - { - m_refcount--; - m_pRefLock->Unlock(); - return false; - } - m_pRefLock->Unlock(); - - /* Remove us from the search list */ - if (m_bPersistent) - { - g_MyDriver.RemoveFromList(this, true); - } - - /* Finally, free our resource(s) */ - delete this; - - return true; + return !Release(); } const DatabaseInfo &MyDatabase::GetInfo() @@ -300,26 +274,17 @@ IPreparedQuery *MyDatabase::PrepareQuery(const char *query, char *error, size_t bool MyDatabase::LockForFullAtomicOperation() { - if (!m_pFullLock) - { - m_pFullLock = threader->MakeMutex(); - if (!m_pFullLock) - { - return false; - } - } - - m_pFullLock->Lock(); + if (!m_FullLock) + m_FullLock = new ke::Mutex(); + m_FullLock->Lock(); return true; } void MyDatabase::UnlockFromFullAtomicOperation() { - if (m_pFullLock) - { - m_pFullLock->Unlock(); - } + if (m_FullLock) + m_FullLock->Unlock(); } IDBDriver *MyDatabase::GetDriver() @@ -330,4 +295,4 @@ IDBDriver *MyDatabase::GetDriver() bool MyDatabase::SetCharacterSet(const char *characterset) { return mysql_set_character_set(m_mysql, characterset) == 0 ? true : false; -} \ No newline at end of file +} diff --git a/extensions/mysql/mysql/MyDatabase.h b/extensions/mysql/mysql/MyDatabase.h index 50594b6e..27cae4f2 100644 --- a/extensions/mysql/mysql/MyDatabase.h +++ b/extensions/mysql/mysql/MyDatabase.h @@ -1,5 +1,5 @@ /** - * vim: set ts=4 : + * vim: set ts=4 sw=4 tw=99 noet : * ============================================================================= * SourceMod MySQL Extension * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved. @@ -32,13 +32,16 @@ #ifndef _INCLUDE_SM_MYSQL_DATABASE_H_ #define _INCLUDE_SM_MYSQL_DATABASE_H_ +#include +#include #include "MyDriver.h" -#include class MyQuery; class MyStatement; -class MyDatabase : public IDatabase +class MyDatabase + : public IDatabase, + public ke::RefcountedThreadsafe { friend class MyQuery; friend class MyStatement; @@ -67,9 +70,7 @@ public: const DatabaseInfo &GetInfo(); private: MYSQL *m_mysql; - unsigned int m_refcount; - IMutex *m_pFullLock; - IMutex *m_pRefLock; + ke::AutoPtr m_FullLock; /* ---------- */ DatabaseInfo m_Info; diff --git a/extensions/mysql/mysql/MyDriver.cpp b/extensions/mysql/mysql/MyDriver.cpp index 54e67c0a..beb651e3 100644 --- a/extensions/mysql/mysql/MyDriver.cpp +++ b/extensions/mysql/mysql/MyDriver.cpp @@ -1,5 +1,5 @@ /** - * vim: set ts=4 : + * vim: set ts=4 sw=4 tw=99 noet : * ============================================================================= * SourceMod MySQL Extension * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved. @@ -154,6 +154,8 @@ bool CompareField(const char *str1, const char *str2) IDatabase *MyDriver::Connect(const DatabaseInfo *info, bool persistent, char *error, size_t maxlength) { + ke::AutoLock lock(&m_Lock); + if (persistent) { /* Try to find a matching persistent connection */ @@ -194,6 +196,7 @@ IDatabase *MyDriver::Connect(const DatabaseInfo *info, bool persistent, char *er void MyDriver::RemoveFromList(MyDatabase *pdb, bool persistent) { + ke::AutoLock lock(&m_Lock); if (persistent) { m_PermDbs.remove(pdb); diff --git a/extensions/mysql/mysql/MyDriver.h b/extensions/mysql/mysql/MyDriver.h index 863df84e..3d3114e8 100644 --- a/extensions/mysql/mysql/MyDriver.h +++ b/extensions/mysql/mysql/MyDriver.h @@ -1,5 +1,5 @@ /** - * vim: set ts=4 : + * vim: set ts=4 sw=4 tw=99 noet : * ============================================================================= * SourceMod MySQL Extension * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved. @@ -32,6 +32,7 @@ #ifndef _INCLUDE_SM_MYSQL_DRIVER_H_ #define _INCLUDE_SM_MYSQL_DRIVER_H_ +#define SOURCEMOD_SQL_DRIVER_CODE #include #include #if defined PLATFORM_WINDOWS @@ -46,6 +47,7 @@ #include #include +#include using namespace SourceMod; using namespace SourceHook; @@ -71,6 +73,7 @@ public: void Shutdown(); void RemoveFromList(MyDatabase *pdb, bool persistent); private: + ke::Mutex m_Lock; Handle_t m_MyHandle; List m_TempDbs; List m_PermDbs; diff --git a/extensions/mysql/mysql/MyStatement.cpp b/extensions/mysql/mysql/MyStatement.cpp index c643af32..b3b001a5 100644 --- a/extensions/mysql/mysql/MyStatement.cpp +++ b/extensions/mysql/mysql/MyStatement.cpp @@ -48,8 +48,6 @@ MyStatement::MyStatement(MyDatabase *db, MYSQL_STMT *stmt) m_bind = NULL; } - m_pParent->IncReferenceCount(); - m_pRes = mysql_stmt_result_metadata(stmt); m_Results = false; } @@ -75,9 +73,6 @@ MyStatement::~MyStatement() mysql_free_result(m_pRes); } mysql_stmt_close(m_stmt); - - /* Tell the parent database that we're done referencing it */ - m_pParent->Close(); } void MyStatement::Destroy() diff --git a/extensions/mysql/mysql/MyStatement.h b/extensions/mysql/mysql/MyStatement.h index 5cad0af6..2064b643 100644 --- a/extensions/mysql/mysql/MyStatement.h +++ b/extensions/mysql/mysql/MyStatement.h @@ -1,5 +1,5 @@ /** - * vim: set ts=4 : + * vim: set ts=4 sw=4 tw=99 noet : * ============================================================================= * SourceMod MySQL Extension * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved. @@ -69,7 +69,7 @@ private: void *CopyBlob(unsigned int param, const void *blobptr, size_t length); private: MYSQL *m_mysql; - MyDatabase *m_pParent; + ke::Ref m_pParent; MYSQL_STMT *m_stmt; MYSQL_BIND *m_bind; MYSQL_RES *m_pRes; diff --git a/extensions/mysql/sdk/smsdk_config.h b/extensions/mysql/sdk/smsdk_config.h index 047ec0b9..cf2cdd2e 100644 --- a/extensions/mysql/sdk/smsdk_config.h +++ b/extensions/mysql/sdk/smsdk_config.h @@ -67,6 +67,6 @@ //#define SMEXT_ENABLE_MEMUTILS //#define SMEXT_ENABLE_GAMEHELPERS //#define SMEXT_ENABLE_TIMERSYS -#define SMEXT_ENABLE_THREADER +//#define SMEXT_ENABLE_THREADER #endif // _INCLUDE_SOURCEMOD_EXTENSION_CONFIG_H_ diff --git a/extensions/sqlite/driver/SqDatabase.cpp b/extensions/sqlite/driver/SqDatabase.cpp index 7686edda..91811aa5 100644 --- a/extensions/sqlite/driver/SqDatabase.cpp +++ b/extensions/sqlite/driver/SqDatabase.cpp @@ -1,5 +1,5 @@ /** - * vim: set ts=4 : + * vim: set ts=4 sw=4 tw=99 noet : * ============================================================================= * SourceMod SQLite Extension * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved. @@ -34,47 +34,25 @@ #include "SqQuery.h" SqDatabase::SqDatabase(sqlite3 *sq3, bool persistent) : - m_sq3(sq3), m_refcount(1), m_pFullLock(NULL), m_Persistent(persistent) + m_sq3(sq3), m_Persistent(persistent) { - m_pRefLock = threader->MakeMutex(); } SqDatabase::~SqDatabase() { - m_pRefLock->DestroyThis(); - if (m_pFullLock) - { - m_pFullLock->DestroyThis(); - } + if (m_Persistent) + g_SqDriver.RemovePersistent(this); sqlite3_close(m_sq3); } void SqDatabase::IncReferenceCount() { - m_pRefLock->Lock(); - m_refcount++; - m_pRefLock->Unlock(); + AddRef(); } bool SqDatabase::Close() { - m_pRefLock->Lock(); - if (m_refcount > 1) - { - m_refcount--; - m_pRefLock->Unlock(); - return false; - } - m_pRefLock->Unlock(); - - if (m_Persistent) - { - g_SqDriver.RemovePersistent(this); - } - - delete this; - - return true; + return !Release(); } const char *SqDatabase::GetError(int *errorCode/* =NULL */) @@ -84,26 +62,17 @@ const char *SqDatabase::GetError(int *errorCode/* =NULL */) bool SqDatabase::LockForFullAtomicOperation() { - if (!m_pFullLock) - { - m_pFullLock = threader->MakeMutex(); - if (!m_pFullLock) - { - return false; - } - } - - m_pFullLock->Lock(); + if (!m_FullLock) + m_FullLock = new ke::Mutex(); + m_FullLock->Lock(); return true; } void SqDatabase::UnlockFromFullAtomicOperation() { - if (m_pFullLock) - { - m_pFullLock->Unlock(); - } + if (m_FullLock) + m_FullLock->Unlock(); } IDBDriver *SqDatabase::GetDriver() @@ -259,4 +228,4 @@ bool SqDatabase::SetCharacterSet(const char *characterset) { // sqlite only supports utf8 and utf16 - by the time the database is created. It's too late here. return false; -} \ No newline at end of file +} diff --git a/extensions/sqlite/driver/SqDatabase.h b/extensions/sqlite/driver/SqDatabase.h index 72b2405c..7fb9231f 100644 --- a/extensions/sqlite/driver/SqDatabase.h +++ b/extensions/sqlite/driver/SqDatabase.h @@ -1,5 +1,5 @@ /** - * vim: set ts=4 : + * vim: set ts=4 sw=4 tw=99 noet : * ============================================================================= * SourceMod SQLite Extension * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved. @@ -32,10 +32,13 @@ #ifndef _INCLUDE_SQLITE_SOURCEMOD_DATABASE_H_ #define _INCLUDE_SQLITE_SOURCEMOD_DATABASE_H_ -#include +#include +#include #include "SqDriver.h" -class SqDatabase : public IDatabase +class SqDatabase + : public IDatabase, + public ke::RefcountedThreadsafe { public: SqDatabase(sqlite3 *sq3, bool persistent); @@ -63,9 +66,7 @@ public: sqlite3 *GetDb(); private: sqlite3 *m_sq3; - unsigned int m_refcount; - IMutex *m_pFullLock; - IMutex *m_pRefLock; + ke::AutoPtr m_FullLock; bool m_Persistent; String m_LastError; int m_LastErrorCode; diff --git a/extensions/sqlite/driver/SqDriver.cpp b/extensions/sqlite/driver/SqDriver.cpp index beb865fc..27026183 100644 --- a/extensions/sqlite/driver/SqDriver.cpp +++ b/extensions/sqlite/driver/SqDriver.cpp @@ -1,5 +1,5 @@ /** - * vim: set ts=4 : + * vim: set ts=4 sw=4 tw=99 noet : * ============================================================================= * SourceMod SQLite Extension * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved. @@ -66,24 +66,16 @@ int busy_handler(void *unused1, int unused2) SqDriver::SqDriver() { m_Handle = BAD_HANDLE; - m_pOpenLock = NULL; m_bThreadSafe = false; } void SqDriver::Initialize() { - m_pOpenLock = threader->MakeMutex(); - InitializeThreadSafety(); } void SqDriver::Shutdown() { - if (m_pOpenLock) - { - m_pOpenLock->DestroyThis(); - } - if (m_bThreadSafe) { sqlite3_enable_shared_cache(0); @@ -158,8 +150,7 @@ inline bool IsPathSepChar(char c) IDatabase *SqDriver::Connect(const DatabaseInfo *info, bool persistent, char *error, size_t maxlength) { - /* We wrap most of the open process in a mutex just to be safe */ - m_pOpenLock->Lock(); + ke::AutoLock lock(&m_OpenLock); /* Format our path */ char path[PLATFORM_MAX_PATH]; @@ -189,7 +180,6 @@ IDatabase *SqDriver::Connect(const DatabaseInfo *info, bool persistent, char *er if (!libsys->CreateFolder(fullpath)) { strncopy(error, "Could not create or open \"data\" folder\"", maxlength); - m_pOpenLock->Unlock(); return NULL; } } @@ -237,7 +227,6 @@ IDatabase *SqDriver::Connect(const DatabaseInfo *info, bool persistent, char *er if ((*iter).path.compare(fullpath) == 0) { (*iter).db->IncReferenceCount(); - m_pOpenLock->Unlock(); return (*iter).db; } } @@ -250,7 +239,6 @@ IDatabase *SqDriver::Connect(const DatabaseInfo *info, bool persistent, char *er { strncopy(error, sqlite3_errmsg(sql), maxlength); sqlite3_close(sql); - m_pOpenLock->Unlock(); return NULL; } @@ -266,13 +254,13 @@ IDatabase *SqDriver::Connect(const DatabaseInfo *info, bool persistent, char *er m_Cache.push_back(pinfo); } - m_pOpenLock->Unlock(); - return pdb; } void SqDriver::RemovePersistent(IDatabase *pdb) { + ke::AutoLock lock(&m_OpenLock); + List::iterator iter; for (iter = m_Cache.begin(); iter != m_Cache.end(); iter++) { diff --git a/extensions/sqlite/driver/SqDriver.h b/extensions/sqlite/driver/SqDriver.h index f73d1092..77bb3a69 100644 --- a/extensions/sqlite/driver/SqDriver.h +++ b/extensions/sqlite/driver/SqDriver.h @@ -1,5 +1,5 @@ /** - * vim: set ts=4 : + * vim: set ts=4 sw=4 tw=99 noet : * ============================================================================= * SourceMod SQLite Extension * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved. @@ -32,10 +32,11 @@ #ifndef _INCLUDE_SQLITE_SOURCEMOD_DRIVER_H_ #define _INCLUDE_SQLITE_SOURCEMOD_DRIVER_H_ +#define SOURCEMOD_SQL_DRIVER_CODE #include -#include #include #include +#include #include "sqlite-source/sqlite3.h" using namespace SourceMod; @@ -70,7 +71,7 @@ public: void RemovePersistent(IDatabase *pdb); private: Handle_t m_Handle; - IMutex *m_pOpenLock; + ke::Mutex m_OpenLock; List m_Cache; bool m_bThreadSafe; }; diff --git a/extensions/sqlite/driver/SqQuery.cpp b/extensions/sqlite/driver/SqQuery.cpp index b1753e81..063d395a 100644 --- a/extensions/sqlite/driver/SqQuery.cpp +++ b/extensions/sqlite/driver/SqQuery.cpp @@ -36,14 +36,12 @@ SqQuery::SqQuery(SqDatabase *parent, sqlite3_stmt *stmt) : { m_ParamCount = sqlite3_bind_parameter_count(m_pStmt); m_ColCount = sqlite3_column_count(m_pStmt); - m_pParent->IncReferenceCount(); } SqQuery::~SqQuery() { delete m_pResults; sqlite3_finalize(m_pStmt); - m_pParent->Close(); } IResultSet *SqQuery::GetResultSet() diff --git a/extensions/sqlite/driver/SqQuery.h b/extensions/sqlite/driver/SqQuery.h index 16bef53f..ca726091 100644 --- a/extensions/sqlite/driver/SqQuery.h +++ b/extensions/sqlite/driver/SqQuery.h @@ -1,5 +1,5 @@ /** - * vim: set ts=4 : + * vim: set ts=4 sw=4 tw=99 noet : * ============================================================================= * SourceMod SQLite Extension * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved. @@ -32,6 +32,7 @@ #ifndef _INCLUDE_SQLITE_SOURCEMOD_QUERY_H_ #define _INCLUDE_SQLITE_SOURCEMOD_QUERY_H_ +#include #include "SqDatabase.h" #include "SqResults.h" @@ -81,7 +82,7 @@ public: //IResultRow public: sqlite3_stmt *GetStmt(); private: - SqDatabase *m_pParent; + ke::Ref m_pParent; sqlite3_stmt *m_pStmt; SqResults *m_pResults; unsigned int m_ParamCount; diff --git a/extensions/sqlite/extension.h b/extensions/sqlite/extension.h index bf5716f5..a758f947 100644 --- a/extensions/sqlite/extension.h +++ b/extensions/sqlite/extension.h @@ -37,6 +37,7 @@ * @brief Sample extension code header. */ +#define SOURCEMOD_SQL_DRIVER_CODE #include "smsdk_ext.h" diff --git a/extensions/sqlite/sdk/smsdk_config.h b/extensions/sqlite/sdk/smsdk_config.h index 2f6cb852..a447d412 100644 --- a/extensions/sqlite/sdk/smsdk_config.h +++ b/extensions/sqlite/sdk/smsdk_config.h @@ -67,7 +67,7 @@ //#define SMEXT_ENABLE_MEMUTILS //#define SMEXT_ENABLE_GAMEHELPERS //#define SMEXT_ENABLE_TIMERSYS -#define SMEXT_ENABLE_THREADER +//#define SMEXT_ENABLE_THREADER #define SMEXT_ENABLE_LIBSYS #endif // _INCLUDE_SOURCEMOD_EXTENSION_CONFIG_H_ diff --git a/public/IDBDriver.h b/public/IDBDriver.h index 68b4dcf0..3a5de881 100644 --- a/public/IDBDriver.h +++ b/public/IDBDriver.h @@ -608,6 +608,7 @@ namespace SourceMod */ virtual bool SetCharacterSet(const char *characterset) =0; +#if !defined(SOURCEMOD_SQL_DRIVER_CODE) /** * @brief Wrapper around IncReferenceCount(), for ke::Ref. */ @@ -621,6 +622,7 @@ namespace SourceMod void Release() { Close(); } +#endif }; /** diff --git a/public/amtl/am-atomics.h b/public/amtl/am-atomics.h new file mode 100644 index 00000000..a933468e --- /dev/null +++ b/public/amtl/am-atomics.h @@ -0,0 +1,100 @@ +// vim: set sts=8 ts=2 sw=2 tw=99 et: +// +// Copyright (C) 2013, David Anderson and AlliedModders LLC +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of AlliedModders LLC nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + +#ifndef _include_amtl_atomics_h_ +#define _include_amtl_atomics_h_ + +#include + +namespace ke { + +#if defined(_MSC_VER) +extern "C" { + long __cdecl _InterlockedIncrement(long volatile *dest); + long __cdecl _InterlockedDecrement(long volatile *dest); +} +# pragma intrinsic(_InterlockedIncrement); +# pragma intrinsic(_InterlockedDecrement); +#endif + +template +struct AtomicOps; + +template <> +struct AtomicOps<4> +{ + typedef int Type; + +#if defined(_MSC_VER) + static int Increment(int *ptr) { + return _InterlockedIncrement(ptr); + } + static int Decrement(int *ptr) { + return _InterlockedDecrement(ptr); + }; +#elif defined(__GNUC__) + // x86/x64 notes: When using GCC < 4.8, this will compile to a spinlock. + // On 4.8+, or when using Clang, we'll get the more optimal "lock addl" + // variant. + static int Increment(int *ptr) { + return __sync_add_and_fetch(ptr, 1); + } + static int Decrement(int *ptr) { + return __sync_sub_and_fetch(ptr, 1); + } +#endif +}; + +class AtomicRefCount +{ + typedef AtomicOps Ops; + + public: + AtomicRefCount(uintptr_t value) + : value_(value) + { + } + + void increment() { + Ops::Increment(&value_); + } + + // Return false if all references are gone. + bool decrement() { + return Ops::Decrement(&value_) != 0; + } + + private: + Ops::Type value_; +}; + +} + +#endif // _include_amtl_atomics_h_ + diff --git a/public/amtl/am-refcounting-threadsafe.h b/public/amtl/am-refcounting-threadsafe.h new file mode 100644 index 00000000..a37b39d4 --- /dev/null +++ b/public/amtl/am-refcounting-threadsafe.h @@ -0,0 +1,68 @@ +// vim: set sts=8 ts=2 sw=2 tw=99 et: +// +// Copyright (C) 2013, David Anderson and AlliedModders LLC +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of AlliedModders LLC nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + +#ifndef _include_amtl_ts_refcounting_h_ +#define _include_amtl_ts_refcounting_h_ + +#include +#include + +namespace ke { + +template +class RefcountedThreadsafe +{ + public: + RefcountedThreadsafe() + : refcount_(1) + { + } + + void AddRef() { + refcount_.increment(); + } + bool Release() { + if (!refcount_.decrement()) { + delete static_cast(this); + return false; + } + return true; + } + + protected: + ~RefcountedThreadsafe() { + } + + private: + AtomicRefCount refcount_; +}; + +} // namespace ke + +#endif // _include_amtl_ts_refcounting_h_