Move ke_ headers to new public/amtl folder.
Move ke_ headers to new public/amtl folder.
1.1 --- a/AMBuildScript Thu Aug 22 14:05:44 2013 -0700
1.2 +++ b/AMBuildScript Thu Aug 22 16:30:44 2013 -0700
1.3 @@ -300,6 +300,7 @@
1.4 compiler['CXXINCLUDES'].append(os.path.join(AMBuild.sourceFolder, 'public'))
1.5 compiler['CXXINCLUDES'].append(os.path.join(AMBuild.sourceFolder, 'public', 'extensions'))
1.6 compiler['CXXINCLUDES'].append(os.path.join(AMBuild.sourceFolder, 'public', 'sourcepawn'))
1.7 + compiler['CXXINCLUDES'].append(os.path.join(AMBuild.sourceFolder, 'public', 'amtl'))
1.8 return compiler
1.9
1.10 def AutoVersion(self, folder, binary):
2.1 --- a/core/logic/AMBuilder Thu Aug 22 14:05:44 2013 -0700
2.2 +++ b/core/logic/AMBuilder Thu Aug 22 16:30:44 2013 -0700
2.3 @@ -7,6 +7,7 @@
2.4 compiler['CXXINCLUDES'].append(os.path.join(base, 'core', 'logic'))
2.5 compiler['CXXINCLUDES'].append(os.path.join(base, 'public'))
2.6 compiler['CXXINCLUDES'].append(os.path.join(base, 'public', 'sourcepawn'))
2.7 +compiler['CXXINCLUDES'].append(os.path.join(base, 'public', 'amtl'))
2.8 compiler['CDEFINES'].append('SM_DEFAULT_THREADER')
2.9 compiler['CDEFINES'].append('SM_LOGIC')
2.10
3.1 --- a/extensions/clientprefs/extension.h Thu Aug 22 14:05:44 2013 -0700
3.2 +++ b/extensions/clientprefs/extension.h Thu Aug 22 16:30:44 2013 -0700
3.3 @@ -156,7 +156,6 @@
3.4 IPhraseCollection *phrases;
3.5 const DatabaseInfo *DBInfo;
3.6
3.7 - IMutex *cookieMutex;
3.8 bool databaseLoading;
3.9
3.10 private:
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
4.2 +++ b/public/amtl/ke_allocator_policies.h Thu Aug 22 16:30:44 2013 -0700
4.3 @@ -0,0 +1,53 @@
4.4 +/* vim: set ts=2 sw=2 tw=99 et:
4.5 + *
4.6 + * Copyright (C) 2012 David Anderson
4.7 + *
4.8 + * This file is part of SourcePawn.
4.9 + *
4.10 + * SourcePawn is free software: you can redistribute it and/or modify it under
4.11 + * the terms of the GNU General Public License as published by the Free
4.12 + * Software Foundation, either version 3 of the License, or (at your option)
4.13 + * any later version.
4.14 + *
4.15 + * SourcePawn is distributed in the hope that it will be useful, but WITHOUT ANY
4.16 + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
4.17 + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
4.18 + *
4.19 + * You should have received a copy of the GNU General Public License along with
4.20 + * SourcePawn. If not, see http://www.gnu.org/licenses/.
4.21 + */
4.22 +#ifndef _include_sourcepawn_allocatorpolicies_h_
4.23 +#define _include_sourcepawn_allocatorpolicies_h_
4.24 +
4.25 +#include <stdio.h>
4.26 +#include <stdlib.h>
4.27 +
4.28 +namespace ke {
4.29 +
4.30 +class SystemAllocatorPolicy
4.31 +{
4.32 + protected:
4.33 + void reportOutOfMemory() {
4.34 + fprintf(stderr, "OUT OF MEMORY\n");
4.35 + abort();
4.36 + }
4.37 + void reportAllocationOverflow() {
4.38 + fprintf(stderr, "OUT OF MEMORY\n");
4.39 + abort();
4.40 + }
4.41 +
4.42 + public:
4.43 + void free(void *memory) {
4.44 + ::free(memory);
4.45 + }
4.46 + void *malloc(size_t bytes) {
4.47 + void *ptr = ::malloc(bytes);
4.48 + if (!ptr)
4.49 + reportOutOfMemory();
4.50 + return ptr;
4.51 + }
4.52 +};
4.53 +
4.54 +}
4.55 +
4.56 +#endif // _include_sourcepawn_allocatorpolicies_h_
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
5.2 +++ b/public/amtl/ke_inline_list.h Thu Aug 22 16:30:44 2013 -0700
5.3 @@ -0,0 +1,137 @@
5.4 +/**
5.5 + * vim: set sts=2 ts=8 sw=2 tw=99 noet :
5.6 + * =============================================================================
5.7 + * SourcePawn
5.8 + * Copyright (C) 2004-2009 AlliedModders LLC. All rights reserved.
5.9 + * =============================================================================
5.10 + *
5.11 + * This program is free software; you can redistribute it and/or modify it under
5.12 + * the terms of the GNU General Public License, version 3.0, as published by the
5.13 + * Free Software Foundation.
5.14 + *
5.15 + * This program is distributed in the hope that it will be useful, but WITHOUT
5.16 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
5.17 + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
5.18 + * details.
5.19 + *
5.20 + * You should have received a copy of the GNU General Public License along with
5.21 + * this program. If not, see <http://www.gnu.org/licenses/>.
5.22 + *
5.23 + * As a special exception, AlliedModders LLC gives you permission to link the
5.24 + * code of this program (as well as its derivative works) to "Half-Life 2," the
5.25 + * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
5.26 + * by the Valve Corporation. You must obey the GNU General Public License in
5.27 + * all respects for all other code used. Additionally, AlliedModders LLC grants
5.28 + * this exception to all derivative works. AlliedModders LLC defines further
5.29 + * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
5.30 + * or <http://www.sourcemod.net/license.php>.
5.31 + */
5.32 +#ifndef _include_sourcepawn_inline_list_h_
5.33 +#define _include_sourcepawn_inline_list_h_
5.34 +
5.35 +#include <stddef.h>
5.36 +
5.37 +template <typename T> class InlineList;
5.38 +
5.39 +template <typename T>
5.40 +class InlineListNode
5.41 +{
5.42 + friend class InlineList<T>;
5.43 +
5.44 + public:
5.45 + InlineListNode()
5.46 + : next_(NULL),
5.47 + prev_(NULL)
5.48 + {
5.49 + }
5.50 +
5.51 + InlineListNode(InlineListNode *next, InlineListNode *prev)
5.52 + : next_(next),
5.53 + prev_(prev)
5.54 + {
5.55 + }
5.56 +
5.57 + protected:
5.58 + InlineListNode *next_;
5.59 + InlineListNode *prev_;
5.60 +};
5.61 +
5.62 +template <typename T>
5.63 +class InlineList
5.64 +{
5.65 + typedef InlineListNode<T> Node;
5.66 +
5.67 + Node head_;
5.68 +
5.69 + public:
5.70 + InlineList()
5.71 + : head_(&head_, &head_)
5.72 + {
5.73 + }
5.74 +
5.75 + public:
5.76 + class iterator
5.77 + {
5.78 + friend class InlineList;
5.79 + Node *iter_;
5.80 +
5.81 + public:
5.82 + iterator(Node *iter)
5.83 + : iter_(iter)
5.84 + {
5.85 + }
5.86 +
5.87 + iterator & operator ++() {
5.88 + iter_ = iter_->next;
5.89 + return *iter_;
5.90 + }
5.91 + iterator operator ++(int) {
5.92 + iterator old(*this);
5.93 + iter_ = iter_->next_;
5.94 + return old;
5.95 + }
5.96 + T * operator *() {
5.97 + return static_cast<T *>(iter_);
5.98 + }
5.99 + T * operator ->() {
5.100 + return static_cast<T *>(iter_);
5.101 + }
5.102 + bool operator !=(const iterator &where) const {
5.103 + return iter_ != where.iter_;
5.104 + }
5.105 + bool operator ==(const iterator &where) const {
5.106 + return iter_ == where.iter_;
5.107 + }
5.108 + iterator prev() const {
5.109 + iterator p(iter_->prev_);
5.110 + return p;
5.111 + }
5.112 + iterator next() const {
5.113 + iterator p(iter_->next_);
5.114 + return p;
5.115 + }
5.116 + };
5.117 +
5.118 + iterator begin() {
5.119 + return iterator(head_.next_);
5.120 + }
5.121 +
5.122 + iterator end() {
5.123 + return iterator(&head_);
5.124 + }
5.125 +
5.126 + void erase(Node *t) {
5.127 + t->prev_->next_ = t->next_;
5.128 + t->next_->prev_ = t->prev_;
5.129 + }
5.130 +
5.131 + void insert(Node *t) {
5.132 + t->prev_ = head_.prev_;
5.133 + t->next_ = &head_;
5.134 + head_.prev_->next_ = t;
5.135 + head_.prev_ = t;
5.136 + }
5.137 +};
5.138 +
5.139 +#endif // _include_sourcepawn_inline_list_h_
5.140 +
6.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
6.2 +++ b/public/amtl/ke_thread_posix.h Thu Aug 22 16:30:44 2013 -0700
6.3 @@ -0,0 +1,200 @@
6.4 +// vim: set ts=8 sts=2 sw=2 tw=99 et:
6.5 +//
6.6 +// This file is part of SourcePawn.
6.7 +//
6.8 +// SourcePawn is free software: you can redistribute it and/or modify
6.9 +// it under the terms of the GNU General Public License as published by
6.10 +// the Free Software Foundation, either version 3 of the License, or
6.11 +// (at your option) any later version.
6.12 +//
6.13 +// SourcePawn is distributed in the hope that it will be useful,
6.14 +// but WITHOUT ANY WARRANTY; without even the implied warranty of
6.15 +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
6.16 +// GNU General Public License for more details.
6.17 +//
6.18 +// You should have received a copy of the GNU General Public License
6.19 +// along with SourcePawn. If not, see <http://www.gnu.org/licenses/>.
6.20 +#ifndef _include_sourcepawn_thread_posix_h_
6.21 +#define _include_sourcepawn_thread_posix_h_
6.22 +
6.23 +#include <pthread.h>
6.24 +#include <sys/time.h>
6.25 +#include <errno.h>
6.26 +#include <stdio.h>
6.27 +#if defined(__linux__)
6.28 +# include <sys/prctl.h>
6.29 +#endif
6.30 +#if defined(__APPLE__)
6.31 +# include <dlfcn.h>
6.32 +#endif
6.33 +
6.34 +namespace ke {
6.35 +
6.36 +class Mutex : public Lockable
6.37 +{
6.38 + public:
6.39 + Mutex() {
6.40 +#if !defined(NDEBUG)
6.41 + int rv =
6.42 +#endif
6.43 + pthread_mutex_init(&mutex_, NULL);
6.44 + assert(rv == 0);
6.45 + }
6.46 + ~Mutex() {
6.47 + pthread_mutex_destroy(&mutex_);
6.48 + }
6.49 +
6.50 + bool DoTryLock() {
6.51 + return pthread_mutex_trylock(&mutex_) == 0;
6.52 + }
6.53 +
6.54 + void DoLock() {
6.55 + pthread_mutex_lock(&mutex_);
6.56 + }
6.57 +
6.58 + void DoUnlock() {
6.59 + pthread_mutex_unlock(&mutex_);
6.60 + }
6.61 +
6.62 + pthread_mutex_t *raw() {
6.63 + return &mutex_;
6.64 + }
6.65 +
6.66 + private:
6.67 + pthread_mutex_t mutex_;
6.68 +};
6.69 +
6.70 +// Currently, this class only supports single-listener CVs.
6.71 +class ConditionVariable : public Lockable
6.72 +{
6.73 + public:
6.74 + ConditionVariable() {
6.75 +#if !defined(NDEBUG)
6.76 + int rv =
6.77 +#endif
6.78 + pthread_cond_init(&cv_, NULL);
6.79 + assert(rv == 0);
6.80 + }
6.81 + ~ConditionVariable() {
6.82 + pthread_cond_destroy(&cv_);
6.83 + }
6.84 +
6.85 + bool DoTryLock() {
6.86 + return mutex_.DoTryLock();
6.87 + }
6.88 + void DoLock() {
6.89 + mutex_.DoLock();
6.90 + }
6.91 + void DoUnlock() {
6.92 + mutex_.DoUnlock();
6.93 + }
6.94 +
6.95 + void Notify() {
6.96 + AssertCurrentThreadOwns();
6.97 + pthread_cond_signal(&cv_);
6.98 + }
6.99 +
6.100 + WaitResult Wait(size_t timeout_ms) {
6.101 + AssertCurrentThreadOwns();
6.102 +
6.103 +#if defined(__linux__)
6.104 + struct timespec ts;
6.105 + if (clock_gettime(CLOCK_REALTIME, &ts) == -1)
6.106 + return Wait_Error;
6.107 +#else
6.108 + struct timeval tv;
6.109 + gettimeofday(&tv, NULL);
6.110 +
6.111 + struct timespec ts;
6.112 + ts.tv_sec = tv.tv_sec;
6.113 + ts.tv_nsec = tv.tv_usec * 1000;
6.114 +#endif
6.115 +
6.116 + ts.tv_sec += timeout_ms / 1000;
6.117 + ts.tv_nsec += (timeout_ms % 1000) * 1000000;
6.118 + if (ts.tv_nsec >= 1000000000) {
6.119 + ts.tv_sec++;
6.120 + ts.tv_nsec -= 1000000000;
6.121 + }
6.122 +
6.123 + DebugSetUnlocked();
6.124 + int rv = pthread_cond_timedwait(&cv_, mutex_.raw(), &ts);
6.125 + DebugSetLocked();
6.126 +
6.127 + if (rv == ETIMEDOUT)
6.128 + return Wait_Timeout;
6.129 + if (rv == 0)
6.130 + return Wait_Signaled;
6.131 + return Wait_Error;
6.132 + }
6.133 +
6.134 + WaitResult Wait() {
6.135 + AssertCurrentThreadOwns();
6.136 +
6.137 + DebugSetUnlocked();
6.138 + int rv = pthread_cond_wait(&cv_, mutex_.raw());
6.139 + DebugSetLocked();
6.140 +
6.141 + if (rv == 0)
6.142 + return Wait_Signaled;
6.143 + return Wait_Error;
6.144 + }
6.145 +
6.146 + private:
6.147 + Mutex mutex_;
6.148 + pthread_cond_t cv_;
6.149 +};
6.150 +
6.151 +class Thread
6.152 +{
6.153 + struct ThreadData {
6.154 + IRunnable *run;
6.155 + char name[17];
6.156 + };
6.157 + public:
6.158 + Thread(IRunnable *run, const char *name = NULL) {
6.159 + ThreadData *data = new ThreadData;
6.160 + data->run = run;
6.161 + snprintf(data->name, sizeof(data->name), "%s", name ? name : "");
6.162 +
6.163 + initialized_ = (pthread_create(&thread_, NULL, Main, data) == 0);
6.164 + if (!initialized_)
6.165 + delete data;
6.166 + }
6.167 +
6.168 + bool Succeeded() const {
6.169 + return initialized_;
6.170 + }
6.171 +
6.172 + void Join() {
6.173 + if (!Succeeded())
6.174 + return;
6.175 + pthread_join(thread_, NULL);
6.176 + }
6.177 +
6.178 + private:
6.179 + static void *Main(void *arg) {
6.180 + AutoPtr<ThreadData> data((ThreadData *)arg);
6.181 +
6.182 + if (data->name[0]) {
6.183 +#if defined(__linux__)
6.184 + prctl(PR_SET_NAME, (unsigned long)data->name);
6.185 +#elif defined(__APPLE__)
6.186 + int (*fn)(const char *) = (int (*)(const char *))dlsym(RTLD_DEFAULT, "pthread_setname_np");
6.187 + if (fn)
6.188 + fn(data->name);
6.189 +#endif
6.190 + }
6.191 + data->run->Run();
6.192 + return NULL;
6.193 + }
6.194 +
6.195 + private:
6.196 + bool initialized_;
6.197 + pthread_t thread_;
6.198 +};
6.199 +
6.200 +} // namespace ke
6.201 +
6.202 +#endif // _include_sourcepawn_thread_posix_h_
6.203 +
7.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
7.2 +++ b/public/amtl/ke_thread_utils.h Thu Aug 22 16:30:44 2013 -0700
7.3 @@ -0,0 +1,246 @@
7.4 +// vim: set ts=8 sts=2 sw=2 tw=99 et:
7.5 +//
7.6 +// This file is part of SourcePawn.
7.7 +//
7.8 +// SourcePawn is free software: you can redistribute it and/or modify
7.9 +// it under the terms of the GNU General Public License as published by
7.10 +// the Free Software Foundation, either version 3 of the License, or
7.11 +// (at your option) any later version.
7.12 +//
7.13 +// SourcePawn is distributed in the hope that it will be useful,
7.14 +// but WITHOUT ANY WARRANTY; without even the implied warranty of
7.15 +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
7.16 +// GNU General Public License for more details.
7.17 +//
7.18 +// You should have received a copy of the GNU General Public License
7.19 +// along with SourcePawn. If not, see <http://www.gnu.org/licenses/>.
7.20 +#ifndef _include_sourcepawn_threads_
7.21 +#define _include_sourcepawn_threads_
7.22 +
7.23 +#include <assert.h>
7.24 +#if defined(_MSC_VER)
7.25 +# include <windows.h>
7.26 +# include <WinBase.h>
7.27 +#else
7.28 +# include <pthread.h>
7.29 +#endif
7.30 +#include <ke_utility.h>
7.31 +
7.32 +// Thread primitives for SourcePawn.
7.33 +//
7.34 +// -- Mutexes --
7.35 +//
7.36 +// A Lockable is a mutual exclusion primitive. It can be owned by at most one
7.37 +// thread at a time, and ownership blocks any other thread from taking taking
7.38 +// ownership. Ownership must be acquired and released on the same thread.
7.39 +// Lockables are not re-entrant.
7.40 +//
7.41 +// While a few classes support the Lockable interface, the simplest Lockable
7.42 +// object that can be instantiated is a Mutex.
7.43 +//
7.44 +// -- Condition Variables --
7.45 +//
7.46 +// A ConditionVariable provides mutually exclusive access based on a
7.47 +// condition ocurring. CVs provide two capabilities: Wait(), which will block
7.48 +// until the condition is triggered, and Notify(), which signals any blocking
7.49 +// thread that the condition has occurred.
7.50 +//
7.51 +// Condition variables have an underlying mutex lock. This lock must be
7.52 +// acquired before calling Wait() or Notify(). It is automatically released
7.53 +// once Wait begins blocking. This operation is atomic with respect to other
7.54 +// threads and the mutex. For example, it is not possible for the lock to be
7.55 +// acquired by another thread in between unlocking and blocking. Since Notify
7.56 +// also requires the lock to be acquired, there is no risk of an event
7.57 +// accidentally dissipating into thin air because it was sent before the other
7.58 +// thread began blocking.
7.59 +//
7.60 +// When Wait() returns, the lock is automatically re-acquired. This operation
7.61 +// is NOT atomic. In between waking up and re-acquiring the lock, another
7.62 +// thread may steal the lock and issue another event. Applications must
7.63 +// account for this. For example, a message pump should check that there are
7.64 +// no messages left to process before blocking again.
7.65 +//
7.66 +// Likewise, it is also not defined whether a Signal() will have any effect
7.67 +// while a thread is not waiting on the monitor. This is yet another reason
7.68 +// the above paragraph is so important - applications should, under a lock of
7.69 +// the condition variable - check for state changes before waiting.
7.70 +//
7.71 +// -- Threads --
7.72 +//
7.73 +// A Thread object, when created, spawns a new thread with the given callback
7.74 +// (the callbacks must implement IRunnable). Threads have one method of
7.75 +// interest, Join(), which will block until the thread's execution finishes.
7.76 +// Deleting a thread object will free any operating system resources associated
7.77 +// with that thread, if the thread has finished executing.
7.78 +//
7.79 +// Threads can fail to spawn; make sure to check Succeeded().
7.80 +//
7.81 +
7.82 +namespace ke {
7.83 +
7.84 +// Abstraction for getting a unique thread identifier. Debug-only.
7.85 +#if defined(_MSC_VER)
7.86 +typedef DWORD ThreadId;
7.87 +
7.88 +static inline ThreadId GetCurrentThreadId()
7.89 +{
7.90 + return ::GetCurrentThreadId();
7.91 +}
7.92 +#else
7.93 +typedef pthread_t ThreadId;
7.94 +
7.95 +static inline ThreadId GetCurrentThreadId()
7.96 +{
7.97 + return pthread_self();
7.98 +}
7.99 +#endif
7.100 +
7.101 +// Classes which use non-reentrant, same-thread lock/unlock semantics should
7.102 +// inherit from this and implement DoLock/DoUnlock.
7.103 +class Lockable
7.104 +{
7.105 + public:
7.106 + Lockable()
7.107 + {
7.108 +#if !defined(NDEBUG)
7.109 + owner_ = 0;
7.110 +#endif
7.111 + }
7.112 + virtual ~Lockable() {
7.113 + }
7.114 +
7.115 + bool TryLock() {
7.116 + if (DoTryLock()) {
7.117 + DebugSetLocked();
7.118 + return true;
7.119 + }
7.120 + return false;
7.121 + }
7.122 +
7.123 + void Lock() {
7.124 + assert(Owner() != GetCurrentThreadId());
7.125 + DoLock();
7.126 + DebugSetLocked();
7.127 + }
7.128 +
7.129 + void Unlock() {
7.130 + assert(Owner() == GetCurrentThreadId());
7.131 + DebugSetUnlocked();
7.132 + DoUnlock();
7.133 + }
7.134 +
7.135 + void AssertCurrentThreadOwns() const {
7.136 + assert(Owner() == GetCurrentThreadId());
7.137 + }
7.138 +#if !defined(NDEBUG)
7.139 + bool Locked() const {
7.140 + return owner_ != 0;
7.141 + }
7.142 + ThreadId Owner() const {
7.143 + return owner_;
7.144 + }
7.145 +#endif
7.146 +
7.147 + virtual bool DoTryLock() = 0;
7.148 + virtual void DoLock() = 0;
7.149 + virtual void DoUnlock() = 0;
7.150 +
7.151 + protected:
7.152 + void DebugSetUnlocked() {
7.153 +#if !defined(NDEBUG)
7.154 + owner_ = 0;
7.155 +#endif
7.156 + }
7.157 + void DebugSetLocked() {
7.158 +#if !defined(NDEBUG)
7.159 + owner_ = GetCurrentThreadId();
7.160 +#endif
7.161 + }
7.162 +
7.163 + protected:
7.164 +#if !defined(NDEBUG)
7.165 + ThreadId owner_;
7.166 +#endif
7.167 +};
7.168 +
7.169 +// RAII for automatically locking and unlocking an object.
7.170 +class AutoLock
7.171 +{
7.172 + public:
7.173 + AutoLock(Lockable *lock)
7.174 + : lock_(lock)
7.175 + {
7.176 + lock_->Lock();
7.177 + }
7.178 + ~AutoLock() {
7.179 + lock_->Unlock();
7.180 + }
7.181 +
7.182 + private:
7.183 + Lockable *lock_;
7.184 +};
7.185 +
7.186 +class AutoTryLock
7.187 +{
7.188 + public:
7.189 + AutoTryLock(Lockable *lock)
7.190 + {
7.191 + lock_ = lock->TryLock() ? lock : NULL;
7.192 + }
7.193 + ~AutoTryLock() {
7.194 + if (lock_)
7.195 + lock_->Unlock();
7.196 + }
7.197 +
7.198 + private:
7.199 + Lockable *lock_;
7.200 +};
7.201 +
7.202 +// RAII for automatically unlocking and relocking an object.
7.203 +class AutoUnlock
7.204 +{
7.205 + public:
7.206 + AutoUnlock(Lockable *lock)
7.207 + : lock_(lock)
7.208 + {
7.209 + lock_->Unlock();
7.210 + }
7.211 + ~AutoUnlock() {
7.212 + lock_->Lock();
7.213 + }
7.214 +
7.215 + private:
7.216 + Lockable *lock_;
7.217 +};
7.218 +
7.219 +enum WaitResult {
7.220 + // Woke up because something happened.
7.221 + Wait_Signaled,
7.222 +
7.223 + // Woke up because nothing happened and a timeout was specified.
7.224 + Wait_Timeout,
7.225 +
7.226 + // Woke up, but because of an error.
7.227 + Wait_Error
7.228 +};
7.229 +
7.230 +// This must be implemented in order to spawn a new thread.
7.231 +class IRunnable
7.232 +{
7.233 + public:
7.234 + virtual ~IRunnable() {
7.235 + }
7.236 +
7.237 + virtual void Run() = 0;
7.238 +};
7.239 +
7.240 +} // namespace ke
7.241 +
7.242 +// Include the actual thread implementations.
7.243 +#if defined(_MSC_VER)
7.244 +# include "ke_thread_windows.h"
7.245 +#else
7.246 +# include "ke_thread_posix.h"
7.247 +#endif
7.248 +
7.249 +#endif // _include_sourcepawn_threads_
8.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
8.2 +++ b/public/amtl/ke_thread_windows.h Thu Aug 22 16:30:44 2013 -0700
8.3 @@ -0,0 +1,148 @@
8.4 +// vim: set ts=8 sts=2 sw=2 tw=99 et:
8.5 +//
8.6 +// This file is part of SourcePawn.
8.7 +//
8.8 +// SourcePawn is free software: you can redistribute it and/or modify
8.9 +// it under the terms of the GNU General Public License as published by
8.10 +// the Free Software Foundation, either version 3 of the License, or
8.11 +// (at your option) any later version.
8.12 +//
8.13 +// SourcePawn is distributed in the hope that it will be useful,
8.14 +// but WITHOUT ANY WARRANTY; without even the implied warranty of
8.15 +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
8.16 +// GNU General Public License for more details.
8.17 +//
8.18 +// You should have received a copy of the GNU General Public License
8.19 +// along with SourcePawn. If not, see <http://www.gnu.org/licenses/>.
8.20 +#ifndef _include_sourcepawn_thread_windows_h_
8.21 +#define _include_sourcepawn_thread_windows_h_
8.22 +
8.23 +#include <windows.h>
8.24 +
8.25 +namespace ke {
8.26 +
8.27 +class CriticalSection : public Lockable
8.28 +{
8.29 + public:
8.30 + CriticalSection() {
8.31 + InitializeCriticalSection(&cs_);
8.32 + }
8.33 + ~CriticalSection() {
8.34 + DeleteCriticalSection(&cs_);
8.35 + }
8.36 +
8.37 + bool DoTryLock() {
8.38 + return !!TryEnterCriticalSection(&cs_);
8.39 + }
8.40 + void DoLock() {
8.41 + EnterCriticalSection(&cs_);
8.42 + }
8.43 +
8.44 + void DoUnlock() {
8.45 + LeaveCriticalSection(&cs_);
8.46 + }
8.47 +
8.48 + private:
8.49 + CRITICAL_SECTION cs_;
8.50 +};
8.51 +
8.52 +typedef CriticalSection Mutex;
8.53 +
8.54 +// Currently, this class only supports single-listener CVs.
8.55 +class ConditionVariable : public Lockable
8.56 +{
8.57 + public:
8.58 + ConditionVariable() {
8.59 + event_ = CreateEvent(NULL, FALSE, FALSE, NULL);
8.60 + }
8.61 + ~ConditionVariable() {
8.62 + CloseHandle(event_);
8.63 + }
8.64 +
8.65 + bool DoTryLock() {
8.66 + return cs_.DoTryLock();
8.67 + }
8.68 + void DoLock() {
8.69 + cs_.DoLock();
8.70 + }
8.71 + void DoUnlock() {
8.72 + cs_.DoUnlock();
8.73 + }
8.74 +
8.75 + void Notify() {
8.76 + AssertCurrentThreadOwns();
8.77 + SetEvent(event_);
8.78 + }
8.79 +
8.80 + WaitResult Wait(size_t timeout_ms) {
8.81 + // This will assert if the lock has not been acquired. We don't need to be
8.82 + // atomic here, like pthread_cond_wait, because the event bit will stick
8.83 + // until reset by a wait function.
8.84 + Unlock();
8.85 + DWORD rv = WaitForSingleObject(event_, timeout_ms);
8.86 + Lock();
8.87 +
8.88 + if (rv == WAIT_TIMEOUT)
8.89 + return Wait_Timeout;
8.90 + if (rv == WAIT_FAILED)
8.91 + return Wait_Error;
8.92 + return Wait_Signaled;
8.93 + }
8.94 +
8.95 + WaitResult Wait() {
8.96 + return Wait(INFINITE);
8.97 + }
8.98 +
8.99 + private:
8.100 + CriticalSection cs_;
8.101 + HANDLE event_;
8.102 +};
8.103 +
8.104 +class Thread
8.105 +{
8.106 + public:
8.107 + Thread(IRunnable *run, const char *name = NULL) {
8.108 + thread_ = CreateThread(NULL, 0, Main, run, 0, NULL);
8.109 + }
8.110 + ~Thread() {
8.111 + if (!thread_)
8.112 + return;
8.113 + CloseHandle(thread_);
8.114 + }
8.115 +
8.116 + bool Succeeded() const {
8.117 + return !!thread_;
8.118 + }
8.119 +
8.120 + void Join() {
8.121 + if (!Succeeded())
8.122 + return;
8.123 + WaitForSingleObject(thread_, INFINITE);
8.124 + }
8.125 +
8.126 + HANDLE handle() const {
8.127 + return thread_;
8.128 + }
8.129 +
8.130 + private:
8.131 + static DWORD WINAPI Main(LPVOID arg) {
8.132 + ((IRunnable *)arg)->Run();
8.133 + return 0;
8.134 + }
8.135 +
8.136 +#pragma pack(push, 8)
8.137 + struct ThreadNameInfo {
8.138 + DWORD dwType;
8.139 + LPCSTR szName;
8.140 + DWORD dwThreadID;
8.141 + DWORD dwFlags;
8.142 + };
8.143 +#pragma pack(pop)
8.144 +
8.145 + private:
8.146 + HANDLE thread_;
8.147 +};
8.148 +
8.149 +} // namespace ke
8.150 +
8.151 +#endif // _include_sourcepawn_thread_windows_h_
9.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
9.2 +++ b/public/amtl/ke_utility.h Thu Aug 22 16:30:44 2013 -0700
9.3 @@ -0,0 +1,327 @@
9.4 +/* vim: set ts=4 sw=4 tw=99 et:
9.5 + *
9.6 + * Copyright (C) 2012-2013 David Anderson
9.7 + *
9.8 + * This file is part of SourcePawn.
9.9 + *
9.10 + * SourcePawn is free software: you can redistribute it and/or modify it under
9.11 + * the terms of the GNU General Public License as published by the Free
9.12 + * Software Foundation, either version 3 of the License, or (at your option)
9.13 + * any later version.
9.14 + *
9.15 + * SourcePawn is distributed in the hope that it will be useful, but WITHOUT ANY
9.16 + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
9.17 + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
9.18 + *
9.19 + * You should have received a copy of the GNU General Public License along with
9.20 + * SourcePawn. If not, see http://www.gnu.org/licenses/.
9.21 + */
9.22 +#ifndef _include_jitcraft_utility_h_
9.23 +#define _include_jitcraft_utility_h_
9.24 +
9.25 +#include <assert.h>
9.26 +#include <stddef.h>
9.27 +#include <stdlib.h>
9.28 +#include <stdint.h>
9.29 +#if defined(_MSC_VER)
9.30 +# include <intrin.h>
9.31 +#endif
9.32 +
9.33 +#define KE_32BIT
9.34 +
9.35 +#if defined(_MSC_VER)
9.36 +# pragma warning(disable:4355)
9.37 +#endif
9.38 +
9.39 +namespace ke {
9.40 +
9.41 +static const size_t kMallocAlignment = sizeof(void *) * 2;
9.42 +
9.43 +typedef uint8_t uint8;
9.44 +typedef int32_t int32;
9.45 +typedef uint32_t uint32;
9.46 +typedef int64_t int64;
9.47 +typedef uint64_t uint64;
9.48 +
9.49 +typedef uint8 * Address;
9.50 +
9.51 +static const size_t kKB = 1024;
9.52 +static const size_t kMB = 1024 * kKB;
9.53 +static const size_t kGB = 1024 * kMB;
9.54 +
9.55 +template <typename T> T
9.56 +ReturnAndVoid(T &t)
9.57 +{
9.58 + T saved = t;
9.59 + t = T();
9.60 + return saved;
9.61 +}
9.62 +
9.63 +// Wrapper that automatically deletes its contents. The pointer can be taken
9.64 +// to avoid destruction.
9.65 +template <typename T>
9.66 +class AutoPtr
9.67 +{
9.68 + T *t_;
9.69 +
9.70 + public:
9.71 + AutoPtr()
9.72 + : t_(NULL)
9.73 + {
9.74 + }
9.75 + explicit AutoPtr(T *t)
9.76 + : t_(t)
9.77 + {
9.78 + }
9.79 + ~AutoPtr() {
9.80 + delete t_;
9.81 + }
9.82 + T *take() {
9.83 + return ReturnAndVoid(t_);
9.84 + }
9.85 + T *operator *() const {
9.86 + return t_;
9.87 + }
9.88 + T *operator ->() const {
9.89 + return t_;
9.90 + }
9.91 + operator T *() const {
9.92 + return t_;
9.93 + }
9.94 + void operator =(T *t) {
9.95 + delete t_;
9.96 + t_ = t;
9.97 + }
9.98 + bool operator !() const {
9.99 + return !t_;
9.100 + }
9.101 +};
9.102 +
9.103 +// Bob Jenkin's one-at-a-time hash function[1].
9.104 +//
9.105 +// [1] http://burtleburtle.net/bob/hash/doobs.html
9.106 +class CharacterStreamHasher
9.107 +{
9.108 + uint32 hash;
9.109 +
9.110 + public:
9.111 + CharacterStreamHasher()
9.112 + : hash(0)
9.113 + { }
9.114 +
9.115 + void add(char c) {
9.116 + hash += c;
9.117 + hash += (hash << 10);
9.118 + hash ^= (hash >> 6);
9.119 + }
9.120 +
9.121 + void add(const char *s, size_t length) {
9.122 + for (size_t i = 0; i < length; i++)
9.123 + add(s[i]);
9.124 + }
9.125 +
9.126 + uint32 result() {
9.127 + hash += (hash << 3);
9.128 + hash ^= (hash >> 11);
9.129 + hash += (hash << 15);
9.130 + return hash;
9.131 + }
9.132 +};
9.133 +
9.134 +static inline uint32
9.135 +HashCharSequence(const char *s, size_t length)
9.136 +{
9.137 + CharacterStreamHasher hasher;
9.138 + hasher.add(s, length);
9.139 + return hasher.result();
9.140 +}
9.141 +
9.142 +// From http://burtleburtle.net/bob/hash/integer.html
9.143 +static inline uint32
9.144 +HashInt32(int32 a)
9.145 +{
9.146 + a = (a ^ 61) ^ (a >> 16);
9.147 + a = a + (a << 3);
9.148 + a = a ^ (a >> 4);
9.149 + a = a * 0x27d4eb2d;
9.150 + a = a ^ (a >> 15);
9.151 + return a;
9.152 +}
9.153 +
9.154 +// From http://www.cris.com/~Ttwang/tech/inthash.htm
9.155 +static inline uint32
9.156 +HashInt64(int64 key)
9.157 +{
9.158 + key = (~key) + (key << 18); // key = (key << 18) - key - 1;
9.159 + key = key ^ (uint64(key) >> 31);
9.160 + key = key * 21; // key = (key + (key << 2)) + (key << 4);
9.161 + key = key ^ (uint64(key) >> 11);
9.162 + key = key + (key << 6);
9.163 + key = key ^ (uint64(key) >> 22);
9.164 + return uint32(key);
9.165 +}
9.166 +
9.167 +static inline uint32
9.168 +HashPointer(void *p)
9.169 +{
9.170 +#if defined(KE_32BIT)
9.171 + return HashInt32(reinterpret_cast<int32>(p));
9.172 +#elif defined(KE_64BIT)
9.173 + return HashInt64(reinterpret_cast<int64>(p));
9.174 +#endif
9.175 +}
9.176 +
9.177 +static inline size_t
9.178 +Log2(size_t number)
9.179 +{
9.180 + assert(number != 0);
9.181 +
9.182 +#ifdef _MSC_VER
9.183 + unsigned long rval;
9.184 +# ifdef _M_IX86
9.185 + _BitScanReverse(&rval, number);
9.186 +# elif _M_X64
9.187 + _BitScanReverse64(&rval, number);
9.188 +# endif
9.189 + return rval;
9.190 +#else
9.191 + size_t bit;
9.192 + asm("bsr %1, %0\n"
9.193 + : "=r" (bit)
9.194 + : "rm" (number));
9.195 + return bit;
9.196 +#endif
9.197 +}
9.198 +
9.199 +static inline size_t
9.200 +FindRightmostBit(size_t number)
9.201 +{
9.202 + assert(number != 0);
9.203 +
9.204 +#ifdef _MSC_VER
9.205 + unsigned long rval;
9.206 +# ifdef _M_IX86
9.207 + _BitScanForward(&rval, number);
9.208 +# elif _M_X64
9.209 + _BitScanForward64(&rval, number);
9.210 +# endif
9.211 + return rval;
9.212 +#else
9.213 + size_t bit;
9.214 + asm("bsf %1, %0\n"
9.215 + : "=r" (bit)
9.216 + : "rm" (number));
9.217 + return bit;
9.218 +#endif
9.219 +}
9.220 +
9.221 +static inline bool
9.222 +IsPowerOfTwo(size_t value)
9.223 +{
9.224 + if (value == 0)
9.225 + return false;
9.226 + return !(value & (value - 1));
9.227 +}
9.228 +
9.229 +static inline size_t
9.230 +Align(size_t count, size_t alignment)
9.231 +{
9.232 + assert(IsPowerOfTwo(alignment));
9.233 + return count + (alignment - (count % alignment)) % alignment;
9.234 +}
9.235 +
9.236 +static inline bool
9.237 +IsUint32AddSafe(unsigned a, unsigned b)
9.238 +{
9.239 + if (!a || !b)
9.240 + return true;
9.241 + size_t log2_a = Log2(a);
9.242 + size_t log2_b = Log2(b);
9.243 + return (log2_a < sizeof(unsigned) * 8) &&
9.244 + (log2_b < sizeof(unsigned) * 8);
9.245 +}
9.246 +
9.247 +static inline bool
9.248 +IsUintPtrAddSafe(size_t a, size_t b)
9.249 +{
9.250 + if (!a || !b)
9.251 + return true;
9.252 + size_t log2_a = Log2(a);
9.253 + size_t log2_b = Log2(b);
9.254 + return (log2_a < sizeof(size_t) * 8) &&
9.255 + (log2_b < sizeof(size_t) * 8);
9.256 +}
9.257 +
9.258 +static inline bool
9.259 +IsUint32MultiplySafe(unsigned a, unsigned b)
9.260 +{
9.261 + if (a <= 1 || b <= 1)
9.262 + return true;
9.263 +
9.264 + size_t log2_a = Log2(a);
9.265 + size_t log2_b = Log2(b);
9.266 + return log2_a + log2_b <= sizeof(unsigned) * 8;
9.267 +}
9.268 +
9.269 +static inline bool
9.270 +IsUintPtrMultiplySafe(size_t a, size_t b)
9.271 +{
9.272 + if (a <= 1 || b <= 1)
9.273 + return true;
9.274 +
9.275 + size_t log2_a = Log2(a);
9.276 + size_t log2_b = Log2(b);
9.277 + return log2_a + log2_b <= sizeof(size_t) * 8;
9.278 +}
9.279 +
9.280 +#define ARRAY_LENGTH(array) (sizeof(array) / sizeof(array[0]))
9.281 +#define STATIC_ASSERT(cond) extern int static_assert_f(int a[(cond) ? 1 : -1])
9.282 +
9.283 +#define IS_ALIGNED(addr, alignment) (!(uintptr_t(addr) & ((alignment) - 1)))
9.284 +
9.285 +template <typename T>
9.286 +static inline bool
9.287 +IsAligned(T addr, size_t alignment)
9.288 +{
9.289 + assert(IsPowerOfTwo(alignment));
9.290 + return !(uintptr_t(addr) & (alignment - 1));
9.291 +}
9.292 +
9.293 +static inline Address
9.294 +AlignedBase(Address addr, size_t alignment)
9.295 +{
9.296 + assert(IsPowerOfTwo(alignment));
9.297 + return Address(uintptr_t(addr) & ~(alignment - 1));
9.298 +}
9.299 +
9.300 +template <typename T> static inline T
9.301 +Min(const T &t1, const T &t2)
9.302 +{
9.303 + return t1 < t2 ? t1 : t2;
9.304 +}
9.305 +
9.306 +template <typename T> static inline T
9.307 +Max(const T &t1, const T &t2)
9.308 +{
9.309 + return t1 > t2 ? t1 : t2;
9.310 +}
9.311 +
9.312 +#define OFFSETOF(Class, Member) reinterpret_cast<size_t>(&((Class *)NULL)->Member)
9.313 +
9.314 +#if defined(_MSC_VER)
9.315 +# define KE_SIZET_FMT "%Iu"
9.316 +#elif defined(__GNUC__)
9.317 +# define KE_SIZET_FMT "%zu"
9.318 +#else
9.319 +# error "Implement format specifier string"
9.320 +#endif
9.321 +
9.322 +#if defined(__GNUC__)
9.323 +# define KE_CRITICAL_LIKELY(x) __builtin_expect(!!(x), 1)
9.324 +#else
9.325 +# define KE_CRITICAL_LIKELY(x) x
9.326 +#endif
9.327 +
9.328 +}
9.329 +
9.330 +#endif // _include_jitcraft_utility_h_
10.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
10.2 +++ b/public/amtl/ke_vector.h Thu Aug 22 16:30:44 2013 -0700
10.3 @@ -0,0 +1,166 @@
10.4 +/* vim: set ts=2 sw=2 tw=99 et:
10.5 + *
10.6 + * Copyright (C) 2012 David Anderson
10.7 + *
10.8 + * This file is part of SourcePawn.
10.9 + *
10.10 + * SourcePawn is free software: you can redistribute it and/or modify it under
10.11 + * the terms of the GNU General Public License as published by the Free
10.12 + * Software Foundation, either version 3 of the License, or (at your option)
10.13 + * any later version.
10.14 + *
10.15 + * SourcePawn is distributed in the hope that it will be useful, but WITHOUT ANY
10.16 + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
10.17 + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
10.18 + *
10.19 + * You should have received a copy of the GNU General Public License along with
10.20 + * SourcePawn. If not, see http://www.gnu.org/licenses/.
10.21 + */
10.22 +#ifndef _INCLUDE_KEIMA_TPL_CPP_VECTOR_H_
10.23 +#define _INCLUDE_KEIMA_TPL_CPP_VECTOR_H_
10.24 +
10.25 +#include <new>
10.26 +#include <stdlib.h>
10.27 +#include <ke_allocator_policies.h>
10.28 +#include <ke_utility.h>
10.29 +
10.30 +namespace ke {
10.31 +
10.32 +template <typename T, typename AllocPolicy = SystemAllocatorPolicy>
10.33 +class Vector : public AllocPolicy
10.34 +{
10.35 + public:
10.36 + Vector(AllocPolicy = AllocPolicy())
10.37 + : data(NULL),
10.38 + nitems(0),
10.39 + maxsize(0)
10.40 + {
10.41 + }
10.42 +
10.43 + ~Vector()
10.44 + {
10.45 + zap();
10.46 + }
10.47 +
10.48 + void steal(Vector &other) {
10.49 + zap();
10.50 + data = other.data;
10.51 + nitems = other.nitems;
10.52 + maxsize = other.maxsize;
10.53 + other.reset();
10.54 + }
10.55 +
10.56 + bool append(const T& item) {
10.57 + if (!growIfNeeded(1))
10.58 + return false;
10.59 + new (&data[nitems]) T(item);
10.60 + nitems++;
10.61 + return true;
10.62 + }
10.63 + void infallibleAppend(const T &item) {
10.64 + assert(growIfNeeded(1));
10.65 + new (&data[nitems]) T(item);
10.66 + nitems++;
10.67 + }
10.68 + T popCopy() {
10.69 + T t = at(length() - 1);
10.70 + pop();
10.71 + return t;
10.72 + }
10.73 + void pop() {
10.74 + assert(nitems);
10.75 + data[nitems - 1].~T();
10.76 + nitems--;
10.77 + }
10.78 + bool empty() const {
10.79 + return length() == 0;
10.80 + }
10.81 + size_t length() const {
10.82 + return nitems;
10.83 + }
10.84 + T& at(size_t i) {
10.85 + assert(i < length());
10.86 + return data[i];
10.87 + }
10.88 + const T& at(size_t i) const {
10.89 + assert(i < length());
10.90 + return data[i];
10.91 + }
10.92 + T& operator [](size_t i) {
10.93 + return at(i);
10.94 + }
10.95 + const T& operator [](size_t i) const {
10.96 + return at(i);
10.97 + }
10.98 + void clear() {
10.99 + nitems = 0;
10.100 + }
10.101 + const T &back() const {
10.102 + return at(length() - 1);
10.103 + }
10.104 + T &back() {
10.105 + return at(length() - 1);
10.106 + }
10.107 +
10.108 + T *buffer() const {
10.109 + return data;
10.110 + }
10.111 +
10.112 + bool ensure(size_t desired) {
10.113 + if (desired <= length())
10.114 + return true;
10.115 +
10.116 + return growIfNeeded(desired - length());
10.117 + }
10.118 +
10.119 + private:
10.120 + void zap() {
10.121 + for (size_t i = 0; i < nitems; i++)
10.122 + data[i].~T();
10.123 + this->free(data);
10.124 + }
10.125 + void reset() {
10.126 + data = NULL;
10.127 + nitems = 0;
10.128 + maxsize = 0;
10.129 + }
10.130 +
10.131 + bool growIfNeeded(size_t needed)
10.132 + {
10.133 + if (!IsUintPtrAddSafe(nitems, needed)) {
10.134 + this->reportAllocationOverflow();
10.135 + return false;
10.136 + }
10.137 + if (nitems + needed < maxsize)
10.138 + return true;
10.139 + if (maxsize == 0)
10.140 + maxsize = 8;
10.141 + while (nitems + needed > maxsize) {
10.142 + if (!IsUintPtrMultiplySafe(maxsize, 2)) {
10.143 + this->reportAllocationOverflow();
10.144 + return false;
10.145 + }
10.146 + maxsize *= 2;
10.147 + }
10.148 + T* newdata = (T*)this->malloc(sizeof(T) * maxsize);
10.149 + if (newdata == NULL)
10.150 + return false;
10.151 + for (size_t i = 0; i < nitems; i++) {
10.152 + new (&newdata[i]) T(data[i]);
10.153 + data[i].~T();
10.154 + }
10.155 + this->free(data);
10.156 + data = newdata;
10.157 + return true;
10.158 + }
10.159 +
10.160 + private:
10.161 + T* data;
10.162 + size_t nitems;
10.163 + size_t maxsize;
10.164 +};
10.165 +
10.166 +}
10.167 +
10.168 +#endif /* _INCLUDE_KEIMA_TPL_CPP_VECTOR_H_ */
10.169 +
11.1 --- a/public/sourcepawn/ke_allocator_policies.h Thu Aug 22 14:05:44 2013 -0700
11.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
11.3 @@ -1,53 +0,0 @@
11.4 -/* vim: set ts=2 sw=2 tw=99 et:
11.5 - *
11.6 - * Copyright (C) 2012 David Anderson
11.7 - *
11.8 - * This file is part of SourcePawn.
11.9 - *
11.10 - * SourcePawn is free software: you can redistribute it and/or modify it under
11.11 - * the terms of the GNU General Public License as published by the Free
11.12 - * Software Foundation, either version 3 of the License, or (at your option)
11.13 - * any later version.
11.14 - *
11.15 - * SourcePawn is distributed in the hope that it will be useful, but WITHOUT ANY
11.16 - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11.17 - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
11.18 - *
11.19 - * You should have received a copy of the GNU General Public License along with
11.20 - * SourcePawn. If not, see http://www.gnu.org/licenses/.
11.21 - */
11.22 -#ifndef _include_sourcepawn_allocatorpolicies_h_
11.23 -#define _include_sourcepawn_allocatorpolicies_h_
11.24 -
11.25 -#include <stdio.h>
11.26 -#include <stdlib.h>
11.27 -
11.28 -namespace ke {
11.29 -
11.30 -class SystemAllocatorPolicy
11.31 -{
11.32 - protected:
11.33 - void reportOutOfMemory() {
11.34 - fprintf(stderr, "OUT OF MEMORY\n");
11.35 - abort();
11.36 - }
11.37 - void reportAllocationOverflow() {
11.38 - fprintf(stderr, "OUT OF MEMORY\n");
11.39 - abort();
11.40 - }
11.41 -
11.42 - public:
11.43 - void free(void *memory) {
11.44 - ::free(memory);
11.45 - }
11.46 - void *malloc(size_t bytes) {
11.47 - void *ptr = ::malloc(bytes);
11.48 - if (!ptr)
11.49 - reportOutOfMemory();
11.50 - return ptr;
11.51 - }
11.52 -};
11.53 -
11.54 -}
11.55 -
11.56 -#endif // _include_sourcepawn_allocatorpolicies_h_
12.1 --- a/public/sourcepawn/ke_inline_list.h Thu Aug 22 14:05:44 2013 -0700
12.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
12.3 @@ -1,137 +0,0 @@
12.4 -/**
12.5 - * vim: set sts=2 ts=8 sw=2 tw=99 noet :
12.6 - * =============================================================================
12.7 - * SourcePawn
12.8 - * Copyright (C) 2004-2009 AlliedModders LLC. All rights reserved.
12.9 - * =============================================================================
12.10 - *
12.11 - * This program is free software; you can redistribute it and/or modify it under
12.12 - * the terms of the GNU General Public License, version 3.0, as published by the
12.13 - * Free Software Foundation.
12.14 - *
12.15 - * This program is distributed in the hope that it will be useful, but WITHOUT
12.16 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12.17 - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
12.18 - * details.
12.19 - *
12.20 - * You should have received a copy of the GNU General Public License along with
12.21 - * this program. If not, see <http://www.gnu.org/licenses/>.
12.22 - *
12.23 - * As a special exception, AlliedModders LLC gives you permission to link the
12.24 - * code of this program (as well as its derivative works) to "Half-Life 2," the
12.25 - * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
12.26 - * by the Valve Corporation. You must obey the GNU General Public License in
12.27 - * all respects for all other code used. Additionally, AlliedModders LLC grants
12.28 - * this exception to all derivative works. AlliedModders LLC defines further
12.29 - * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
12.30 - * or <http://www.sourcemod.net/license.php>.
12.31 - */
12.32 -#ifndef _include_sourcepawn_inline_list_h_
12.33 -#define _include_sourcepawn_inline_list_h_
12.34 -
12.35 -#include <stddef.h>
12.36 -
12.37 -template <typename T> class InlineList;
12.38 -
12.39 -template <typename T>
12.40 -class InlineListNode
12.41 -{
12.42 - friend class InlineList<T>;
12.43 -
12.44 - public:
12.45 - InlineListNode()
12.46 - : next_(NULL),
12.47 - prev_(NULL)
12.48 - {
12.49 - }
12.50 -
12.51 - InlineListNode(InlineListNode *next, InlineListNode *prev)
12.52 - : next_(next),
12.53 - prev_(prev)
12.54 - {
12.55 - }
12.56 -
12.57 - protected:
12.58 - InlineListNode *next_;
12.59 - InlineListNode *prev_;
12.60 -};
12.61 -
12.62 -template <typename T>
12.63 -class InlineList
12.64 -{
12.65 - typedef InlineListNode<T> Node;
12.66 -
12.67 - Node head_;
12.68 -
12.69 - public:
12.70 - InlineList()
12.71 - : head_(&head_, &head_)
12.72 - {
12.73 - }
12.74 -
12.75 - public:
12.76 - class iterator
12.77 - {
12.78 - friend class InlineList;
12.79 - Node *iter_;
12.80 -
12.81 - public:
12.82 - iterator(Node *iter)
12.83 - : iter_(iter)
12.84 - {
12.85 - }
12.86 -
12.87 - iterator & operator ++() {
12.88 - iter_ = iter_->next;
12.89 - return *iter_;
12.90 - }
12.91 - iterator operator ++(int) {
12.92 - iterator old(*this);
12.93 - iter_ = iter_->next_;
12.94 - return old;
12.95 - }
12.96 - T * operator *() {
12.97 - return static_cast<T *>(iter_);
12.98 - }
12.99 - T * operator ->() {
12.100 - return static_cast<T *>(iter_);
12.101 - }
12.102 - bool operator !=(const iterator &where) const {
12.103 - return iter_ != where.iter_;
12.104 - }
12.105 - bool operator ==(const iterator &where) const {
12.106 - return iter_ == where.iter_;
12.107 - }
12.108 - iterator prev() const {
12.109 - iterator p(iter_->prev_);
12.110 - return p;
12.111 - }
12.112 - iterator next() const {
12.113 - iterator p(iter_->next_);
12.114 - return p;
12.115 - }
12.116 - };
12.117 -
12.118 - iterator begin() {
12.119 - return iterator(head_.next_);
12.120 - }
12.121 -
12.122 - iterator end() {
12.123 - return iterator(&head_);
12.124 - }
12.125 -
12.126 - void erase(Node *t) {
12.127 - t->prev_->next_ = t->next_;
12.128 - t->next_->prev_ = t->prev_;
12.129 - }
12.130 -
12.131 - void insert(Node *t) {
12.132 - t->prev_ = head_.prev_;
12.133 - t->next_ = &head_;
12.134 - head_.prev_->next_ = t;
12.135 - head_.prev_ = t;
12.136 - }
12.137 -};
12.138 -
12.139 -#endif // _include_sourcepawn_inline_list_h_
12.140 -
13.1 --- a/public/sourcepawn/ke_thread_posix.h Thu Aug 22 14:05:44 2013 -0700
13.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
13.3 @@ -1,200 +0,0 @@
13.4 -// vim: set ts=8 sts=2 sw=2 tw=99 et:
13.5 -//
13.6 -// This file is part of SourcePawn.
13.7 -//
13.8 -// SourcePawn is free software: you can redistribute it and/or modify
13.9 -// it under the terms of the GNU General Public License as published by
13.10 -// the Free Software Foundation, either version 3 of the License, or
13.11 -// (at your option) any later version.
13.12 -//
13.13 -// SourcePawn is distributed in the hope that it will be useful,
13.14 -// but WITHOUT ANY WARRANTY; without even the implied warranty of
13.15 -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13.16 -// GNU General Public License for more details.
13.17 -//
13.18 -// You should have received a copy of the GNU General Public License
13.19 -// along with SourcePawn. If not, see <http://www.gnu.org/licenses/>.
13.20 -#ifndef _include_sourcepawn_thread_posix_h_
13.21 -#define _include_sourcepawn_thread_posix_h_
13.22 -
13.23 -#include <pthread.h>
13.24 -#include <sys/time.h>
13.25 -#include <errno.h>
13.26 -#include <stdio.h>
13.27 -#if defined(__linux__)
13.28 -# include <sys/prctl.h>
13.29 -#endif
13.30 -#if defined(__APPLE__)
13.31 -# include <dlfcn.h>
13.32 -#endif
13.33 -
13.34 -namespace ke {
13.35 -
13.36 -class Mutex : public Lockable
13.37 -{
13.38 - public:
13.39 - Mutex() {
13.40 -#if !defined(NDEBUG)
13.41 - int rv =
13.42 -#endif
13.43 - pthread_mutex_init(&mutex_, NULL);
13.44 - assert(rv == 0);
13.45 - }
13.46 - ~Mutex() {
13.47 - pthread_mutex_destroy(&mutex_);
13.48 - }
13.49 -
13.50 - bool DoTryLock() {
13.51 - return pthread_mutex_trylock(&mutex_) == 0;
13.52 - }
13.53 -
13.54 - void DoLock() {
13.55 - pthread_mutex_lock(&mutex_);
13.56 - }
13.57 -
13.58 - void DoUnlock() {
13.59 - pthread_mutex_unlock(&mutex_);
13.60 - }
13.61 -
13.62 - pthread_mutex_t *raw() {
13.63 - return &mutex_;
13.64 - }
13.65 -
13.66 - private:
13.67 - pthread_mutex_t mutex_;
13.68 -};
13.69 -
13.70 -// Currently, this class only supports single-listener CVs.
13.71 -class ConditionVariable : public Lockable
13.72 -{
13.73 - public:
13.74 - ConditionVariable() {
13.75 -#if !defined(NDEBUG)
13.76 - int rv =
13.77 -#endif
13.78 - pthread_cond_init(&cv_, NULL);
13.79 - assert(rv == 0);
13.80 - }
13.81 - ~ConditionVariable() {
13.82 - pthread_cond_destroy(&cv_);
13.83 - }
13.84 -
13.85 - bool DoTryLock() {
13.86 - return mutex_.DoTryLock();
13.87 - }
13.88 - void DoLock() {
13.89 - mutex_.DoLock();
13.90 - }
13.91 - void DoUnlock() {
13.92 - mutex_.DoUnlock();
13.93 - }
13.94 -
13.95 - void Notify() {
13.96 - AssertCurrentThreadOwns();
13.97 - pthread_cond_signal(&cv_);
13.98 - }
13.99 -
13.100 - WaitResult Wait(size_t timeout_ms) {
13.101 - AssertCurrentThreadOwns();
13.102 -
13.103 -#if defined(__linux__)
13.104 - struct timespec ts;
13.105 - if (clock_gettime(CLOCK_REALTIME, &ts) == -1)
13.106 - return Wait_Error;
13.107 -#else
13.108 - struct timeval tv;
13.109 - gettimeofday(&tv, NULL);
13.110 -
13.111 - struct timespec ts;
13.112 - ts.tv_sec = tv.tv_sec;
13.113 - ts.tv_nsec = tv.tv_usec * 1000;
13.114 -#endif
13.115 -
13.116 - ts.tv_sec += timeout_ms / 1000;
13.117 - ts.tv_nsec += (timeout_ms % 1000) * 1000000;
13.118 - if (ts.tv_nsec >= 1000000000) {
13.119 - ts.tv_sec++;
13.120 - ts.tv_nsec -= 1000000000;
13.121 - }
13.122 -
13.123 - DebugSetUnlocked();
13.124 - int rv = pthread_cond_timedwait(&cv_, mutex_.raw(), &ts);
13.125 - DebugSetLocked();
13.126 -
13.127 - if (rv == ETIMEDOUT)
13.128 - return Wait_Timeout;
13.129 - if (rv == 0)
13.130 - return Wait_Signaled;
13.131 - return Wait_Error;
13.132 - }
13.133 -
13.134 - WaitResult Wait() {
13.135 - AssertCurrentThreadOwns();
13.136 -
13.137 - DebugSetUnlocked();
13.138 - int rv = pthread_cond_wait(&cv_, mutex_.raw());
13.139 - DebugSetLocked();
13.140 -
13.141 - if (rv == 0)
13.142 - return Wait_Signaled;
13.143 - return Wait_Error;
13.144 - }
13.145 -
13.146 - private:
13.147 - Mutex mutex_;
13.148 - pthread_cond_t cv_;
13.149 -};
13.150 -
13.151 -class Thread
13.152 -{
13.153 - struct ThreadData {
13.154 - IRunnable *run;
13.155 - char name[17];
13.156 - };
13.157 - public:
13.158 - Thread(IRunnable *run, const char *name = NULL) {
13.159 - ThreadData *data = new ThreadData;
13.160 - data->run = run;
13.161 - snprintf(data->name, sizeof(data->name), "%s", name ? name : "");
13.162 -
13.163 - initialized_ = (pthread_create(&thread_, NULL, Main, data) == 0);
13.164 - if (!initialized_)
13.165 - delete data;
13.166 - }
13.167 -
13.168 - bool Succeeded() const {
13.169 - return initialized_;
13.170 - }
13.171 -
13.172 - void Join() {
13.173 - if (!Succeeded())
13.174 - return;
13.175 - pthread_join(thread_, NULL);
13.176 - }
13.177 -
13.178 - private:
13.179 - static void *Main(void *arg) {
13.180 - AutoPtr<ThreadData> data((ThreadData *)arg);
13.181 -
13.182 - if (data->name[0]) {
13.183 -#if defined(__linux__)
13.184 - prctl(PR_SET_NAME, (unsigned long)data->name);
13.185 -#elif defined(__APPLE__)
13.186 - int (*fn)(const char *) = (int (*)(const char *))dlsym(RTLD_DEFAULT, "pthread_setname_np");
13.187 - if (fn)
13.188 - fn(data->name);
13.189 -#endif
13.190 - }
13.191 - data->run->Run();
13.192 - return NULL;
13.193 - }
13.194 -
13.195 - private:
13.196 - bool initialized_;
13.197 - pthread_t thread_;
13.198 -};
13.199 -
13.200 -} // namespace ke
13.201 -
13.202 -#endif // _include_sourcepawn_thread_posix_h_
13.203 -
14.1 --- a/public/sourcepawn/ke_thread_utils.h Thu Aug 22 14:05:44 2013 -0700
14.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
14.3 @@ -1,246 +0,0 @@
14.4 -// vim: set ts=8 sts=2 sw=2 tw=99 et:
14.5 -//
14.6 -// This file is part of SourcePawn.
14.7 -//
14.8 -// SourcePawn is free software: you can redistribute it and/or modify
14.9 -// it under the terms of the GNU General Public License as published by
14.10 -// the Free Software Foundation, either version 3 of the License, or
14.11 -// (at your option) any later version.
14.12 -//
14.13 -// SourcePawn is distributed in the hope that it will be useful,
14.14 -// but WITHOUT ANY WARRANTY; without even the implied warranty of
14.15 -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14.16 -// GNU General Public License for more details.
14.17 -//
14.18 -// You should have received a copy of the GNU General Public License
14.19 -// along with SourcePawn. If not, see <http://www.gnu.org/licenses/>.
14.20 -#ifndef _include_sourcepawn_threads_
14.21 -#define _include_sourcepawn_threads_
14.22 -
14.23 -#include <assert.h>
14.24 -#if defined(_MSC_VER)
14.25 -# include <windows.h>
14.26 -# include <WinBase.h>
14.27 -#else
14.28 -# include <pthread.h>
14.29 -#endif
14.30 -#include <ke_utility.h>
14.31 -
14.32 -// Thread primitives for SourcePawn.
14.33 -//
14.34 -// -- Mutexes --
14.35 -//
14.36 -// A Lockable is a mutual exclusion primitive. It can be owned by at most one
14.37 -// thread at a time, and ownership blocks any other thread from taking taking
14.38 -// ownership. Ownership must be acquired and released on the same thread.
14.39 -// Lockables are not re-entrant.
14.40 -//
14.41 -// While a few classes support the Lockable interface, the simplest Lockable
14.42 -// object that can be instantiated is a Mutex.
14.43 -//
14.44 -// -- Condition Variables --
14.45 -//
14.46 -// A ConditionVariable provides mutually exclusive access based on a
14.47 -// condition ocurring. CVs provide two capabilities: Wait(), which will block
14.48 -// until the condition is triggered, and Notify(), which signals any blocking
14.49 -// thread that the condition has occurred.
14.50 -//
14.51 -// Condition variables have an underlying mutex lock. This lock must be
14.52 -// acquired before calling Wait() or Notify(). It is automatically released
14.53 -// once Wait begins blocking. This operation is atomic with respect to other
14.54 -// threads and the mutex. For example, it is not possible for the lock to be
14.55 -// acquired by another thread in between unlocking and blocking. Since Notify
14.56 -// also requires the lock to be acquired, there is no risk of an event
14.57 -// accidentally dissipating into thin air because it was sent before the other
14.58 -// thread began blocking.
14.59 -//
14.60 -// When Wait() returns, the lock is automatically re-acquired. This operation
14.61 -// is NOT atomic. In between waking up and re-acquiring the lock, another
14.62 -// thread may steal the lock and issue another event. Applications must
14.63 -// account for this. For example, a message pump should check that there are
14.64 -// no messages left to process before blocking again.
14.65 -//
14.66 -// Likewise, it is also not defined whether a Signal() will have any effect
14.67 -// while a thread is not waiting on the monitor. This is yet another reason
14.68 -// the above paragraph is so important - applications should, under a lock of
14.69 -// the condition variable - check for state changes before waiting.
14.70 -//
14.71 -// -- Threads --
14.72 -//
14.73 -// A Thread object, when created, spawns a new thread with the given callback
14.74 -// (the callbacks must implement IRunnable). Threads have one method of
14.75 -// interest, Join(), which will block until the thread's execution finishes.
14.76 -// Deleting a thread object will free any operating system resources associated
14.77 -// with that thread, if the thread has finished executing.
14.78 -//
14.79 -// Threads can fail to spawn; make sure to check Succeeded().
14.80 -//
14.81 -
14.82 -namespace ke {
14.83 -
14.84 -// Abstraction for getting a unique thread identifier. Debug-only.
14.85 -#if defined(_MSC_VER)
14.86 -typedef DWORD ThreadId;
14.87 -
14.88 -static inline ThreadId GetCurrentThreadId()
14.89 -{
14.90 - return ::GetCurrentThreadId();
14.91 -}
14.92 -#else
14.93 -typedef pthread_t ThreadId;
14.94 -
14.95 -static inline ThreadId GetCurrentThreadId()
14.96 -{
14.97 - return pthread_self();
14.98 -}
14.99 -#endif
14.100 -
14.101 -// Classes which use non-reentrant, same-thread lock/unlock semantics should
14.102 -// inherit from this and implement DoLock/DoUnlock.
14.103 -class Lockable
14.104 -{
14.105 - public:
14.106 - Lockable()
14.107 - {
14.108 -#if !defined(NDEBUG)
14.109 - owner_ = 0;
14.110 -#endif
14.111 - }
14.112 - virtual ~Lockable() {
14.113 - }
14.114 -
14.115 - bool TryLock() {
14.116 - if (DoTryLock()) {
14.117 - DebugSetLocked();
14.118 - return true;
14.119 - }
14.120 - return false;
14.121 - }
14.122 -
14.123 - void Lock() {
14.124 - assert(Owner() != GetCurrentThreadId());
14.125 - DoLock();
14.126 - DebugSetLocked();
14.127 - }
14.128 -
14.129 - void Unlock() {
14.130 - assert(Owner() == GetCurrentThreadId());
14.131 - DebugSetUnlocked();
14.132 - DoUnlock();
14.133 - }
14.134 -
14.135 - void AssertCurrentThreadOwns() const {
14.136 - assert(Owner() == GetCurrentThreadId());
14.137 - }
14.138 -#if !defined(NDEBUG)
14.139 - bool Locked() const {
14.140 - return owner_ != 0;
14.141 - }
14.142 - ThreadId Owner() const {
14.143 - return owner_;
14.144 - }
14.145 -#endif
14.146 -
14.147 - virtual bool DoTryLock() = 0;
14.148 - virtual void DoLock() = 0;
14.149 - virtual void DoUnlock() = 0;
14.150 -
14.151 - protected:
14.152 - void DebugSetUnlocked() {
14.153 -#if !defined(NDEBUG)
14.154 - owner_ = 0;
14.155 -#endif
14.156 - }
14.157 - void DebugSetLocked() {
14.158 -#if !defined(NDEBUG)
14.159 - owner_ = GetCurrentThreadId();
14.160 -#endif
14.161 - }
14.162 -
14.163 - protected:
14.164 -#if !defined(NDEBUG)
14.165 - ThreadId owner_;
14.166 -#endif
14.167 -};
14.168 -
14.169 -// RAII for automatically locking and unlocking an object.
14.170 -class AutoLock
14.171 -{
14.172 - public:
14.173 - AutoLock(Lockable *lock)
14.174 - : lock_(lock)
14.175 - {
14.176 - lock_->Lock();
14.177 - }
14.178 - ~AutoLock() {
14.179 - lock_->Unlock();
14.180 - }
14.181 -
14.182 - private:
14.183 - Lockable *lock_;
14.184 -};
14.185 -
14.186 -class AutoTryLock
14.187 -{
14.188 - public:
14.189 - AutoTryLock(Lockable *lock)
14.190 - {
14.191 - lock_ = lock->TryLock() ? lock : NULL;
14.192 - }
14.193 - ~AutoTryLock() {
14.194 - if (lock_)
14.195 - lock_->Unlock();
14.196 - }
14.197 -
14.198 - private:
14.199 - Lockable *lock_;
14.200 -};
14.201 -
14.202 -// RAII for automatically unlocking and relocking an object.
14.203 -class AutoUnlock
14.204 -{
14.205 - public:
14.206 - AutoUnlock(Lockable *lock)
14.207 - : lock_(lock)
14.208 - {
14.209 - lock_->Unlock();
14.210 - }
14.211 - ~AutoUnlock() {
14.212 - lock_->Lock();
14.213 - }
14.214 -
14.215 - private:
14.216 - Lockable *lock_;
14.217 -};
14.218 -
14.219 -enum WaitResult {
14.220 - // Woke up because something happened.
14.221 - Wait_Signaled,
14.222 -
14.223 - // Woke up because nothing happened and a timeout was specified.
14.224 - Wait_Timeout,
14.225 -
14.226 - // Woke up, but because of an error.
14.227 - Wait_Error
14.228 -};
14.229 -
14.230 -// This must be implemented in order to spawn a new thread.
14.231 -class IRunnable
14.232 -{
14.233 - public:
14.234 - virtual ~IRunnable() {
14.235 - }
14.236 -
14.237 - virtual void Run() = 0;
14.238 -};
14.239 -
14.240 -} // namespace ke
14.241 -
14.242 -// Include the actual thread implementations.
14.243 -#if defined(_MSC_VER)
14.244 -# include "ke_thread_windows.h"
14.245 -#else
14.246 -# include "ke_thread_posix.h"
14.247 -#endif
14.248 -
14.249 -#endif // _include_sourcepawn_threads_
15.1 --- a/public/sourcepawn/ke_thread_windows.h Thu Aug 22 14:05:44 2013 -0700
15.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
15.3 @@ -1,148 +0,0 @@
15.4 -// vim: set ts=8 sts=2 sw=2 tw=99 et:
15.5 -//
15.6 -// This file is part of SourcePawn.
15.7 -//
15.8 -// SourcePawn is free software: you can redistribute it and/or modify
15.9 -// it under the terms of the GNU General Public License as published by
15.10 -// the Free Software Foundation, either version 3 of the License, or
15.11 -// (at your option) any later version.
15.12 -//
15.13 -// SourcePawn is distributed in the hope that it will be useful,
15.14 -// but WITHOUT ANY WARRANTY; without even the implied warranty of
15.15 -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15.16 -// GNU General Public License for more details.
15.17 -//
15.18 -// You should have received a copy of the GNU General Public License
15.19 -// along with SourcePawn. If not, see <http://www.gnu.org/licenses/>.
15.20 -#ifndef _include_sourcepawn_thread_windows_h_
15.21 -#define _include_sourcepawn_thread_windows_h_
15.22 -
15.23 -#include <windows.h>
15.24 -
15.25 -namespace ke {
15.26 -
15.27 -class CriticalSection : public Lockable
15.28 -{
15.29 - public:
15.30 - CriticalSection() {
15.31 - InitializeCriticalSection(&cs_);
15.32 - }
15.33 - ~CriticalSection() {
15.34 - DeleteCriticalSection(&cs_);
15.35 - }
15.36 -
15.37 - bool DoTryLock() {
15.38 - return !!TryEnterCriticalSection(&cs_);
15.39 - }
15.40 - void DoLock() {
15.41 - EnterCriticalSection(&cs_);
15.42 - }
15.43 -
15.44 - void DoUnlock() {
15.45 - LeaveCriticalSection(&cs_);
15.46 - }
15.47 -
15.48 - private:
15.49 - CRITICAL_SECTION cs_;
15.50 -};
15.51 -
15.52 -typedef CriticalSection Mutex;
15.53 -
15.54 -// Currently, this class only supports single-listener CVs.
15.55 -class ConditionVariable : public Lockable
15.56 -{
15.57 - public:
15.58 - ConditionVariable() {
15.59 - event_ = CreateEvent(NULL, FALSE, FALSE, NULL);
15.60 - }
15.61 - ~ConditionVariable() {
15.62 - CloseHandle(event_);
15.63 - }
15.64 -
15.65 - bool DoTryLock() {
15.66 - return cs_.DoTryLock();
15.67 - }
15.68 - void DoLock() {
15.69 - cs_.DoLock();
15.70 - }
15.71 - void DoUnlock() {
15.72 - cs_.DoUnlock();
15.73 - }
15.74 -
15.75 - void Notify() {
15.76 - AssertCurrentThreadOwns();
15.77 - SetEvent(event_);
15.78 - }
15.79 -
15.80 - WaitResult Wait(size_t timeout_ms) {
15.81 - // This will assert if the lock has not been acquired. We don't need to be
15.82 - // atomic here, like pthread_cond_wait, because the event bit will stick
15.83 - // until reset by a wait function.
15.84 - Unlock();
15.85 - DWORD rv = WaitForSingleObject(event_, timeout_ms);
15.86 - Lock();
15.87 -
15.88 - if (rv == WAIT_TIMEOUT)
15.89 - return Wait_Timeout;
15.90 - if (rv == WAIT_FAILED)
15.91 - return Wait_Error;
15.92 - return Wait_Signaled;
15.93 - }
15.94 -
15.95 - WaitResult Wait() {
15.96 - return Wait(INFINITE);
15.97 - }
15.98 -
15.99 - private:
15.100 - CriticalSection cs_;
15.101 - HANDLE event_;
15.102 -};
15.103 -
15.104 -class Thread
15.105 -{
15.106 - public:
15.107 - Thread(IRunnable *run, const char *name = NULL) {
15.108 - thread_ = CreateThread(NULL, 0, Main, run, 0, NULL);
15.109 - }
15.110 - ~Thread() {
15.111 - if (!thread_)
15.112 - return;
15.113 - CloseHandle(thread_);
15.114 - }
15.115 -
15.116 - bool Succeeded() const {
15.117 - return !!thread_;
15.118 - }
15.119 -
15.120 - void Join() {
15.121 - if (!Succeeded())
15.122 - return;
15.123 - WaitForSingleObject(thread_, INFINITE);
15.124 - }
15.125 -
15.126 - HANDLE handle() const {
15.127 - return thread_;
15.128 - }
15.129 -
15.130 - private:
15.131 - static DWORD WINAPI Main(LPVOID arg) {
15.132 - ((IRunnable *)arg)->Run();
15.133 - return 0;
15.134 - }
15.135 -
15.136 -#pragma pack(push, 8)
15.137 - struct ThreadNameInfo {
15.138 - DWORD dwType;
15.139 - LPCSTR szName;
15.140 - DWORD dwThreadID;
15.141 - DWORD dwFlags;
15.142 - };
15.143 -#pragma pack(pop)
15.144 -
15.145 - private:
15.146 - HANDLE thread_;
15.147 -};
15.148 -
15.149 -} // namespace ke
15.150 -
15.151 -#endif // _include_sourcepawn_thread_windows_h_
16.1 --- a/public/sourcepawn/ke_utility.h Thu Aug 22 14:05:44 2013 -0700
16.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
16.3 @@ -1,327 +0,0 @@
16.4 -/* vim: set ts=4 sw=4 tw=99 et:
16.5 - *
16.6 - * Copyright (C) 2012-2013 David Anderson
16.7 - *
16.8 - * This file is part of SourcePawn.
16.9 - *
16.10 - * SourcePawn is free software: you can redistribute it and/or modify it under
16.11 - * the terms of the GNU General Public License as published by the Free
16.12 - * Software Foundation, either version 3 of the License, or (at your option)
16.13 - * any later version.
16.14 - *
16.15 - * SourcePawn is distributed in the hope that it will be useful, but WITHOUT ANY
16.16 - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
16.17 - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
16.18 - *
16.19 - * You should have received a copy of the GNU General Public License along with
16.20 - * SourcePawn. If not, see http://www.gnu.org/licenses/.
16.21 - */
16.22 -#ifndef _include_jitcraft_utility_h_
16.23 -#define _include_jitcraft_utility_h_
16.24 -
16.25 -#include <assert.h>
16.26 -#include <stddef.h>
16.27 -#include <stdlib.h>
16.28 -#include <stdint.h>
16.29 -#if defined(_MSC_VER)
16.30 -# include <intrin.h>
16.31 -#endif
16.32 -
16.33 -#define KE_32BIT
16.34 -
16.35 -#if defined(_MSC_VER)
16.36 -# pragma warning(disable:4355)
16.37 -#endif
16.38 -
16.39 -namespace ke {
16.40 -
16.41 -static const size_t kMallocAlignment = sizeof(void *) * 2;
16.42 -
16.43 -typedef uint8_t uint8;
16.44 -typedef int32_t int32;
16.45 -typedef uint32_t uint32;
16.46 -typedef int64_t int64;
16.47 -typedef uint64_t uint64;
16.48 -
16.49 -typedef uint8 * Address;
16.50 -
16.51 -static const size_t kKB = 1024;
16.52 -static const size_t kMB = 1024 * kKB;
16.53 -static const size_t kGB = 1024 * kMB;
16.54 -
16.55 -template <typename T> T
16.56 -ReturnAndVoid(T &t)
16.57 -{
16.58 - T saved = t;
16.59 - t = T();
16.60 - return saved;
16.61 -}
16.62 -
16.63 -// Wrapper that automatically deletes its contents. The pointer can be taken
16.64 -// to avoid destruction.
16.65 -template <typename T>
16.66 -class AutoPtr
16.67 -{
16.68 - T *t_;
16.69 -
16.70 - public:
16.71 - AutoPtr()
16.72 - : t_(NULL)
16.73 - {
16.74 - }
16.75 - explicit AutoPtr(T *t)
16.76 - : t_(t)
16.77 - {
16.78 - }
16.79 - ~AutoPtr() {
16.80 - delete t_;
16.81 - }
16.82 - T *take() {
16.83 - return ReturnAndVoid(t_);
16.84 - }
16.85 - T *operator *() const {
16.86 - return t_;
16.87 - }
16.88 - T *operator ->() const {
16.89 - return t_;
16.90 - }
16.91 - operator T *() const {
16.92 - return t_;
16.93 - }
16.94 - void operator =(T *t) {
16.95 - delete t_;
16.96 - t_ = t;
16.97 - }
16.98 - bool operator !() const {
16.99 - return !t_;
16.100 - }
16.101 -};
16.102 -
16.103 -// Bob Jenkin's one-at-a-time hash function[1].
16.104 -//
16.105 -// [1] http://burtleburtle.net/bob/hash/doobs.html
16.106 -class CharacterStreamHasher
16.107 -{
16.108 - uint32 hash;
16.109 -
16.110 - public:
16.111 - CharacterStreamHasher()
16.112 - : hash(0)
16.113 - { }
16.114 -
16.115 - void add(char c) {
16.116 - hash += c;
16.117 - hash += (hash << 10);
16.118 - hash ^= (hash >> 6);
16.119 - }
16.120 -
16.121 - void add(const char *s, size_t length) {
16.122 - for (size_t i = 0; i < length; i++)
16.123 - add(s[i]);
16.124 - }
16.125 -
16.126 - uint32 result() {
16.127 - hash += (hash << 3);
16.128 - hash ^= (hash >> 11);
16.129 - hash += (hash << 15);
16.130 - return hash;
16.131 - }
16.132 -};
16.133 -
16.134 -static inline uint32
16.135 -HashCharSequence(const char *s, size_t length)
16.136 -{
16.137 - CharacterStreamHasher hasher;
16.138 - hasher.add(s, length);
16.139 - return hasher.result();
16.140 -}
16.141 -
16.142 -// From http://burtleburtle.net/bob/hash/integer.html
16.143 -static inline uint32
16.144 -HashInt32(int32 a)
16.145 -{
16.146 - a = (a ^ 61) ^ (a >> 16);
16.147 - a = a + (a << 3);
16.148 - a = a ^ (a >> 4);
16.149 - a = a * 0x27d4eb2d;
16.150 - a = a ^ (a >> 15);
16.151 - return a;
16.152 -}
16.153 -
16.154 -// From http://www.cris.com/~Ttwang/tech/inthash.htm
16.155 -static inline uint32
16.156 -HashInt64(int64 key)
16.157 -{
16.158 - key = (~key) + (key << 18); // key = (key << 18) - key - 1;
16.159 - key = key ^ (uint64(key) >> 31);
16.160 - key = key * 21; // key = (key + (key << 2)) + (key << 4);
16.161 - key = key ^ (uint64(key) >> 11);
16.162 - key = key + (key << 6);
16.163 - key = key ^ (uint64(key) >> 22);
16.164 - return uint32(key);
16.165 -}
16.166 -
16.167 -static inline uint32
16.168 -HashPointer(void *p)
16.169 -{
16.170 -#if defined(KE_32BIT)
16.171 - return HashInt32(reinterpret_cast<int32>(p));
16.172 -#elif defined(KE_64BIT)
16.173 - return HashInt64(reinterpret_cast<int64>(p));
16.174 -#endif
16.175 -}
16.176 -
16.177 -static inline size_t
16.178 -Log2(size_t number)
16.179 -{
16.180 - assert(number != 0);
16.181 -
16.182 -#ifdef _MSC_VER
16.183 - unsigned long rval;
16.184 -# ifdef _M_IX86
16.185 - _BitScanReverse(&rval, number);
16.186 -# elif _M_X64
16.187 - _BitScanReverse64(&rval, number);
16.188 -# endif
16.189 - return rval;
16.190 -#else
16.191 - size_t bit;
16.192 - asm("bsr %1, %0\n"
16.193 - : "=r" (bit)
16.194 - : "rm" (number));
16.195 - return bit;
16.196 -#endif
16.197 -}
16.198 -
16.199 -static inline size_t
16.200 -FindRightmostBit(size_t number)
16.201 -{
16.202 - assert(number != 0);
16.203 -
16.204 -#ifdef _MSC_VER
16.205 - unsigned long rval;
16.206 -# ifdef _M_IX86
16.207 - _BitScanForward(&rval, number);
16.208 -# elif _M_X64
16.209 - _BitScanForward64(&rval, number);
16.210 -# endif
16.211 - return rval;
16.212 -#else
16.213 - size_t bit;
16.214 - asm("bsf %1, %0\n"
16.215 - : "=r" (bit)
16.216 - : "rm" (number));
16.217 - return bit;
16.218 -#endif
16.219 -}
16.220 -
16.221 -static inline bool
16.222 -IsPowerOfTwo(size_t value)
16.223 -{
16.224 - if (value == 0)
16.225 - return false;
16.226 - return !(value & (value - 1));
16.227 -}
16.228 -
16.229 -static inline size_t
16.230 -Align(size_t count, size_t alignment)
16.231 -{
16.232 - assert(IsPowerOfTwo(alignment));
16.233 - return count + (alignment - (count % alignment)) % alignment;
16.234 -}
16.235 -
16.236 -static inline bool
16.237 -IsUint32AddSafe(unsigned a, unsigned b)
16.238 -{
16.239 - if (!a || !b)
16.240 - return true;
16.241 - size_t log2_a = Log2(a);
16.242 - size_t log2_b = Log2(b);
16.243 - return (log2_a < sizeof(unsigned) * 8) &&
16.244 - (log2_b < sizeof(unsigned) * 8);
16.245 -}
16.246 -
16.247 -static inline bool
16.248 -IsUintPtrAddSafe(size_t a, size_t b)
16.249 -{
16.250 - if (!a || !b)
16.251 - return true;
16.252 - size_t log2_a = Log2(a);
16.253 - size_t log2_b = Log2(b);
16.254 - return (log2_a < sizeof(size_t) * 8) &&
16.255 - (log2_b < sizeof(size_t) * 8);
16.256 -}
16.257 -
16.258 -static inline bool
16.259 -IsUint32MultiplySafe(unsigned a, unsigned b)
16.260 -{
16.261 - if (a <= 1 || b <= 1)
16.262 - return true;
16.263 -
16.264 - size_t log2_a = Log2(a);
16.265 - size_t log2_b = Log2(b);
16.266 - return log2_a + log2_b <= sizeof(unsigned) * 8;
16.267 -}
16.268 -
16.269 -static inline bool
16.270 -IsUintPtrMultiplySafe(size_t a, size_t b)
16.271 -{
16.272 - if (a <= 1 || b <= 1)
16.273 - return true;
16.274 -
16.275 - size_t log2_a = Log2(a);
16.276 - size_t log2_b = Log2(b);
16.277 - return log2_a + log2_b <= sizeof(size_t) * 8;
16.278 -}
16.279 -
16.280 -#define ARRAY_LENGTH(array) (sizeof(array) / sizeof(array[0]))
16.281 -#define STATIC_ASSERT(cond) extern int static_assert_f(int a[(cond) ? 1 : -1])
16.282 -
16.283 -#define IS_ALIGNED(addr, alignment) (!(uintptr_t(addr) & ((alignment) - 1)))
16.284 -
16.285 -template <typename T>
16.286 -static inline bool
16.287 -IsAligned(T addr, size_t alignment)
16.288 -{
16.289 - assert(IsPowerOfTwo(alignment));
16.290 - return !(uintptr_t(addr) & (alignment - 1));
16.291 -}
16.292 -
16.293 -static inline Address
16.294 -AlignedBase(Address addr, size_t alignment)
16.295 -{
16.296 - assert(IsPowerOfTwo(alignment));
16.297 - return Address(uintptr_t(addr) & ~(alignment - 1));
16.298 -}
16.299 -
16.300 -template <typename T> static inline T
16.301 -Min(const T &t1, const T &t2)
16.302 -{
16.303 - return t1 < t2 ? t1 : t2;
16.304 -}
16.305 -
16.306 -template <typename T> static inline T
16.307 -Max(const T &t1, const T &t2)
16.308 -{
16.309 - return t1 > t2 ? t1 : t2;
16.310 -}
16.311 -
16.312 -#define OFFSETOF(Class, Member) reinterpret_cast<size_t>(&((Class *)NULL)->Member)
16.313 -
16.314 -#if defined(_MSC_VER)
16.315 -# define KE_SIZET_FMT "%Iu"
16.316 -#elif defined(__GNUC__)
16.317 -# define KE_SIZET_FMT "%zu"
16.318 -#else
16.319 -# error "Implement format specifier string"
16.320 -#endif
16.321 -
16.322 -#if defined(__GNUC__)
16.323 -# define KE_CRITICAL_LIKELY(x) __builtin_expect(!!(x), 1)
16.324 -#else
16.325 -# define KE_CRITICAL_LIKELY(x) x
16.326 -#endif
16.327 -
16.328 -}
16.329 -
16.330 -#endif // _include_jitcraft_utility_h_
17.1 --- a/public/sourcepawn/ke_vector.h Thu Aug 22 14:05:44 2013 -0700
17.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
17.3 @@ -1,166 +0,0 @@
17.4 -/* vim: set ts=2 sw=2 tw=99 et:
17.5 - *
17.6 - * Copyright (C) 2012 David Anderson
17.7 - *
17.8 - * This file is part of SourcePawn.
17.9 - *
17.10 - * SourcePawn is free software: you can redistribute it and/or modify it under
17.11 - * the terms of the GNU General Public License as published by the Free
17.12 - * Software Foundation, either version 3 of the License, or (at your option)
17.13 - * any later version.
17.14 - *
17.15 - * SourcePawn is distributed in the hope that it will be useful, but WITHOUT ANY
17.16 - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17.17 - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
17.18 - *
17.19 - * You should have received a copy of the GNU General Public License along with
17.20 - * SourcePawn. If not, see http://www.gnu.org/licenses/.
17.21 - */
17.22 -#ifndef _INCLUDE_KEIMA_TPL_CPP_VECTOR_H_
17.23 -#define _INCLUDE_KEIMA_TPL_CPP_VECTOR_H_
17.24 -
17.25 -#include <new>
17.26 -#include <stdlib.h>
17.27 -#include <ke_allocator_policies.h>
17.28 -#include <ke_utility.h>
17.29 -
17.30 -namespace ke {
17.31 -
17.32 -template <typename T, typename AllocPolicy = SystemAllocatorPolicy>
17.33 -class Vector : public AllocPolicy
17.34 -{
17.35 - public:
17.36 - Vector(AllocPolicy = AllocPolicy())
17.37 - : data(NULL),
17.38 - nitems(0),
17.39 - maxsize(0)
17.40 - {
17.41 - }
17.42 -
17.43 - ~Vector()
17.44 - {
17.45 - zap();
17.46 - }
17.47 -
17.48 - void steal(Vector &other) {
17.49 - zap();
17.50 - data = other.data;
17.51 - nitems = other.nitems;
17.52 - maxsize = other.maxsize;
17.53 - other.reset();
17.54 - }
17.55 -
17.56 - bool append(const T& item) {
17.57 - if (!growIfNeeded(1))
17.58 - return false;
17.59 - new (&data[nitems]) T(item);
17.60 - nitems++;
17.61 - return true;
17.62 - }
17.63 - void infallibleAppend(const T &item) {
17.64 - assert(growIfNeeded(1));
17.65 - new (&data[nitems]) T(item);
17.66 - nitems++;
17.67 - }
17.68 - T popCopy() {
17.69 - T t = at(length() - 1);
17.70 - pop();
17.71 - return t;
17.72 - }
17.73 - void pop() {
17.74 - assert(nitems);
17.75 - data[nitems - 1].~T();
17.76 - nitems--;
17.77 - }
17.78 - bool empty() const {
17.79 - return length() == 0;
17.80 - }
17.81 - size_t length() const {
17.82 - return nitems;
17.83 - }
17.84 - T& at(size_t i) {
17.85 - assert(i < length());
17.86 - return data[i];
17.87 - }
17.88 - const T& at(size_t i) const {
17.89 - assert(i < length());
17.90 - return data[i];
17.91 - }
17.92 - T& operator [](size_t i) {
17.93 - return at(i);
17.94 - }
17.95 - const T& operator [](size_t i) const {
17.96 - return at(i);
17.97 - }
17.98 - void clear() {
17.99 - nitems = 0;
17.100 - }
17.101 - const T &back() const {
17.102 - return at(length() - 1);
17.103 - }
17.104 - T &back() {
17.105 - return at(length() - 1);
17.106 - }
17.107 -
17.108 - T *buffer() const {
17.109 - return data;
17.110 - }
17.111 -
17.112 - bool ensure(size_t desired) {
17.113 - if (desired <= length())
17.114 - return true;
17.115 -
17.116 - return growIfNeeded(desired - length());
17.117 - }
17.118 -
17.119 - private:
17.120 - void zap() {
17.121 - for (size_t i = 0; i < nitems; i++)
17.122 - data[i].~T();
17.123 - this->free(data);
17.124 - }
17.125 - void reset() {
17.126 - data = NULL;
17.127 - nitems = 0;
17.128 - maxsize = 0;
17.129 - }
17.130 -
17.131 - bool growIfNeeded(size_t needed)
17.132 - {
17.133 - if (!IsUintPtrAddSafe(nitems, needed)) {
17.134 - this->reportAllocationOverflow();
17.135 - return false;
17.136 - }
17.137 - if (nitems + needed < maxsize)
17.138 - return true;
17.139 - if (maxsize == 0)
17.140 - maxsize = 8;
17.141 - while (nitems + needed > maxsize) {
17.142 - if (!IsUintPtrMultiplySafe(maxsize, 2)) {
17.143 - this->reportAllocationOverflow();
17.144 - return false;
17.145 - }
17.146 - maxsize *= 2;
17.147 - }
17.148 - T* newdata = (T*)this->malloc(sizeof(T) * maxsize);
17.149 - if (newdata == NULL)
17.150 - return false;
17.151 - for (size_t i = 0; i < nitems; i++) {
17.152 - new (&newdata[i]) T(data[i]);
17.153 - data[i].~T();
17.154 - }
17.155 - this->free(data);
17.156 - data = newdata;
17.157 - return true;
17.158 - }
17.159 -
17.160 - private:
17.161 - T* data;
17.162 - size_t nitems;
17.163 - size_t maxsize;
17.164 -};
17.165 -
17.166 -}
17.167 -
17.168 -#endif /* _INCLUDE_KEIMA_TPL_CPP_VECTOR_H_ */
17.169 -
18.1 --- a/sourcepawn/jit/AMBuilder Thu Aug 22 14:05:44 2013 -0700
18.2 +++ b/sourcepawn/jit/AMBuilder Thu Aug 22 16:30:44 2013 -0700
18.3 @@ -8,6 +8,7 @@
18.4 compiler['CXXINCLUDES'].append(os.path.join(base, 'sourcepawn', 'jit', 'x86'))
18.5 compiler['CXXINCLUDES'].append(os.path.join(base, 'public'))
18.6 compiler['CXXINCLUDES'].append(os.path.join(base, 'public', 'sourcepawn'))
18.7 +compiler['CXXINCLUDES'].append(os.path.join(base, 'public', 'amtl'))
18.8 compiler['CXXINCLUDES'].append(os.path.join(base, 'public', 'jit'))
18.9 compiler['CXXINCLUDES'].append(os.path.join(base, 'public', 'jit', 'x86'))
18.10 compiler['CXXINCLUDES'].append(os.path.join(base, 'knight', 'shared'))