/* Copyright 2003-2005 ROBLOX Corporation, All Rights Reserved */ #pragma once #include // defines std::min and std::max before Windows.h takes over #include "boost/config/user.hpp" #ifndef ROBLOX_BOOST_CONFIGS #error // Please re-get the full boost directory #endif #include "boost/shared_ptr.hpp" #include "boost/bind.hpp" #include #include // for placement_any #include #include #include #include #include using boost::shared_ptr; using boost::scoped_ptr; using boost::weak_ptr; #ifdef _WIN32 //#include #else #include "RbxFormat.h" #include // This is a hack. Truncates a pointer. #define GetCurrentThreadId() (static_cast(reinterpret_cast(pthread_self()))) #define SwitchToThread() {sched_yield();} // We may decide to use the following instead on Mac, but we would prefer the above. //#define SwitchToThread() {struct timespec req = {0, 1}; nanosleep(&req, NULL);} #endif namespace RBX { // TODO: Does boost have a nicer way of doing this? template void del_fun(T* t) { delete t; } bool isFinite(double value); bool isFinite(int value); } namespace rbx { namespace implementation { class type_holder : boost::noncopyable { public: // operations void (*destruct)(char* dest); void (*construct)(const char* src, char* dest); }; template class typed_holder : public type_holder { typed_holder() { construct = &construct_func; destruct = &destruct_func; } public: static const typed_holder* singleton() { static typed_holder s; return &s; } static void construct_func(const char* src, char* dest) { const ValueType* value = reinterpret_cast(src); ValueType* v = reinterpret_cast(dest); new (v) ValueType(*value); } static void destruct_func(char* dest) { ValueType* value = reinterpret_cast(dest); value->~ValueType(); } }; } // placement_any is a reworking of boost::any that embeds the value inside of // itself, rather than in the heap. This eliminates new/delete operations. However, // you must know in advance how big the values are able to be. Also, placement_any // allocates enough memory for the largest possible object, even when it is void. // SizeType must be a class that is as large as the largest sized object that // will be placed inside placement_any template class placement_any { public: // structors placement_any() : holder(0) { } placement_any(const placement_any& other) : holder(0) { if (other.holder) (*other.holder->construct)(other.data, data); holder = other.holder; // construct didn't throw, so we can assign the holder now } template explicit placement_any(const ValueType& value) : holder(0) { // If this fails, then make ValueType the new SizeType! BOOST_STATIC_ASSERT((sizeof(ValueType) <= sizeof(SizeType))); ValueType* v = reinterpret_cast(data); new (v) ValueType(value); holder = implementation::typed_holder::singleton(); // construct didn't throw, so we can assign it now } ~placement_any() { if (holder) (*holder->destruct)(data); } public: // modifiers placement_any& swap(placement_any& rhs) { placement_any temp(*this); *this = rhs; rhs = temp; return *this; } template placement_any& operator=(const ValueType& rhs) { const implementation::typed_holder* s = implementation::typed_holder::singleton(); if (holder == s) { // Optimization. Is this worth it? ValueType* dest = reinterpret_cast(data); *dest = rhs; } else { if (holder) { (*holder->destruct)(data); holder = 0; } // If this fails, then make ValueType the new SizeType! BOOST_STATIC_ASSERT((sizeof(ValueType) <= sizeof(SizeType))); ValueType* v = reinterpret_cast(data); new (v) ValueType(rhs); holder = s; } return *this; } placement_any& operator=(const placement_any& rhs) { if (&rhs == this) return *this; if (holder) { (*holder->destruct)(data); holder = 0; } if (rhs.holder) { (*rhs.holder->construct)(rhs.data, data); holder = rhs.holder; } return *this; } public: // queries bool empty() const { return holder == 0; } const char* getData() const { return holder ? data : NULL; } char* getData() { return holder ? data : NULL; } private: // representation const implementation::type_holder* holder; char data[sizeof(SizeType)]; }; }