diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 00000000..40c909fb --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "public/amtl"] + path = public/amtl + url = https://github.com/alliedmodders/amtl diff --git a/AMBuildScript b/AMBuildScript index f7c0d143..65305bdf 100644 --- a/AMBuildScript +++ b/AMBuildScript @@ -326,7 +326,7 @@ class SMConfig(object): os.path.join(builder.sourcePath, 'public'), os.path.join(builder.sourcePath, 'public', 'extensions'), os.path.join(builder.sourcePath, 'sourcepawn', 'include'), - os.path.join(builder.sourcePath, 'public', 'amtl'), + os.path.join(builder.sourcePath, 'public', 'amtl', 'include'), ] return compiler diff --git a/core/MenuStyle_Base.h b/core/MenuStyle_Base.h index 78a98e54..a9afe7b6 100644 --- a/core/MenuStyle_Base.h +++ b/core/MenuStyle_Base.h @@ -48,19 +48,19 @@ public: style = 0; access = 0; } - CItem(ke::Moveable other) - : info(ke::Move(other->info)), - display(ke::Move(other->display)) + CItem(CItem &&other) + : info(ke::Move(other.info)), + display(ke::Move(other.display)) { - style = other->style; - access = other->access; + style = other.style; + access = other.access; } - CItem & operator =(ke::Moveable other) + CItem & operator =(CItem &&other) { - info = ke::Move(other->info); - display = ke::Move(other->display); - style = other->style; - access = other->access; + info = ke::Move(other.info); + display = ke::Move(other.display); + style = other.style; + access = other.access; return *this; } diff --git a/core/logic/AMBuilder b/core/logic/AMBuilder index 368ccc3a..af59296f 100644 --- a/core/logic/AMBuilder +++ b/core/logic/AMBuilder @@ -6,7 +6,7 @@ binary.compiler.cxxincludes += [ os.path.join(builder.sourcePath, 'core', 'logic'), os.path.join(builder.sourcePath, 'public'), os.path.join(builder.sourcePath, 'sourcepawn', 'include'), - os.path.join(builder.sourcePath, 'public', 'amtl'), + os.path.join(builder.sourcePath, 'public', 'amtl', 'include'), os.path.join(SM.mms_root, 'core', 'sourcehook') ] binary.compiler.defines += [ diff --git a/core/logic/smn_adt_trie.cpp b/core/logic/smn_adt_trie.cpp index 94a57678..7b706489 100644 --- a/core/logic/smn_adt_trie.cpp +++ b/core/logic/smn_adt_trie.cpp @@ -63,11 +63,11 @@ public: : control_(0) { } - Entry(ke::Moveable other) + Entry(Entry &&other) { - control_ = other->control_; - data_ = other->data_; - other->control_ = 0; + control_ = other.control_; + data_ = other.data_; + other.control_ = 0; } ~Entry() diff --git a/extensions/sdkhooks/extension.h b/extensions/sdkhooks/extension.h index f1e1b297..7beb86ab 100644 --- a/extensions/sdkhooks/extension.h +++ b/extensions/sdkhooks/extension.h @@ -6,7 +6,7 @@ #include #include #include -#include +#include #include #include diff --git a/extensions/sdktools/hooks.h b/extensions/sdktools/hooks.h index 261e158d..28e1f286 100644 --- a/extensions/sdktools/hooks.h +++ b/extensions/sdktools/hooks.h @@ -35,7 +35,7 @@ class CUserCmd; #include "extension.h" -#include "amtl/am-vector.h" +#include #include "vtable_hook_helper.h" class CHookManager : IPluginsListener, IFeatureProvider diff --git a/public/amtl b/public/amtl new file mode 160000 index 00000000..1bb5196c --- /dev/null +++ b/public/amtl @@ -0,0 +1 @@ +Subproject commit 1bb5196ce39ff3ed59445e51f9223734d4bcf886 diff --git a/public/amtl/am-allocator-policies.h b/public/amtl/am-allocator-policies.h deleted file mode 100644 index 5f9712bf..00000000 --- a/public/amtl/am-allocator-policies.h +++ /dev/null @@ -1,65 +0,0 @@ -// 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_allocatorpolicies_h_ -#define _include_amtl_allocatorpolicies_h_ - -#include -#include - -namespace ke { - -// The default system allocator policy will crash on out-of-memory. -class SystemAllocatorPolicy -{ - public: - void reportOutOfMemory() { - fprintf(stderr, "OUT OF MEMORY\n"); - abort(); - } - void reportAllocationOverflow() { - fprintf(stderr, "OUT OF MEMORY\n"); - abort(); - } - - public: - void free(void *memory) { - ::free(memory); - } - void *malloc(size_t bytes) { - void *ptr = ::malloc(bytes); - if (!ptr) - reportOutOfMemory(); - return ptr; - } -}; - -} - -#endif // _include_amtl_allocatorpolicies_h_ diff --git a/public/amtl/am-atomics.h b/public/amtl/am-atomics.h deleted file mode 100644 index e32d1df9..00000000 --- a/public/amtl/am-atomics.h +++ /dev/null @@ -1,102 +0,0 @@ -// 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> -{ -#if defined(_MSC_VER) - typedef long Type; - - static Type Increment(Type *ptr) { - return _InterlockedIncrement(ptr); - } - static Type Decrement(Type *ptr) { - return _InterlockedDecrement(ptr); - }; -#elif defined(__GNUC__) - typedef int Type; - - // 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 Type Increment(Type *ptr) { - return __sync_add_and_fetch(ptr, 1); - } - static Type Decrement(Type *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-fixedarray.h b/public/amtl/am-fixedarray.h deleted file mode 100644 index 1925a780..00000000 --- a/public/amtl/am-fixedarray.h +++ /dev/null @@ -1,103 +0,0 @@ -// vim: set sts=8 ts=2 sw=2 tw=99 et: -// -// Copyright (C) 2013-2014, 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_fixedarray_h_ -#define _include_amtl_fixedarray_h_ - -#include -#include -#include - -namespace ke { - -template -class FixedArray : public AllocPolicy -{ - public: - FixedArray(size_t length, AllocPolicy = AllocPolicy()) { - length_ = length; - data_ = (T *)this->malloc(sizeof(T) * length_); - if (!data_) - return; - - for (size_t i = 0; i < length_; i++) - new (&data_[i]) T(); - } - ~FixedArray() { - for (size_t i = 0; i < length_; i++) - data_[i].~T(); - this->free(data_); - } - - // This call may be skipped if the allocator policy is infallible. - bool initialize() { - return length_ == 0 || !!data_; - } - - size_t length() const { - return length_; - } - T &operator [](size_t index) { - return at(index); - } - const T &operator [](size_t index) const { - return at(index); - } - T &at(size_t index) { - assert(index < length()); - return data_[index]; - } - const T &at(size_t index) const { - assert(index < length()); - return data_[index]; - } - void set(size_t index, const T &t) { - assert(index < length()); - data_[index] = t; - } - void set(size_t index, ke::Moveable t) { - assert(index < length()); - data_[index] = t; - } - - T *buffer() const { - return data_; - } - - private: - FixedArray(const FixedArray &other) KE_DELETE; - FixedArray &operator =(const FixedArray &other) KE_DELETE; - - private: - size_t length_; - T *data_; -}; - -} // namespace ke - -#endif // _include_amtl_fixedarray_h_ diff --git a/public/amtl/am-float.h b/public/amtl/am-float.h deleted file mode 100644 index e53f25a0..00000000 --- a/public/amtl/am-float.h +++ /dev/null @@ -1,50 +0,0 @@ -// 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_float_h_ -#define _include_amtl_float_h_ - -#include -#include - -namespace ke { - -static inline bool -IsNaN(double v) -{ -#ifdef _MSC_VER - return !!_isnan(v); -#else - return isnan(v); -#endif -} - -} // namespace ke - -#endif // _include_amtl_float_h_ diff --git a/public/amtl/am-hashmap.h b/public/amtl/am-hashmap.h deleted file mode 100644 index 7d5c3839..00000000 --- a/public/amtl/am-hashmap.h +++ /dev/null @@ -1,201 +0,0 @@ -// 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_hashmap_h_ -#define _include_amtl_hashmap_h_ - -#include - -namespace ke { - -// Template parameters: -// -// K - Key type. -// V - Value type. -// HashPolicy - A struct with a hash and comparator function for each lookup type: -// static uint32_t hash(const Type &value); -// static bool matches(const Type &value, const K &key); -// -// All types that match a given key, must compute the same hash. -// -// Note that like HashTable, a HashMap is not usable until init() has been called. -template -class HashMap : public AllocPolicy -{ - private: - struct Entry - { - K key; - V value; - - Entry() - { - } - Entry(Moveable other) - : key(Moveable(other->key)), - value(Moveable(other->value)) - { - } - - Entry(const K &aKey, const V &aValue) - : key(aKey), - value(aValue) - { } - Entry(const K &aKey, Moveable aValue) - : key(aKey), - value(aValue) - { } - Entry(Moveable aKey, const V &aValue) - : key(aKey), - value(aValue) - { } - Entry(Moveable aKey, Moveable aValue) - : key(aKey), - value(aValue) - { } - }; - - struct Policy - { - typedef Entry Payload; - - template - static uint32_t hash(const Lookup &key) { - return HashPolicy::hash(key); - } - - template - static bool matches(const Lookup &key, const Payload &payload) { - return HashPolicy::matches(key, payload.key); - } - }; - - typedef HashTable Internal; - - public: - HashMap(AllocPolicy ap = AllocPolicy()) - : table_(ap) - { - } - - // capacity must be a power of two. - bool init(size_t capacity = 16) { - return table_.init(capacity); - } - - typedef typename Internal::Result Result; - typedef typename Internal::Insert Insert; - typedef typename Internal::iterator iterator; - - template - Result find(const Lookup &key) { - return table_.find(key); - } - - template - Insert findForAdd(const Lookup &key) { - return table_.findForAdd(key); - } - - template - void removeIfExists(const Lookup &key) { - return table_.remove(key); - } - - void remove(Result &r) { - table_.remove(r); - } - - // The map must not have been mutated in between findForAdd() and add(). - // The Insert object is still valid after add() returns, however. - bool add(Insert &i, const K &key, const V &value) { - Entry entry(key, value); - return table_.add(i, ke::Move(entry)); - } - bool add(Insert &i, Moveable key, const V &value) { - Entry entry(key, value); - return table_.add(i, ke::Move(entry)); - } - bool add(Insert &i, const K &key, Moveable value) { - Entry entry(key, value); - return table_.add(i, ke::Move(entry)); - } - bool add(Insert &i, Moveable key, Moveable value) { - Entry entry(key, value); - return table_.add(i, ke::Move(entry)); - } - bool add(Insert &i, Moveable key) { - Entry entry(key, V()); - return table_.add(i, ke::Move(entry)); - } - - // This can be used to avoid compiler constructed temporaries, since AMTL - // does not yet support move semantics. If you use this, the key and value - // must be set after. - bool add(Insert &i) { - return table_.add(i); - } - - iterator iter() { - return iterator(&table_); - } - - void clear() { - table_.clear(); - } - - size_t elements() const { - return table_.elements(); - } - - size_t estimateMemoryUse() const { - return table_.estimateMemoryUse(); - } - - private: - Internal table_; -}; - -template -struct PointerPolicy -{ - static inline uint32_t hash(T *p) { - return HashPointer(p); - } - static inline bool matches(T *p1, T *p2) { - return p1 == p2; - } -}; - -} - -#endif // _include_amtl_hashmap_h_ diff --git a/public/amtl/am-hashset.h b/public/amtl/am-hashset.h deleted file mode 100644 index 13f8eb8f..00000000 --- a/public/amtl/am-hashset.h +++ /dev/null @@ -1,129 +0,0 @@ -// 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_hashmap_h_ -#define _include_amtl_hashmap_h_ - -#include - -namespace ke { - -// Template parameters: -// -// K - Key type. -// HashPolicy - A struct with a hash and comparator function for each lookup type: -// static uint32_t hash(const Type &value); -// static bool matches(const Type &value, const K &key); -// -// Like HashMap and HashTable, init() must be called to construct the set. -template -class HashSet : public AllocPolicy -{ - struct Policy { - typedef K Payload; - - template - static uint32_t hash(const Lookup &key) { - return HashPolicy::hash(key); - } - - template - static bool matches(const Lookup &key, const Payload &payload) { - return HashPolicy::matches(key, payload); - } - }; - - typedef HashTable Internal; - - public: - HashSet(AllocPolicy ap = AllocPolicy()) - : table_(ap) - { - } - - // capacity must be a power of two. - bool init(size_t capacity = 16) { - return table_.init(capacity); - } - - typedef typename Internal::Result Result; - typedef typename Internal::Insert Insert; - - template - Result find(const Lookup &key) { - return table_.find(key); - } - - template - Insert findForAdd(const Lookup &key) { - return table_.findForAdd(key); - } - - template - void removeIfExists(const Lookup &key) { - return table_.remove(key); - } - - void remove(Result &r) { - table_.remove(r); - } - - // The map must not have been mutated in between findForAdd() and add(). - // The Insert object is still valid after add() returns, however. - bool add(Insert &i, const K &key) { - return table_.add(i, key); - } - bool add(Insert &i, Moveable key) { - return table_.add(i, key); - } - - // This can be used to avoid compiler constructed temporaries, since AMTL - // does not yet support move semantics. If you use this, the key and value - // must be set after. - bool add(Insert &i) { - return table_.add(i); - } - - void clear() { - table_.clear(); - } - - size_t estimateMemoryUse() const { - return table_.estimateMemoryUse(); - } - - private: - Internal table_; -}; - -} - -#endif // _include_amtl_hashset_h_ diff --git a/public/amtl/am-hashtable.h b/public/amtl/am-hashtable.h deleted file mode 100644 index 1101a247..00000000 --- a/public/amtl/am-hashtable.h +++ /dev/null @@ -1,631 +0,0 @@ -// 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_KEIMA_HASHTABLE_H_ -#define _INCLUDE_KEIMA_HASHTABLE_H_ - -#include -#include -#include -#include "am-allocator-policies.h" -#include "am-utility.h" -#include "am-moveable.h" - -namespace ke { - -namespace detail { - template - class HashTableEntry - { - uint32_t hash_; - T t_; - - public: - static const uint32_t kFreeHash = 0; - static const uint32_t kRemovedHash = 1; - - public: - void setHash(uint32_t hash) { - hash_ = hash; - } - void construct() { - new (&t_) T(); - } - void construct(const T &t) { - new (&t_) T(t); - } - void construct(Moveable t) { - new (&t_) T(t); - } - uint32_t hash() const { - return hash_; - } - void setRemoved() { - destruct(); - hash_ = kRemovedHash; - } - void setFree() { - destruct(); - hash_ = kFreeHash; - } - void initialize() { - hash_ = kFreeHash; - } - void destruct() { - if (isLive()) - t_.~T(); - } - bool removed() const { - return hash_ == kRemovedHash; - } - bool free() const { - return hash_ == kFreeHash; - } - bool isLive() const { - return hash_ > kRemovedHash; - } - T &payload() { - assert(isLive()); - return t_; - } - bool sameHash(uint32_t hash) const { - return hash_ == hash; - } - - private: - HashTableEntry(const HashTableEntry &other) KE_DELETE; - HashTableEntry &operator =(const HashTableEntry &other) KE_DELETE; - }; -} - -// The HashPolicy for the table must have the following members: -// -// Payload -// static uint32_t hash(const LookupType &key); -// static bool matches(const LookupType &key, const Payload &other); -// -// Payload must be a type, and LookupType is any type that lookups will be -// performed with (these functions can be overloaded). Example: -// -// struct Policy { -// typedef KeyValuePair Payload; -// static uint32 hash(const Key &key) { -// ... -// } -// static bool matches(const Key &key, const KeyValuePair &pair) { -// ... -// } -// }; -// -// Note that the table is not usable until init() has been called. -// -template -class HashTable : public AllocPolicy -{ - friend class iterator; - - typedef typename HashPolicy::Payload Payload; - typedef detail::HashTableEntry Entry; - - private: - static const uint32_t kMinCapacity = 16; - static const uint32_t kMaxCapacity = INT_MAX / sizeof(Entry); - - template - uint32_t computeHash(const Key &key) { - // Multiply by golden ratio. - uint32_t hash = HashPolicy::hash(key) * 0x9E3779B9; - if (hash == Entry::kFreeHash || hash == Entry::kRemovedHash) - hash += 2; - return hash; - } - - Entry *createTable(uint32_t capacity) { - assert(capacity <= kMaxCapacity); - - Entry *table = (Entry *)this->malloc(capacity * sizeof(Entry)); - if (!table) - return NULL; - - for (size_t i = 0; i < capacity; i++) - table[i].initialize(); - - return table; - } - - public: - class Result - { - friend class HashTable; - - Entry *entry_; - - Entry &entry() { - return *entry_; - } - - public: - Result(Entry *entry) - : entry_(entry) - { } - - Payload * operator ->() { - return &entry_->payload(); - } - Payload & operator *() { - return entry_->payload(); - } - - bool found() const { - return entry_->isLive(); - } - }; - - class Insert : public Result - { - uint32_t hash_; - - public: - Insert(Entry *entry, uint32_t hash) - : Result(entry), - hash_(hash) - { - } - - uint32_t hash() const { - return hash_; - } - }; - - private: - class Probulator { - uint32_t hash_; - uint32_t capacity_; - - public: - Probulator(uint32_t hash, uint32_t capacity) - : hash_(hash), - capacity_(capacity) - { - assert(IsPowerOfTwo(capacity_)); - } - - uint32_t entry() const { - return hash_ & (capacity_ - 1); - } - uint32_t next() { - hash_++; - return entry(); - } - }; - - bool underloaded() const { - // Check if the table is underloaded: < 25% entries used. - return (capacity_ > kMinCapacity) && (nelements_ + ndeleted_ < capacity_ / 4); - } - bool overloaded() const { - // Grow if the table is overloaded: > 75% entries used. - return (nelements_ + ndeleted_) > ((capacity_ / 2) + (capacity_ / 4)); - } - - bool shrink() { - if ((capacity_ >> 1) < minCapacity_) - return true; - return changeCapacity(capacity_ >> 1); - } - - bool grow() { - if (capacity_ >= kMaxCapacity) { - this->reportAllocationOverflow(); - return false; - } - return changeCapacity(capacity_ << 1); - } - - bool changeCapacity(uint32_t newCapacity) { - assert(newCapacity <= kMaxCapacity); - - Entry *newTable = createTable(newCapacity); - if (!newTable) - return false; - - Entry *oldTable = table_; - uint32_t oldCapacity = capacity_; - - table_ = newTable; - capacity_ = newCapacity; - ndeleted_ = 0; - - for (uint32_t i = 0; i < oldCapacity; i++) { - Entry &oldEntry = oldTable[i]; - if (oldEntry.isLive()) { - Insert p = insertUnique(oldEntry.hash()); - p.entry().setHash(p.hash()); - p.entry().construct(Moveable(oldEntry.payload())); - } - oldEntry.destruct(); - } - this->free(oldTable); - - return true; - } - - // For use when the key is known to be unique. - Insert insertUnique(uint32_t hash) { - Probulator probulator(hash, capacity_); - - Entry *e = &table_[probulator.entry()]; - for (;;) { - if (e->free() || e->removed()) - break; - e = &table_[probulator.next()]; - } - - return Insert(e, hash); - } - - template - Result lookup(const Key &key) { - uint32_t hash = computeHash(key); - Probulator probulator(hash, capacity_); - - Entry *e = &table_[probulator.entry()]; - for (;;) { - if (e->free()) - break; - if (e->isLive() && - e->sameHash(hash) && - HashPolicy::matches(key, e->payload())) - { - return Result(e); - } - e = &table_[probulator.next()]; - } - - return Result(e); - } - - template - Insert lookupForAdd(const Key &key) { - uint32_t hash = computeHash(key); - Probulator probulator(hash, capacity_); - - Entry *e = &table_[probulator.entry()]; - for (;;) { - if (!e->isLive()) - break; - if (e->sameHash(hash) && HashPolicy::matches(key, e->payload())) - break; - e = &table_[probulator.next()]; - } - - return Insert(e, hash); - } - - bool internalAdd(Insert &i) { - assert(!i.found()); - - // If the entry is deleted, just re-use the slot. - if (i.entry().removed()) { - ndeleted_--; - } else { - // Otherwise, see if we're at max capacity. - if (nelements_ == kMaxCapacity) { - this->reportAllocationOverflow(); - return false; - } - - // Check if the table is over or underloaded. The table is always at - // least 25% free, so this check is enough to guarantee one free slot. - // (Without one free slot, insertion search could infinite loop.) - uint32_t oldCapacity = capacity_; - if (!checkDensity()) - return false; - - // If the table changed size, we need to find a new insertion point. - // Note that a removed entry is impossible: either we caught it above, - // or we just resized and no entries are removed. - if (capacity_ != oldCapacity) - i = insertUnique(i.hash()); - } - - nelements_++; - i.entry().setHash(i.hash()); - return true; - } - - void removeEntry(Entry &e) { - assert(e.isLive()); - e.setRemoved(); - ndeleted_++; - nelements_--; - } - - public: - HashTable(AllocPolicy ap = AllocPolicy()) - : AllocPolicy(ap), - capacity_(0), - nelements_(0), - ndeleted_(0), - table_(NULL), - minCapacity_(kMinCapacity) - { - } - - ~HashTable() - { - for (uint32_t i = 0; i < capacity_; i++) - table_[i].destruct(); - this->free(table_); - } - - bool init(uint32_t capacity = 0) { - if (capacity < kMinCapacity) { - capacity = kMinCapacity; - } else if (capacity > kMaxCapacity) { - this->reportAllocationOverflow(); - return false; - } - - minCapacity_ = capacity; - - assert(IsPowerOfTwo(capacity)); - capacity_ = capacity; - - table_ = createTable(capacity_); - if (!table_) - return false; - - return true; - } - - // The Result object must not be used past mutating table operations. - template - Result find(const Key &key) { - return lookup(key); - } - - // The Insert object must not be used past mutating table operations. - template - Insert findForAdd(const Key &key) { - return lookupForAdd(key); - } - - template - void removeIfExists(const Key &key) { - Result r = find(key); - if (!r.found()) - return; - remove(r); - } - - void remove(Result &r) { - assert(r.found()); - removeEntry(r.entry()); - } - - // The table must not have been mutated in between findForAdd() and add(). - // The Insert object is still valid after add() returns, however. - bool add(Insert &i, const Payload &payload) { - if (!internalAdd(i)) - return false; - i.entry().construct(payload); - return true; - } - bool add(Insert &i, Moveable payload) { - if (!internalAdd(i)) - return false; - i.entry().construct(payload); - return true; - } - bool add(Insert &i) { - if (!internalAdd(i)) - return false; - i.entry().construct(); - return true; - } - - bool checkDensity() { - if (underloaded()) - return shrink(); - if (overloaded()) - return grow(); - return true; - } - - void clear() { - for (size_t i = 0; i < capacity_; i++) { - table_[i].setFree(); - } - ndeleted_ = 0; - nelements_ = 0; - } - - size_t elements() const { - return nelements_; - } - - size_t estimateMemoryUse() const { - return sizeof(Entry) * capacity_; - } - - public: - // It is illegal to mutate a HashTable during iteration. - class iterator - { - public: - iterator(HashTable *table) - : table_(table), - i_(table->table_), - end_(table->table_ + table->capacity_) - { - while (i_ < end_ && !i_->isLive()) - i_++; - } - - bool empty() const { - return i_ == end_; - } - - void erase() { - assert(!empty()); - table_->removeEntry(*i_); - } - - Payload *operator ->() const { - return &i_->payload(); - } - Payload &operator *() const { - return i_->payload(); - } - - void next() { - do { - i_++; - } while (i_ < end_ && !i_->isLive()); - } - - private: - HashTable *table_; - Entry *i_; - Entry *end_; - }; - - private: - HashTable(const HashTable &other) KE_DELETE; - HashTable &operator =(const HashTable &other) KE_DELETE; - - private: - uint32_t capacity_; - uint32_t nelements_; - uint32_t ndeleted_; - Entry *table_; - uint32_t minCapacity_; -}; - -// Bob Jenkin's one-at-a-time hash function[1]. -// -// [1] http://burtleburtle.net/bob/hash/doobs.html -class CharacterStreamHasher -{ - uint32_t hash; - - public: - CharacterStreamHasher() - : hash(0) - { } - - void add(char c) { - hash += c; - hash += (hash << 10); - hash ^= (hash >> 6); - } - - void add(const char *s, size_t length) { - for (size_t i = 0; i < length; i++) - add(s[i]); - } - - uint32_t result() { - hash += (hash << 3); - hash ^= (hash >> 11); - hash += (hash << 15); - return hash; - } -}; - -static inline uint32_t -HashCharSequence(const char *s, size_t length) -{ - CharacterStreamHasher hasher; - hasher.add(s, length); - return hasher.result(); -} - -static inline uint32_t -FastHashCharSequence(const char *s, size_t length) -{ - uint32_t hash = 0; - for (size_t i = 0; i < length; i++) - hash = s[i] + (hash << 6) + (hash << 16) - hash; - return hash; -} - -// From http://burtleburtle.net/bob/hash/integer.html -static inline uint32_t -HashInt32(int32_t a) -{ - a = (a ^ 61) ^ (a >> 16); - a = a + (a << 3); - a = a ^ (a >> 4); - a = a * 0x27d4eb2d; - a = a ^ (a >> 15); - return a; -} - -// From http://www.cris.com/~Ttwang/tech/inthash.htm -static inline uint32_t -HashInt64(int64_t key) -{ - key = (~key) + (key << 18); // key = (key << 18) - key - 1; - key = key ^ (uint64_t(key) >> 31); - key = key * 21; // key = (key + (key << 2)) + (key << 4); - key = key ^ (uint64_t(key) >> 11); - key = key + (key << 6); - key = key ^ (uint64_t(key) >> 22); - return uint32_t(key); -} - -template -static inline uint32_t -HashInteger(uintptr_t value); - -template <> -inline uint32_t -HashInteger<4>(uintptr_t value) -{ - return HashInt32(value); -} - -template <> -inline uint32_t -HashInteger<8>(uintptr_t value) -{ - return HashInt64(value); -} - -static inline uint32_t -HashPointer(void *ptr) -{ - return HashInteger(reinterpret_cast(ptr)); -} - -} // namespace ke - -#endif // _INCLUDE_KEIMA_HASHTABLE_H_ diff --git a/public/amtl/am-inlinelist.h b/public/amtl/am-inlinelist.h deleted file mode 100644 index 99c37793..00000000 --- a/public/amtl/am-inlinelist.h +++ /dev/null @@ -1,183 +0,0 @@ -// 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_inline_list_h_ -#define _include_amtl_inline_list_h_ - -#include -#include - -namespace ke { - -template class InlineList; - -// Objects can recursively inherit from InlineListNode in order to have -// membership in an InlineList. -template -class InlineListNode -{ - friend class InlineList; - - public: - InlineListNode() - : next_(NULL), - prev_(NULL) - { - } - - InlineListNode(InlineListNode *next, InlineListNode *prev) - : next_(next), - prev_(prev) - { - } - - protected: - InlineListNode *next_; - InlineListNode *prev_; -}; - -// An InlineList is a linked list that threads link pointers through objects, -// rather than allocating node memory. A node can be in at most one list at -// any time. -// -// Since InlineLists are designed to be very cheap, there is no requirement -// that elements be removed from a list once the list is destructed. However, -// for as long as the list is alive, all of its contained nodes must also -// be alive. -template -class InlineList -{ - typedef InlineListNode Node; - - Node head_; - - // Work around a clang bug where we can't initialize with &head_ in the ctor. - inline Node *head() { - return &head_; - } - - public: - InlineList() - : head_(head(), head()) - { - } - - ~InlineList() - { -#if !defined(NDEBUG) - // Remove all items to clear their next/prev fields. - while (begin() != end()) - remove(*begin()); -#endif - } - - public: - class iterator - { - friend class InlineList; - Node *iter_; - - public: - iterator(Node *iter) - : iter_(iter) - { - } - - iterator & operator ++() { - iter_ = iter_->next; - return *this; - } - iterator operator ++(int) { - iterator old(*this); - iter_ = iter_->next_; - return old; - } - T * operator *() { - return static_cast(iter_); - } - T * operator ->() { - return static_cast(iter_); - } - bool operator !=(const iterator &where) const { - return iter_ != where.iter_; - } - bool operator ==(const iterator &where) const { - return iter_ == where.iter_; - } - }; - - iterator begin() { - return iterator(head_.next_); - } - - iterator end() { - return iterator(&head_); - } - - iterator erase(iterator &at) { - iterator next = at; - next++; - - remove(at.iter_); - - // Iterator is no longer valid. - at.iter_ = NULL; - - return next; - } - - bool empty() const { - return head_.next_ == &head_; - } - - void remove(Node *t) { - t->prev_->next_ = t->next_; - t->next_->prev_ = t->prev_; - -#if !defined(NDEBUG) - t->next_ = NULL; - t->prev_ = NULL; -#endif - } - - void append(Node *t) { - assert(!t->next_); - assert(!t->prev_); - - t->prev_ = head_.prev_; - t->next_ = &head_; - head_.prev_->next_ = t; - head_.prev_ = t; - } -}; - -} - -#endif // _include_amtl_inline_list_h_ - diff --git a/public/amtl/am-linkedlist.h b/public/amtl/am-linkedlist.h deleted file mode 100644 index 488e97a2..00000000 --- a/public/amtl/am-linkedlist.h +++ /dev/null @@ -1,309 +0,0 @@ -// 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_linkedlist_h_ -#define _include_amtl_linkedlist_h_ - -#include -#include -#include -#include -#include - -namespace ke { - -// LinkedList, analagous to std::list or SourceHook::List. Since it performs a -// malloc() and free() on every contained node, it should be avoided unless -// absolutely necessary, or for when allocation performance is not a factor. It -// is provided here to safely port old AlliedModders code to AMTL. -// -// In order to use a circular chain, LinkedList's allocation size includes -// exactly one T. If T is very large, LinkedList should be allocated on the -// heap, to avoid using the stack. -template -class LinkedList : public AllocPolicy -{ - public: - friend class iterator; - - class Node - { - public: - Node(const T &o) - : obj(o) - { - } - Node(Moveable o) - : obj(o) - { - } - - T obj; - Node *next; - Node *prev; - }; - -public: - LinkedList(AllocPolicy = AllocPolicy()) - : length_(0) - { - head()->prev = head(); - head()->next = head(); - } - ~LinkedList() { - clear(); - } - - bool append(const T &obj) { - return insertBefore(end(), obj) != end(); - } - bool append(Moveable obj) { - return insertBefore(end(), obj) != end(); - } - - bool prepend(const T &obj) { - return insertBefore(begin(), obj) != begin(); - } - bool prepend(Moveable obj) { - return insertBefore(begin(), obj) != begin(); - } - - size_t length() const { - return length_; - } - - void clear() { - Node *node = head()->next; - Node *temp; - head()->next = head(); - head()->prev = head(); - - // Iterate through the nodes until we find the sentinel again. - while (node != head()) { - temp = node->next; - freeNode(node); - node = temp; - } - length_ = 0; - } - - bool empty() const { - return (length_ == 0); - } - - T &front() { - assert(!empty()); - return head()->next->obj; - } - T &back() { - assert(!empty()); - return head()->prev->obj; - } - - private: - const Node *head() const { - return sentinel_.address(); - } - Node *head() { - return sentinel_.address(); - } - - Node *allocNode(const T &obj) { - Node *node = (Node *)this->malloc(sizeof(Node)); - if (!node) - return NULL; - new (node) Node(obj); - return node; - } - Node *allocNode(Moveable obj) { - Node *node = (Node *)this->malloc(sizeof(Node)); - if (!node) - return NULL; - new (node) Node(obj); - return node; - } - - void freeNode(Node *node) { - node->obj.~T(); - this->free(node); - } - - private: - StorageBuffer sentinel_; - size_t length_; - - public: - class iterator - { - friend class LinkedList; - - public: - iterator() - : this_(NULL) - { - } - iterator(const LinkedList &src) - : this_(src.head()) - { - } - iterator(Node *n) - : this_(n) - { - } - iterator(const iterator &where) - : this_(where.this_) - { - } - - iterator &operator --() { - if (this_) - this_ = this_->prev; - return *this; - } - iterator operator --(int) { - iterator old(*this); - if (this_) - this_ = this_->prev; - return old; - } - iterator &operator ++() { - if (this_) - this_ = this_->next; - return *this; - } - iterator operator ++(int) { - iterator old(*this); - if (this_) - this_ = this_->next; - return old; - } - - const T &operator * () const { - return this_->obj; - } - T &operator * () { - return this_->obj; - } - T *operator ->() { - return &this_->obj; - } - const T *operator ->() const { - return &(this_->obj); - } - - bool operator !=(const iterator &where) const { - return (this_ != where.this_); - } - bool operator ==(const iterator &where) const { - return (this_ == where.this_); - } - - operator bool() { - return !!this_; - } - - private: - Node *this_; - }; - - private: - // Insert obj right before where. - iterator insert(iterator where, Node *node) { - if (!node) - return where; - - Node *pWhereNode = where.this_; - - pWhereNode->prev->next = node; - node->prev = pWhereNode->prev; - pWhereNode->prev = node; - node->next = pWhereNode; - - length_++; - return iterator(node); - } - - public: - iterator begin() { - return iterator(head()->next); - } - iterator end() { - return iterator(head()); - } - iterator erase(iterator where) { - Node *pNode = where.this_; - iterator iter(where); - iter++; - - pNode->prev->next = pNode->next; - pNode->next->prev = pNode->prev; - - freeNode(pNode); - length_--; - - return iter; - } - iterator insertBefore(iterator where, const T &obj) { - return insert(where, allocNode(obj)); - } - iterator insertBefore(iterator where, Moveable obj) { - return insert(where, allocNode(obj)); - } - - public: - // Removes one instance of |obj| from the list, if found. - void remove(const T &obj) { - for (iterator b = begin(); b != end(); b++) { - if (*b == obj) { - erase(b); - break; - } - } - } - - template - iterator find(const U &equ) { - for (iterator iter = begin(); iter != end(); iter++) { - if (*iter == equ) - return iter; - } - return end(); - } - - - private: - // These are disallowed because they basically violate the failure handling - // model for AllocPolicies and are also likely to have abysmal performance. - LinkedList &operator =(const LinkedList &other) KE_DELETE; - LinkedList(const LinkedList &other) KE_DELETE; -}; - -} // namespace ke - -#endif //_INCLUDE_CSDM_LIST_H diff --git a/public/amtl/am-moveable.h b/public/amtl/am-moveable.h deleted file mode 100644 index e500dbc7..00000000 --- a/public/amtl/am-moveable.h +++ /dev/null @@ -1,73 +0,0 @@ -// 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_moveable_h_ -#define _include_amtl_moveable_h_ - -namespace ke { - -// This is a feature in C++11, but since AM projects do not have access to -// C++11 yet, we provide templates to implement move semantics. A class can -// provide a constructor for (ke::Moveable t) which containers will try -// to use. -// -// When implementing a constructor that takes a Moveable, the object being -// moved should be left in a state that is safe, since its destructor will -// be called even though it has been moved. - -template -struct Moveable -{ - public: - explicit Moveable(T &t) - : t_(t) - { - } - - T *operator ->() { - return &t_; - } - operator T &() { - return t_; - } - - private: - T &t_; -}; - -template -static inline Moveable -Move(T &t) -{ - return Moveable(t); -} - -} // namespace ke - -#endif // _include_amtl_moveable_h_ diff --git a/public/amtl/am-refcounting-threadsafe.h b/public/amtl/am-refcounting-threadsafe.h deleted file mode 100644 index 785ba62b..00000000 --- a/public/amtl/am-refcounting-threadsafe.h +++ /dev/null @@ -1,71 +0,0 @@ -// 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 { - -// See the comment above Refcounted for more information. This class is -// identical, except changing the reference count is guaranteed to be atomic -// with respect to other threads changing the reference count. -template -class RefcountedThreadsafe -{ - public: - RefcountedThreadsafe() - : refcount_(0) - { - } - - 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_ diff --git a/public/amtl/am-refcounting.h b/public/amtl/am-refcounting.h deleted file mode 100644 index ea869464..00000000 --- a/public/amtl/am-refcounting.h +++ /dev/null @@ -1,336 +0,0 @@ -// vim: set sts=8 ts=4 sw=4 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_refcounting_h_ -#define _include_amtl_refcounting_h_ - -#include -#include - -namespace ke { - -template class Ref; - -// Objects in AMTL inheriting from Refcounted will have an initial refcount -// of 0. However, in some systems (such as COM), the initial refcount is 1, -// or functions may return raw pointers that have been AddRef'd. In these -// cases it would be a mistake to use Ref<> or PassRef<>, since the object -// would leak an extra reference. -// -// This container holds a refcounted object without addrefing it. This is -// intended only for interacting with functions which return an object that -// has been manually AddRef'd. Note that this will perform a Release(), so -// so it is necessary to assign it to retain the object. -template -class AlreadyRefed -{ - public: - AlreadyRefed(T *t) - : thing_(t) - { - } - AlreadyRefed(const AlreadyRefed &other) - : thing_(other.thing_) - { - // If copy elision for some reason doesn't happen (for example, when - // returning from AdoptRef), just null out the source ref. - other.thing_ = NULL; - } - ~AlreadyRefed() { - if (thing_) - thing_->Release(); - } - - T *release() const { - return ReturnAndVoid(thing_); - } - - private: - mutable T *thing_; -}; - -template -static inline AlreadyRefed -AdoptRef(T *t) -{ - return AlreadyRefed(t); -} - -// When returning a value, we'd rather not be needlessly changing the refcount, -// so we have a special type to use for returns. -template -class PassRef -{ - public: - PassRef(T *thing) - : thing_(thing) - { - AddRef(); - } - PassRef() - : thing_(NULL) - { - } - - PassRef(const AlreadyRefed &other) - : thing_(other.release()) - { - // Don't addref, newborn means already addref'd. - } - - template - PassRef(const AlreadyRefed &other) - : thing_(other.release()) - { - // Don't addref, newborn means already addref'd. - } - - template - inline PassRef(const Ref &other); - - PassRef(const PassRef &other) - : thing_(other.release()) - { - } - template - PassRef(const PassRef &other) - : thing_(other.release()) - { - } - ~PassRef() - { - Release(); - } - - operator T &() { - return *thing_; - } - operator T *() const { - return thing_; - } - T *operator ->() const { - return operator *(); - } - T *operator *() const { - return thing_; - } - bool operator !() const { - return !thing_; - } - - T *release() const { - return ReturnAndVoid(thing_); - } - - template - PassRef &operator =(const PassRef &other) { - Release(); - thing_ = other.release(); - return *this; - } - - private: - // Disallowed operators. - PassRef &operator =(T *other); - PassRef &operator =(AlreadyRefed &other); - - void AddRef() { - if (thing_) - thing_->AddRef(); - } - void Release() { - if (thing_) - thing_->Release(); - } - - private: - mutable T *thing_; -}; - -// Classes which are refcounted should inherit from this. Note that reference -// counts start at 0 in AMTL, rather than 1. This avoids the complexity of -// having to adopt the initial ref upon allocation. However, this also means -// invoking Release() on a newly allocated object is illegal. Newborn objects -// must either be assigned to a Ref or PassRef (NOT an AdoptRef/AlreadyRefed), -// or must be deleted using |delete|. -template -class Refcounted -{ - public: - Refcounted() - : refcount_(0) - { - } - - void AddRef() { - refcount_++; - } - void Release() { - assert(refcount_ > 0); - if (--refcount_ == 0) - delete static_cast(this); - } - - protected: - ~Refcounted() { - } - - private: - uintptr_t refcount_; -}; - -// Simple class for automatic refcounting. -template -class Ref -{ - public: - Ref(T *thing) - : thing_(thing) - { - AddRef(); - } - - Ref() - : thing_(NULL) - { - } - - Ref(const Ref &other) - : thing_(other.thing_) - { - AddRef(); - } - Ref(Moveable other) - : thing_(other->thing_) - { - other->thing_ = NULL; - } - template - Ref(const Ref &other) - : thing_(*other) - { - AddRef(); - } - Ref(const PassRef &other) - : thing_(other.release()) - { - } - template - Ref(const PassRef &other) - : thing_(other.release()) - { - } - Ref(const AlreadyRefed &other) - : thing_(other.release()) - { - } - template - Ref(const AlreadyRefed &other) - : thing_(other.release()) - { - } - ~Ref() - { - Release(); - } - - T *operator ->() const { - return operator *(); - } - T *operator *() const { - return thing_; - } - operator T *() { - return thing_; - } - bool operator !() const { - return !thing_; - } - - template - Ref &operator =(S *thing) { - Release(); - thing_ = thing; - AddRef(); - return *this; - } - - template - Ref &operator =(const PassRef &other) { - Release(); - thing_ = other.release(); - return *this; - } - - template - Ref &operator =(const AlreadyRefed &other) { - Release(); - thing_ = other.release(); - return *this; - } - - Ref &operator =(const Ref &other) { - Release(); - thing_ = other.thing_; - AddRef(); - return *this; - } - - Ref &operator =(Moveable other) { - Release(); - thing_ = other->thing_; - other->thing_ = NULL; - return *this; - } - - private: - void AddRef() { - if (thing_) - thing_->AddRef(); - } - void Release() { - if (thing_) - thing_->Release(); - } - - protected: - T *thing_; -}; - -template template -PassRef::PassRef(const Ref &other) - : thing_(*other) -{ - AddRef(); -} - -} // namespace ke - -#endif // _include_amtl_refcounting_h_ - diff --git a/public/amtl/am-string.h b/public/amtl/am-string.h deleted file mode 100644 index 4e62bde2..00000000 --- a/public/amtl/am-string.h +++ /dev/null @@ -1,136 +0,0 @@ -// 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_string_h_ -#define _include_amtl_string_h_ - -#include -#include -#include -#include - -namespace ke { - -// ASCII string. -class AString -{ - public: - AString() - : length_(0) - { - } - - explicit AString(const char *str) { - set(str, strlen(str)); - } - AString(const char *str, size_t length) { - set(str, length); - } - AString(const AString &other) { - if (other.length_) - set(other.chars_, other.length_); - else - length_ = 0; - } - AString(Moveable other) - : chars_(other->chars_.take()), - length_(other->length_) - { - other->length_ = 0; - } - - AString &operator =(const char *str) { - if (str && str[0]) { - set(str, strlen(str)); - } else { - chars_ = NULL; - length_ = 0; - } - return *this; - } - AString &operator =(const AString &other) { - if (other.length_) { - set(other.chars_, other.length_); - } else { - chars_ = NULL; - length_ = 0; - } - return *this; - } - AString &operator =(Moveable other) { - chars_ = other->chars_.take(); - length_ = other->length_; - other->length_ = 0; - return *this; - } - - int compare(const char *str) const { - return strcmp(chars(), str); - } - int compare(const AString &other) const { - return strcmp(chars(), other.chars()); - } - bool operator ==(const AString &other) const { - return other.length() == length() && - memcmp(other.chars(), chars(), length()) == 0; - } - - char operator [](size_t index) const { - assert(index < length()); - return chars()[index]; - } - - size_t length() const { - return length_; - } - - const char *chars() const { - if (!chars_) - return ""; - return chars_; - } - - private: - static const size_t kInvalidLength = (size_t)-1; - - void set(const char *str, size_t length) { - chars_ = new char[length + 1]; - length_ = length; - memcpy(chars_, str, length); - chars_[length] = '\0'; - } - - private: - AutoArray chars_; - size_t length_; -}; - -} - -#endif // _include_amtl_string_h_ diff --git a/public/amtl/am-thread-posix.h b/public/amtl/am-thread-posix.h deleted file mode 100644 index c5d1b25c..00000000 --- a/public/amtl/am-thread-posix.h +++ /dev/null @@ -1,219 +0,0 @@ -// 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_thread_posix_h_ -#define _include_amtl_thread_posix_h_ - -#include -#include -#include -#include -#if defined(__linux__) -# include -#endif -#if defined(__APPLE__) -# include -#endif - -namespace ke { - -class Mutex : public Lockable -{ - public: - Mutex() { -#if !defined(NDEBUG) - int rv = -#endif - pthread_mutex_init(&mutex_, NULL); - assert(rv == 0); - } - ~Mutex() { - pthread_mutex_destroy(&mutex_); - } - - bool DoTryLock() KE_OVERRIDE { - return pthread_mutex_trylock(&mutex_) == 0; - } - - void DoLock() KE_OVERRIDE { - pthread_mutex_lock(&mutex_); - } - - void DoUnlock() KE_OVERRIDE { - pthread_mutex_unlock(&mutex_); - } - - pthread_mutex_t *raw() { - return &mutex_; - } - - private: - pthread_mutex_t mutex_; -}; - -// Currently, this class only supports single-listener CVs. -class ConditionVariable : public Lockable -{ - public: - ConditionVariable() { -#if !defined(NDEBUG) - int rv = -#endif - pthread_cond_init(&cv_, NULL); - assert(rv == 0); - } - ~ConditionVariable() { - pthread_cond_destroy(&cv_); - } - - bool DoTryLock() KE_OVERRIDE { - return mutex_.DoTryLock(); - } - void DoLock() KE_OVERRIDE { - mutex_.DoLock(); - } - void DoUnlock() KE_OVERRIDE { - mutex_.DoUnlock(); - } - - void Notify() { - AssertCurrentThreadOwns(); - pthread_cond_signal(&cv_); - } - - WaitResult Wait(size_t timeout_ms) { - AssertCurrentThreadOwns(); - -#if defined(__linux__) - struct timespec ts; - if (clock_gettime(CLOCK_REALTIME, &ts) == -1) - return Wait_Error; -#else - struct timeval tv; - gettimeofday(&tv, NULL); - - struct timespec ts; - ts.tv_sec = tv.tv_sec; - ts.tv_nsec = tv.tv_usec * 1000; -#endif - - ts.tv_sec += timeout_ms / 1000; - ts.tv_nsec += (timeout_ms % 1000) * 1000000; - if (ts.tv_nsec >= 1000000000) { - ts.tv_sec++; - ts.tv_nsec -= 1000000000; - } - - DebugSetUnlocked(); - int rv = pthread_cond_timedwait(&cv_, mutex_.raw(), &ts); - DebugSetLocked(); - - if (rv == ETIMEDOUT) - return Wait_Timeout; - if (rv == 0) - return Wait_Signaled; - return Wait_Error; - } - - WaitResult Wait() { - AssertCurrentThreadOwns(); - - DebugSetUnlocked(); - int rv = pthread_cond_wait(&cv_, mutex_.raw()); - DebugSetLocked(); - - if (rv == 0) - return Wait_Signaled; - return Wait_Error; - } - - private: - Mutex mutex_; - pthread_cond_t cv_; -}; - -class Thread -{ - struct ThreadData { - IRunnable *run; - char name[17]; - }; - public: - Thread(IRunnable *run, const char *name = NULL) { - ThreadData *data = new ThreadData; - data->run = run; - snprintf(data->name, sizeof(data->name), "%s", name ? name : ""); - - initialized_ = (pthread_create(&thread_, NULL, Main, data) == 0); - if (!initialized_) - delete data; - } - ~Thread() { - if (!Succeeded()) - return; - pthread_detach(thread_); - } - - bool Succeeded() const { - return initialized_; - } - - void Join() { - if (!Succeeded()) - return; - pthread_join(thread_, NULL); - initialized_ = false; - } - - private: - static void *Main(void *arg) { - AutoPtr data((ThreadData *)arg); - - if (data->name[0]) { -#if defined(__linux__) - prctl(PR_SET_NAME, (unsigned long)data->name); -#elif defined(__APPLE__) - int (*fn)(const char *) = (int (*)(const char *))dlsym(RTLD_DEFAULT, "pthread_setname_np"); - if (fn) - fn(data->name); -#endif - } - data->run->Run(); - return NULL; - } - - private: - bool initialized_; - pthread_t thread_; -}; - -} // namespace ke - -#endif // _include_amtl_thread_posix_h_ - diff --git a/public/amtl/am-thread-utils.h b/public/amtl/am-thread-utils.h deleted file mode 100644 index 98db2616..00000000 --- a/public/amtl/am-thread-utils.h +++ /dev/null @@ -1,265 +0,0 @@ -// 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_threads_ -#define _include_amtl_threads_ - -#include -#if defined(_MSC_VER) -# include -# include -#else -# include -#endif -#include - -// Thread primitives for SourcePawn. -// -// Linking Requirements: -// -// OS X: None (-lpthread and -ldl are optional) -// Windows: None -// Linux: -lpthread -lrt required -// -// -- Mutexes -- -// -// A Lockable is a mutual exclusion primitive. It can be owned by at most one -// thread at a time, and ownership blocks any other thread from taking taking -// ownership. Ownership must be acquired and released on the same thread. -// Lockables are not re-entrant. -// -// While a few classes support the Lockable interface, the simplest Lockable -// object that can be instantiated is a Mutex. -// -// -- Condition Variables -- -// -// A ConditionVariable provides mutually exclusive access based on a -// condition ocurring. CVs provide two capabilities: Wait(), which will block -// until the condition is triggered, and Notify(), which signals any blocking -// thread that the condition has occurred. -// -// Condition variables have an underlying mutex lock. This lock must be -// acquired before calling Wait() or Notify(). It is automatically released -// once Wait begins blocking. This operation is atomic with respect to other -// threads and the mutex. For example, it is not possible for the lock to be -// acquired by another thread in between unlocking and blocking. Since Notify -// also requires the lock to be acquired, there is no risk of an event -// accidentally dissipating into thin air because it was sent before the other -// thread began blocking. -// -// When Wait() returns, the lock is automatically re-acquired. This operation -// is NOT atomic. In between waking up and re-acquiring the lock, another -// thread may steal the lock and issue another event. Applications must -// account for this. For example, a message pump should check that there are -// no messages left to process before blocking again. -// -// Likewise, it is also not defined whether a Signal() will have any effect -// while a thread is not waiting on the monitor. This is yet another reason -// the above paragraph is so important - applications should, under a lock of -// the condition variable - check for state changes before waiting. -// -// -- Threads -- -// -// A Thread object, when created, spawns a new thread with the given callback -// (the callbacks must implement IRunnable). Threads have one method of -// interest, Join(), which will block until the thread's execution finishes. -// Deleting a thread object will free any operating system resources associated -// with that thread, if the thread has finished executing. -// -// Threads can fail to spawn; make sure to check Succeeded(). -// - -namespace ke { - -// Abstraction for getting a unique thread identifier. Debug-only. -#if defined(_MSC_VER) -typedef DWORD ThreadId; - -static inline ThreadId GetCurrentThreadId() -{ - return ::GetCurrentThreadId(); -} -#else -typedef pthread_t ThreadId; - -static inline ThreadId GetCurrentThreadId() -{ - return pthread_self(); -} -#endif - -// Classes which use non-reentrant, same-thread lock/unlock semantics should -// inherit from this and implement DoLock/DoUnlock. -class Lockable -{ - public: - Lockable() - { -#if !defined(NDEBUG) - owner_ = 0; -#endif - } - virtual ~Lockable() { - } - - bool TryLock() { - if (DoTryLock()) { - DebugSetLocked(); - return true; - } - return false; - } - - void Lock() { - assert(Owner() != GetCurrentThreadId()); - DoLock(); - DebugSetLocked(); - } - - void Unlock() { - assert(Owner() == GetCurrentThreadId()); - DebugSetUnlocked(); - DoUnlock(); - } - - void AssertCurrentThreadOwns() const { - assert(Owner() == GetCurrentThreadId()); - } -#if !defined(NDEBUG) - bool Locked() const { - return owner_ != 0; - } - ThreadId Owner() const { - return owner_; - } -#endif - - virtual bool DoTryLock() = 0; - virtual void DoLock() = 0; - virtual void DoUnlock() = 0; - - protected: - void DebugSetUnlocked() { -#if !defined(NDEBUG) - owner_ = 0; -#endif - } - void DebugSetLocked() { -#if !defined(NDEBUG) - owner_ = GetCurrentThreadId(); -#endif - } - - protected: -#if !defined(NDEBUG) - ThreadId owner_; -#endif -}; - -// RAII for automatically locking and unlocking an object. -class AutoLock -{ - public: - AutoLock(Lockable *lock) - : lock_(lock) - { - lock_->Lock(); - } - ~AutoLock() { - lock_->Unlock(); - } - - private: - Lockable *lock_; -}; - -class AutoTryLock -{ - public: - AutoTryLock(Lockable *lock) - { - lock_ = lock->TryLock() ? lock : NULL; - } - ~AutoTryLock() { - if (lock_) - lock_->Unlock(); - } - - private: - Lockable *lock_; -}; - -// RAII for automatically unlocking and relocking an object. -class AutoUnlock -{ - public: - AutoUnlock(Lockable *lock) - : lock_(lock) - { - lock_->Unlock(); - } - ~AutoUnlock() { - lock_->Lock(); - } - - private: - Lockable *lock_; -}; - -enum WaitResult { - // Woke up because something happened. - Wait_Signaled, - - // Woke up because nothing happened and a timeout was specified. - Wait_Timeout, - - // Woke up, but because of an error. - Wait_Error -}; - -// This must be implemented in order to spawn a new thread. -class IRunnable -{ - public: - virtual ~IRunnable() { - } - - virtual void Run() = 0; -}; - -} // namespace ke - -// Include the actual thread implementations. -#if defined(_MSC_VER) -# include "am-thread-windows.h" -#else -# include "am-thread-posix.h" -#endif - -#endif // _include_amtl_threads_ diff --git a/public/amtl/am-thread-windows.h b/public/amtl/am-thread-windows.h deleted file mode 100644 index c4e34ed2..00000000 --- a/public/amtl/am-thread-windows.h +++ /dev/null @@ -1,161 +0,0 @@ -// 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_thread_windows_h_ -#define _include_amtl_thread_windows_h_ - -#include - -namespace ke { - -class CriticalSection : public Lockable -{ - public: - CriticalSection() { - InitializeCriticalSection(&cs_); - } - ~CriticalSection() { - DeleteCriticalSection(&cs_); - } - - bool DoTryLock() KE_OVERRIDE { - return !!TryEnterCriticalSection(&cs_); - } - void DoLock() KE_OVERRIDE { - EnterCriticalSection(&cs_); - } - - void DoUnlock() KE_OVERRIDE { - LeaveCriticalSection(&cs_); - } - - private: - CRITICAL_SECTION cs_; -}; - -typedef CriticalSection Mutex; - -// Currently, this class only supports single-listener CVs. -class ConditionVariable : public Lockable -{ - public: - ConditionVariable() { - event_ = CreateEvent(NULL, FALSE, FALSE, NULL); - } - ~ConditionVariable() { - CloseHandle(event_); - } - - bool DoTryLock() KE_OVERRIDE { - return cs_.DoTryLock(); - } - void DoLock() KE_OVERRIDE { - cs_.DoLock(); - } - void DoUnlock() KE_OVERRIDE { - cs_.DoUnlock(); - } - - void Notify() { - AssertCurrentThreadOwns(); - SetEvent(event_); - } - - WaitResult Wait(size_t timeout_ms) { - // This will assert if the lock has not been acquired. We don't need to be - // atomic here, like pthread_cond_wait, because the event bit will stick - // until reset by a wait function. - Unlock(); - DWORD rv = WaitForSingleObject(event_, timeout_ms); - Lock(); - - if (rv == WAIT_TIMEOUT) - return Wait_Timeout; - if (rv == WAIT_FAILED) - return Wait_Error; - return Wait_Signaled; - } - - WaitResult Wait() { - return Wait(INFINITE); - } - - private: - CriticalSection cs_; - HANDLE event_; -}; - -class Thread -{ - public: - Thread(IRunnable *run, const char *name = NULL) { - thread_ = CreateThread(NULL, 0, Main, run, 0, NULL); - } - ~Thread() { - if (!thread_) - return; - CloseHandle(thread_); - } - - bool Succeeded() const { - return !!thread_; - } - - void Join() { - if (!Succeeded()) - return; - WaitForSingleObject(thread_, INFINITE); - } - - HANDLE handle() const { - return thread_; - } - - private: - static DWORD WINAPI Main(LPVOID arg) { - ((IRunnable *)arg)->Run(); - return 0; - } - -#pragma pack(push, 8) - struct ThreadNameInfo { - DWORD dwType; - LPCSTR szName; - DWORD dwThreadID; - DWORD dwFlags; - }; -#pragma pack(pop) - - private: - HANDLE thread_; -}; - -} // namespace ke - -#endif // _include_amtl_thread_windows_h_ diff --git a/public/amtl/am-threadlocal.h b/public/amtl/am-threadlocal.h deleted file mode 100644 index df4c023c..00000000 --- a/public/amtl/am-threadlocal.h +++ /dev/null @@ -1,175 +0,0 @@ -// vim: set sts=2 ts=8 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_thread_local_h_ -#define _include_amtl_thread_local_h_ - -#include - -namespace ke { - -// Stores a per-thread value. In single-threaded mode (KE_SINGLE_THREADED), -// this is a no-op container wrapper. -// -// T must be castable to uintptr_t. -// -// When assigning to a ThreadLocal, the assigment will automatically attempt -// to allocate thread-local storage from the operating system. If it fails, it -// will abort the program. If this is undesirable, you may call allocate() -// up-front and handle the error case manually. -// -// The number of thread local slots available to processes is limited (on -// Linux, it is generally 1024). It is best to use ThreadLocal sparingly to -// play nicely with other libraries. -// -// ThreadLocal will free the underlying thread-local storage slot in its -// destructor, but it is not an AutoPtr. It does not delete pointers. Since -// one thread's value is only observable from that thread, make sure to free -// the contained resource (if necessary) before the thread exits. -template -class ThreadLocal -{ - public: - void operator =(const T &other) { - set(other); - } - - T operator *() const { - return get(); - } - T operator ->() const { - return get(); - } - bool operator !() const { - return !get(); - } - bool operator ==(const T &other) const { - return get() == other; - } - bool operator !=(const T &other) const { - return get() != other; - } - - private: - ThreadLocal(const ThreadLocal &other) KE_DELETE; - ThreadLocal &operator =(const ThreadLocal &other) KE_DELETE; - -#if !defined(KE_SINGLE_THREADED) - private: - int allocated_; - - public: - ThreadLocal() { - allocated_ = 0; - } - - T get() const { - if (!allocated_) - return T(); - return internalGet(); - } - void set(const T &t) { - if (!allocated_ && !allocate()) { - fprintf(stderr, "could not allocate thread-local storage\n"); - abort(); - } - internalSet(t); - } - -# if defined(_MSC_VER) - ~ThreadLocal() { - if (allocated_) - TlsFree(key_); - } - - private: - T internalGet() const { - return reinterpret_cast(TlsGetValue(key_)); - } - void internalSet(const T &t) { - TlsSetValue(key_, reinterpret_cast(t)); - } - bool allocate() { - if (InterlockedCompareExchange(&allocated_, 1, 0) == 1) - return true; - key_ = TlsAlloc(); - return key_ != TLS_OUT_OF_INDEXES; - } - - DWORD key_; - -# else - public: - ~ThreadLocal() { - if (allocated_) - pthread_key_delete(key_); - } - - bool allocate() { - if (!__sync_bool_compare_and_swap(&allocated_, 0, 1)) - return true; - return pthread_key_create(&key_, NULL) == 0; - } - - private: - T internalGet() const { - return (T)reinterpret_cast(pthread_getspecific(key_)); - } - void internalSet(const T &t) { - pthread_setspecific(key_, reinterpret_cast(t)); - } - - pthread_key_t key_; -# endif // !_MSC_VER - -#else // KE_SINGLE_THREADED - public: - ThreadLocal() { - t_ = T(); - } - - bool allocate() { - return true; - } - - T get() const { - return t_; - } - void set(const T &t) { - t_ = t; - } - - private: - T t_; -#endif -}; - -} // namespace ke - -#endif // _include_amtl_thread_local_h_ diff --git a/public/amtl/am-utility.h b/public/amtl/am-utility.h deleted file mode 100644 index 25417fab..00000000 --- a/public/amtl/am-utility.h +++ /dev/null @@ -1,405 +0,0 @@ -// 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_utility_h_ -#define _include_amtl_utility_h_ - -#include -#include -#include -#include -#if defined(_MSC_VER) -# include -#endif -#include - -#define KE_32BIT - -#if defined(_MSC_VER) -# pragma warning(disable:4355) -#endif - -namespace ke { - -static const size_t kMallocAlignment = sizeof(void *) * 2; - -static const size_t kKB = 1024; -static const size_t kMB = 1024 * kKB; -static const size_t kGB = 1024 * kMB; - -typedef uint8_t * Address; - -template T -ReturnAndVoid(T &t) -{ - T saved = t; - t = T(); - return saved; -} - -#if __cplusplus >= 201103L -# define KE_CXX11 -#endif - -#if defined(KE_CXX11) -# define KE_DELETE = delete -# define KE_OVERRIDE override -#else -# define KE_DELETE -# define KE_OVERRIDE -#endif - -// Wrapper that automatically deletes its contents. The pointer can be taken -// to avoid destruction. -template -class AutoPtr -{ - T *t_; - - public: - AutoPtr() - : t_(NULL) - { - } - explicit AutoPtr(T *t) - : t_(t) - { - } - AutoPtr(Moveable > other) - { - t_ = other->t_; - other->t_ = NULL; - } - ~AutoPtr() { - delete t_; - } - T *take() { - return ReturnAndVoid(t_); - } - T *operator *() const { - return t_; - } - T *operator ->() const { - return t_; - } - operator T *() const { - return t_; - } - T *operator =(T *t) { - delete t_; - t_ = t; - return t_; - } - T *operator =(Moveable > other) { - delete t_; - t_ = other->t_; - other->t_ = NULL; - return t_; - } - bool operator !() const { - return !t_; - } - - private: - AutoPtr(const AutoPtr &other) KE_DELETE; - AutoPtr &operator =(const AutoPtr &other) KE_DELETE; -}; - -// Wrapper that automatically deletes its contents. The pointer can be taken -// to avoid destruction. -template -class AutoArray -{ - T *t_; - - public: - AutoArray() - : t_(NULL) - { - } - explicit AutoArray(T *t) - : t_(t) - { - } - ~AutoArray() { - delete [] t_; - } - T *take() { - return ReturnAndVoid(t_); - } - T *operator *() const { - return t_; - } - T &operator [](size_t index) { - return t_[index]; - } - const T &operator [](size_t index) const { - return t_[index]; - } - operator T *() const { - return t_; - } - void operator =(T *t) { - delete [] t_; - t_ = t; - } - bool operator !() const { - return !t_; - } -}; - -static inline size_t -Log2(size_t number) -{ - assert(number != 0); - -#if defined _MSC_VER - unsigned long rval; -# ifdef _M_IX86 - _BitScanReverse(&rval, number); -# elif _M_X64 - _BitScanReverse64(&rval, number); -# endif - return rval; -#elif defined __GNUC__ - return 31 - __builtin_clz(number); -#else - size_t bit; - asm("bsr %1, %0\n" - : "=r" (bit) - : "rm" (number)); - return bit; -#endif -} - -static inline size_t -FindRightmostBit(size_t number) -{ - assert(number != 0); - -#if defined _MSC_VER - unsigned long rval; -# ifdef _M_IX86 - _BitScanForward(&rval, number); -# elif _M_X64 - _BitScanForward64(&rval, number); -# endif - return rval; -#elif defined __GNUC__ - return __builtin_ctz(number); -#else - size_t bit; - asm("bsf %1, %0\n" - : "=r" (bit) - : "rm" (number)); - return bit; -#endif -} - -static inline bool -IsPowerOfTwo(size_t value) -{ - if (value == 0) - return false; - return !(value & (value - 1)); -} - -static inline size_t -Align(size_t count, size_t alignment) -{ - assert(IsPowerOfTwo(alignment)); - return count + (alignment - (count % alignment)) % alignment; -} - -static inline bool -IsUint32AddSafe(unsigned a, unsigned b) -{ - if (!a || !b) - return true; - size_t log2_a = Log2(a); - size_t log2_b = Log2(b); - return (log2_a < sizeof(unsigned) * 8) && - (log2_b < sizeof(unsigned) * 8); -} - -static inline bool -IsUintPtrAddSafe(size_t a, size_t b) -{ - if (!a || !b) - return true; - size_t log2_a = Log2(a); - size_t log2_b = Log2(b); - return (log2_a < sizeof(size_t) * 8) && - (log2_b < sizeof(size_t) * 8); -} - -static inline bool -IsUint32MultiplySafe(unsigned a, unsigned b) -{ - if (a <= 1 || b <= 1) - return true; - - size_t log2_a = Log2(a); - size_t log2_b = Log2(b); - return log2_a + log2_b <= sizeof(unsigned) * 8; -} - -static inline bool -IsUintPtrMultiplySafe(size_t a, size_t b) -{ - if (a <= 1 || b <= 1) - return true; - - size_t log2_a = Log2(a); - size_t log2_b = Log2(b); - return log2_a + log2_b <= sizeof(size_t) * 8; -} - -#define ARRAY_LENGTH(array) (sizeof(array) / sizeof(array[0])) -#define STATIC_ASSERT(cond) extern int static_assert_f(int a[(cond) ? 1 : -1]) - -#define IS_ALIGNED(addr, alignment) (!(uintptr_t(addr) & ((alignment) - 1))) - -template -static inline bool -IsAligned(T addr, size_t alignment) -{ - assert(IsPowerOfTwo(alignment)); - return !(uintptr_t(addr) & (alignment - 1)); -} - -static inline Address -AlignedBase(Address addr, size_t alignment) -{ - assert(IsPowerOfTwo(alignment)); - return Address(uintptr_t(addr) & ~(alignment - 1)); -} - -template static inline T -Min(const T &t1, const T &t2) -{ - return t1 < t2 ? t1 : t2; -} - -template static inline T -Max(const T &t1, const T &t2) -{ - return t1 > t2 ? t1 : t2; -} - -template -class StorageBuffer -{ - public: - T *address() { - return reinterpret_cast(buffer_); - } - const T *address() const { - return reinterpret_cast(buffer_); - } - - private: - union { - char buffer_[sizeof(T)]; - uint64_t aligned_; - }; -}; - -template -class SaveAndSet -{ - public: - SaveAndSet(T *location, const T &value) - : location_(location), - old_(*location) - { - *location_ = value; - } - ~SaveAndSet() { - *location_ = old_; - } - - private: - T *location_; - T old_; -}; - -template -class StackLinked -{ - public: - StackLinked(T **prevp) - : prevp_(prevp), - prev_(*prevp) - { - *prevp_ = static_cast(this); - } - virtual ~StackLinked() { - assert(*prevp_ == this); - *prevp_ = prev_; - } - - private: - T **prevp_; - T *prev_; -}; - -#if __cplusplus >= 201103L -# define KE_CXX11 -#endif - -#if defined(KE_CXX11) -# define KE_DELETE = delete -# define KE_OVERRIDE override -#else -# define KE_DELETE -# define KE_OVERRIDE -#endif - -#if defined(_MSC_VER) -# define KE_SIZET_FMT "%Iu" -# define KE_I64_FMT "%I64d" -# define KE_U64_FMT "%I64u" -#elif defined(__GNUC__) -# define KE_SIZET_FMT "%zu" -# define KE_I64_FMT "%lld" -# define KE_U64_FMT "%llu" -#else -# error "Implement format specifier string" -#endif - -#if defined(__GNUC__) -# define KE_CRITICAL_LIKELY(x) __builtin_expect(!!(x), 1) -#else -# define KE_CRITICAL_LIKELY(x) x -#endif - -} - -#endif // _include_amtl_utility_h_ diff --git a/public/amtl/am-vector.h b/public/amtl/am-vector.h deleted file mode 100644 index 4f01bb97..00000000 --- a/public/amtl/am-vector.h +++ /dev/null @@ -1,252 +0,0 @@ -// 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_KEIMA_TPL_CPP_VECTOR_H_ -#define _INCLUDE_KEIMA_TPL_CPP_VECTOR_H_ - -#include -#include -#include -#include -#include - -namespace ke { - -template -class Vector : public AllocPolicy -{ - public: - Vector(AllocPolicy = AllocPolicy()) - : data_(NULL), - nitems_(0), - maxsize_(0) - { - } - - Vector(Moveable > other) { - data_ = other->data_; - nitems_ = other->nitems_; - maxsize_ = other->maxsize_; - other->reset(); - } - - ~Vector() { - zap(); - } - - bool append(const T &item) { - if (!growIfNeeded(1)) - return false; - new (&data_[nitems_]) T(item); - nitems_++; - return true; - } - bool append(Moveable item) { - if (!growIfNeeded(1)) - return false; - new (&data_[nitems_]) T(item); - nitems_++; - return true; - } - void infallibleAppend(const T &item) { - assert(growIfNeeded(1)); - new (&data_[nitems_]) T(item); - nitems_++; - } - void infallibleAppend(Moveable item) { - assert(growIfNeeded(1)); - new (&data_[nitems_]) T(item); - nitems_++; - } - - // Shift all elements including |at| up by one, and insert |item| at the - // given position. If |at| is one greater than the last usable index, - // i.e. |at == length()|, then this is the same as append(). No other - // invalid indexes are allowed. - // - // This is a linear-time operation. - bool insert(size_t at, const T &item) { - if (at == length()) - return append(item); - if (!moveUp(at)) - return false; - new (&data_[at]) T(item); - return true; - } - bool insert(size_t at, Moveable item) { - if (at == length()) - return append(item); - if (!moveUp(at)) - return false; - new (&data_[at]) T(item); - return true; - } - - // Shift all elements at the given position down, removing the given - // element. This is a linear-time operation. - void remove(size_t at) { - for (size_t i = at; i < length() - 1; i++) - data_[i] = Moveable(data_[i + 1]); - pop(); - } - - T popCopy() { - T t = at(length() - 1); - pop(); - return t; - } - void pop() { - assert(nitems_); - data_[nitems_ - 1].~T(); - nitems_--; - } - bool empty() const { - return length() == 0; - } - size_t length() const { - return nitems_; - } - T& at(size_t i) { - assert(i < length()); - return data_[i]; - } - const T& at(size_t i) const { - assert(i < length()); - return data_[i]; - } - T& operator [](size_t i) { - return at(i); - } - const T& operator [](size_t i) const { - return at(i); - } - void clear() { - nitems_ = 0; - } - const T &back() const { - return at(length() - 1); - } - T &back() { - return at(length() - 1); - } - - T *buffer() const { - return data_; - } - - bool ensure(size_t desired) { - if (desired <= length()) - return true; - - return growIfNeeded(desired - length()); - } - - Vector &operator =(Moveable > other) { - data_ = other->data_; - nitems_ = other->nitems_; - maxsize_ = other->maxsize_; - other->reset(); - return *this; - } - - private: - // These are disallowed because they basically violate the failure handling - // model for AllocPolicies and are also likely to have abysmal performance. - Vector(const Vector &other) KE_DELETE; - Vector &operator =(const Vector &other) KE_DELETE; - - private: - void zap() { - for (size_t i = 0; i < nitems_; i++) - data_[i].~T(); - this->free(data_); - } - void reset() { - data_ = NULL; - nitems_ = 0; - maxsize_ = 0; - } - - bool moveUp(size_t at) { - // Note: we don't use append() here. Passing an element as a Moveable into - // insert() or append() can break, since the underlying storage could be - // reallocated, invalidating the Moveable reference. Instead, we inline - // the logic to append() to ensure growIfNeeded occurs before any - // references are taken. - if (!growIfNeeded(1)) - return false; - new (&data_[nitems_]) T(Moveable(data_[nitems_ - 1])); - nitems_++; - for (size_t i = nitems_ - 2; i > at; i--) - data_[i] = Moveable(data_[i - 1]); - return true; - } - - bool growIfNeeded(size_t needed) - { - if (!IsUintPtrAddSafe(nitems_, needed)) { - this->reportAllocationOverflow(); - return false; - } - if (nitems_ + needed < maxsize_) - return true; - - size_t new_maxsize = maxsize_ ? maxsize_ : 8; - while (nitems_ + needed > new_maxsize) { - if (!IsUintPtrMultiplySafe(new_maxsize, 2)) { - this->reportAllocationOverflow(); - return false; - } - new_maxsize *= 2; - } - - T* newdata = (T*)this->malloc(sizeof(T) * new_maxsize); - if (newdata == NULL) - return false; - for (size_t i = 0; i < nitems_; i++) { - new (&newdata[i]) T(Moveable(data_[i])); - data_[i].~T(); - } - this->free(data_); - - data_ = newdata; - maxsize_ = new_maxsize; - return true; - } - - private: - T* data_; - size_t nitems_; - size_t maxsize_; -}; - -} - -#endif /* _INCLUDE_KEIMA_TPL_CPP_VECTOR_H_ */ - diff --git a/public/sm_namehashset.h b/public/sm_namehashset.h index 85edd1cc..5b169d07 100644 --- a/public/sm_namehashset.h +++ b/public/sm_namehashset.h @@ -29,6 +29,8 @@ * Version: $Id$ */ +#include + #ifndef _include_sourcemod_namehashset_h_ #define _include_sourcemod_namehashset_h_ @@ -117,14 +119,10 @@ public: return table_.findForAdd(aKey); } - void add(Insert &i, const T &value) + template + void add(Insert &i, U &&value) { - return table_.add(i, value); - } - - void add(Insert &i, ke::Moveable value) - { - return table_.add(i, value); + return table_.add(i, ke::Forward(value)); } bool retrieve(const char *aKey, T *value) @@ -137,22 +135,14 @@ public: return true; } - bool insert(const char *aKey, const T &value) + template + bool insert(const char *aKey, U &&value) { CharsAndLength key(aKey); Insert i = table_.findForAdd(key); if (i.found()) return false; - return table_.add(i, value); - } - - bool insert(const char *aKey, ke::Moveable value) - { - CharsAndLength key(aKey); - Insert i = table_.findForAdd(key); - if (i.found()) - return false; - return table_.add(i, value); + return table_.add(i, ke::Forward(value)); } bool contains(const char *aKey) diff --git a/sourcepawn/compiler/AMBuilder b/sourcepawn/compiler/AMBuilder index 2612536a..c52dcf47 100644 --- a/sourcepawn/compiler/AMBuilder +++ b/sourcepawn/compiler/AMBuilder @@ -5,7 +5,7 @@ binary = SM.Program(builder, 'spcomp') compiler = binary.compiler compiler.includes += [ os.path.join(builder.sourcePath, 'public'), - os.path.join(builder.sourcePath, 'public', 'amtl'), + os.path.join(builder.sourcePath, 'public', 'amtl', 'include'), os.path.join(builder.sourcePath, 'public', 'sourcepawn'), os.path.join(builder.currentSourcePath, '..', 'include'), os.path.join(builder.currentSourcePath, '..', 'third_party'), diff --git a/sourcepawn/vm/AMBuilder b/sourcepawn/vm/AMBuilder index f112f43e..363f8910 100644 --- a/sourcepawn/vm/AMBuilder +++ b/sourcepawn/vm/AMBuilder @@ -7,7 +7,7 @@ Includes = [ os.path.join(builder.currentSourcePath, '..', 'third_party'), os.path.join(builder.sourcePath, 'public'), os.path.join(builder.sourcePath, 'public', 'sourcepawn'), - os.path.join(builder.sourcePath, 'public', 'amtl'), + os.path.join(builder.sourcePath, 'public', 'amtl', 'include'), os.path.join(builder.sourcePath, 'public', 'jit'), os.path.join(builder.sourcePath, 'public', 'jit', 'x86'),