summaryrefslogtreecommitdiffstats
path: root/Common/include
diff options
context:
space:
mode:
authorEgor Yusov <egor.yusov@gmail.com>2015-10-21 03:46:28 +0000
committerEgor Yusov <egor.yusov@gmail.com>2015-10-21 03:46:28 +0000
commit9ccee73baca0fd7ecb95c90cb983133b737c6c55 (patch)
tree66fea1e6521df31727431520fe3c1ead1896bc5d /Common/include
downloadDiligentCore-9ccee73baca0fd7ecb95c90cb983133b737c6c55.tar.gz
DiligentCore-9ccee73baca0fd7ecb95c90cb983133b737c6c55.zip
Release v1.0.0
Diffstat (limited to 'Common/include')
-rw-r--r--Common/include/BasicFileStream.h66
-rw-r--r--Common/include/BasicTypes.h52
-rw-r--r--Common/include/DataBlobImpl.h58
-rw-r--r--Common/include/DebugUtilities.h66
-rw-r--r--Common/include/Errors.h67
-rw-r--r--Common/include/FileWrapper.h91
-rw-r--r--Common/include/FormatMessage.h44
-rw-r--r--Common/include/HashUtils.h195
-rw-r--r--Common/include/InterfaceID.h50
-rw-r--r--Common/include/LockHelper.h133
-rw-r--r--Common/include/ObjectBase.h83
-rw-r--r--Common/include/RefCntAutoPtr.h391
-rw-r--r--Common/include/RefCountedObjectImpl.h332
-rw-r--r--Common/include/StringTools.h75
-rw-r--r--Common/include/Timer.h41
-rw-r--r--Common/include/UniqueIdentifier.h79
-rw-r--r--Common/include/ValidatedCast.h33
-rw-r--r--Common/include/pch.h35
18 files changed, 1891 insertions, 0 deletions
diff --git a/Common/include/BasicFileStream.h b/Common/include/BasicFileStream.h
new file mode 100644
index 00000000..85f685a5
--- /dev/null
+++ b/Common/include/BasicFileStream.h
@@ -0,0 +1,66 @@
+/* Copyright 2015 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#pragma once
+
+/// \file
+/// Implementation of the Diligent::BasicFileStream class
+
+#include "FileStream.h"
+#include "ObjectBase.h"
+#include "RefCountedObjectImpl.h"
+#include "FileWrapper.h"
+#include "DataBlob.h"
+
+namespace Diligent
+{
+
+/// Basic file stream implementation
+class BasicFileStream : public ObjectBase<IFileStream>
+{
+public:
+ typedef ObjectBase<IFileStream> TBase;
+
+ BasicFileStream(const Diligent::Char *Path,
+ EFileAccessMode Access = EFileAccessMode::Read);
+
+ virtual void QueryInterface( const Diligent::INTERFACE_ID &IID, IObject **ppInterface )override;
+
+ /// Reads data from the stream
+ virtual void Read( Diligent::IDataBlob *pData )override;
+
+ /// Reads data from the stream
+ virtual bool Read( void *Data, size_t BufferSize )override;
+
+ /// Writes data to the stream
+ virtual bool Write( const void *Data, size_t Size )override;
+
+ virtual size_t GetSize()override;
+
+ virtual bool IsValid()override;
+
+private:
+ Diligent::FileWrapper m_FileWrpr;
+};
+
+}
diff --git a/Common/include/BasicTypes.h b/Common/include/BasicTypes.h
new file mode 100644
index 00000000..7d3bea3d
--- /dev/null
+++ b/Common/include/BasicTypes.h
@@ -0,0 +1,52 @@
+/* Copyright 2015 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#pragma once
+
+#include <cstdint>
+#include <string>
+
+namespace Diligent
+{
+ typedef float Float32;
+
+ typedef int64_t Int64;
+ typedef int32_t Int32;
+ typedef int16_t Int16;
+ typedef int8_t Int8;
+
+ typedef uint64_t Uint64;
+ typedef uint32_t Uint32;
+ typedef uint16_t Uint16;
+ typedef uint8_t Uint8;
+
+ typedef size_t SizeType;
+ typedef void* PVoid;
+
+ typedef bool Bool;
+ static const Bool False = false;
+ static const Bool True = true;
+
+ typedef char Char;
+ typedef std::basic_string<Char> String;
+}
diff --git a/Common/include/DataBlobImpl.h b/Common/include/DataBlobImpl.h
new file mode 100644
index 00000000..d9441588
--- /dev/null
+++ b/Common/include/DataBlobImpl.h
@@ -0,0 +1,58 @@
+/* Copyright 2015 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#pragma once
+
+/// \file
+/// Implementation for the IDataBlob interface
+
+#include "DataBlob.h"
+#include "BasicTypes.h"
+#include "ObjectBase.h"
+#include <vector>
+
+namespace Diligent
+{
+
+/// Base interface for a file stream
+class DataBlobImpl : public Diligent::ObjectBase<IDataBlob>
+{
+public:
+ typedef Diligent::ObjectBase<IDataBlob> TBase;
+
+ virtual void QueryInterface( const Diligent::INTERFACE_ID &IID, IObject **ppInterface )override;
+
+ /// Sets the size of the internal data buffer
+ virtual void Resize( size_t NewSize )override;
+
+ /// Returns the size of the internal data buffer
+ virtual size_t GetSize()override;
+
+ /// Returns the pointer to the internal data buffer
+ virtual void* GetDataPtr()override;
+
+private:
+ std::vector<Diligent::Uint8> m_DataBuff;
+};
+
+}
diff --git a/Common/include/DebugUtilities.h b/Common/include/DebugUtilities.h
new file mode 100644
index 00000000..d57fd06b
--- /dev/null
+++ b/Common/include/DebugUtilities.h
@@ -0,0 +1,66 @@
+/* Copyright 2015 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#pragma once
+
+#include "FormatMessage.h"
+#include "PlatformDebug.h"
+
+#ifdef _DEBUG
+
+// This function is only requried to ensure that Message argument passed to the macro
+// is actually string and not something else
+inline void EnsureStr( const char* ){}
+# define VERIFY(Expr, Message, ...)\
+ { \
+ if( !(Expr) ) \
+ { \
+ Diligent::MsgStream ms; \
+ Diligent::FormatMsg( ms, Message, ##__VA_ARGS__);\
+ PlatformDebug::AssertionFailed( ms.str().c_str(), __FUNCTION__, __FILE__, __LINE__); \
+ } \
+ EnsureStr(Message); \
+ }
+# define UNEXPECTED(Message, ...) { VERIFY(false, Message, ##__VA_ARGS__); }
+# define UNSUPPORTED(Message, ...) { VERIFY(false, Message, ##__VA_ARGS__); }
+
+# define VERIFY_EXPR(Expr) VERIFY(Expr, "Debug exression failed:\n", #Expr)
+
+
+template<typename DstType, typename SrcType>
+void CheckDynamicType( SrcType *pSrcPtr )
+{
+ VERIFY( pSrcPtr == nullptr || dynamic_cast<DstType*> (pSrcPtr) != nullptr, "Dynamic type cast failed!" );
+}
+# define CHECK_DYNAMIC_TYPE(DstType, pSrcPtr) CheckDynamicType<DstType>(pSrcPtr)
+
+
+#else
+
+# define CHECK_DYNAMIC_TYPE(...){}
+# define VERIFY(...){}
+# define UNEXPECTED(...){}
+# define UNSUPPORTED(...){}
+# define VERIFY_EXPR(...){}
+
+#endif
diff --git a/Common/include/Errors.h b/Common/include/Errors.h
new file mode 100644
index 00000000..658adb0e
--- /dev/null
+++ b/Common/include/Errors.h
@@ -0,0 +1,67 @@
+/* Copyright 2015 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#pragma once
+
+#include <stdexcept>
+
+#include "PlatformDebug.h"
+#include "FormatMessage.h"
+#include "FileSystem.h"
+
+template<bool bThrowException, typename FirstArgType, typename... RestArgsType>
+void LogError( const char *strFunctionName, const char *strFullFilePath, int Line, const FirstArgType& first, const RestArgsType&... RestArgs )
+{
+ std::string FileName;
+ FileSystem::SplitFilePath( strFullFilePath, nullptr, &FileName );
+ Diligent::MsgStream ss;
+ ss << "The following error occured in the " << strFunctionName << "() function (" << FileName << ", line " << Line << "):\n";
+ Diligent::FormatMsg( ss, first, RestArgs... );
+ auto strFullMessage = ss.str();
+ PlatformDebug::OutputDebugMessage( bThrowException ? PlatformDebug::DebugMessageSeverity::FatalError : PlatformDebug::DebugMessageSeverity::Error, strFullMessage.c_str() );
+ if( bThrowException )
+ {
+ throw std::runtime_error( strFullMessage );
+ }
+}
+
+#define LOG_ERROR(...)\
+{ \
+ LogError<false>(__FUNCTION__, __FILE__, __LINE__, ##__VA_ARGS__); \
+}
+
+#define LOG_ERROR_AND_THROW(...) \
+{ \
+ LogError<true>(__FUNCTION__, __FILE__, __LINE__, ##__VA_ARGS__); \
+}
+
+#define LOG_DEBUG_MESSAGE(Severity, ...) \
+{ \
+ Diligent::MsgStream ss; \
+ Diligent::FormatMsg( ss, ##__VA_ARGS__ ); \
+ PlatformDebug::OutputDebugMessage( Severity, ss.str().c_str() ); \
+}
+
+#define LOG_ERROR_MESSAGE(...) LOG_DEBUG_MESSAGE(PlatformDebug::DebugMessageSeverity::Error, ##__VA_ARGS__)
+#define LOG_WARNING_MESSAGE(...) LOG_DEBUG_MESSAGE(PlatformDebug::DebugMessageSeverity::Warning, ##__VA_ARGS__)
+#define LOG_INFO_MESSAGE(...) LOG_DEBUG_MESSAGE(PlatformDebug::DebugMessageSeverity::Info, ##__VA_ARGS__)
diff --git a/Common/include/FileWrapper.h b/Common/include/FileWrapper.h
new file mode 100644
index 00000000..85851d89
--- /dev/null
+++ b/Common/include/FileWrapper.h
@@ -0,0 +1,91 @@
+/* Copyright 2015 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#pragma once
+
+#include "FileSystem.h"
+#include "Errors.h"
+#include "DebugUtilities.h"
+
+namespace Diligent
+{
+
+class FileWrapper
+{
+public:
+ FileWrapper( ) :
+ m_pFile(nullptr)
+ {}
+
+ FileWrapper( const Diligent::Char *Path,
+ EFileAccessMode Access = EFileAccessMode::Read) :
+ m_pFile( nullptr )
+ {
+ FileOpenAttribs OpenAttribs(Path, Access);
+ Open(OpenAttribs);
+ }
+
+ ~FileWrapper()
+ {
+ Close();
+ }
+
+ void Open(const FileOpenAttribs& OpenAttribs)
+ {
+ VERIFY( !m_pFile, "Another file already attached" );
+ Close();
+ m_pFile = FileSystem::OpenFile( OpenAttribs );
+ }
+
+ CFile *Detach()
+ {
+ CFile *pFile = m_pFile;
+ m_pFile = NULL;
+ return pFile;
+ }
+
+ void Attach(CFile *pFile)
+ {
+ VERIFY(!m_pFile, "Another file already attached");
+ Close();
+ m_pFile = pFile;
+ }
+
+ void Close()
+ {
+ if( m_pFile )
+ FileSystem::ReleaseFile(m_pFile);
+ m_pFile = nullptr;
+ }
+
+ operator CFile*(){return m_pFile;}
+ CFile* operator->(){return m_pFile;}
+
+private:
+ FileWrapper(const FileWrapper&);
+ const FileWrapper& operator=(const FileWrapper&);
+
+ CFile *m_pFile;
+};
+
+}
diff --git a/Common/include/FormatMessage.h b/Common/include/FormatMessage.h
new file mode 100644
index 00000000..a20435ae
--- /dev/null
+++ b/Common/include/FormatMessage.h
@@ -0,0 +1,44 @@
+/* Copyright 2015 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#pragma once
+
+#include <sstream>
+
+namespace Diligent
+{
+ typedef std::stringstream MsgStream;
+
+ template<typename SSType, typename ArgType>
+ void FormatMsg( SSType &ss, const ArgType& Arg )
+ {
+ ss << Arg;
+ }
+
+ template<typename SSType, typename FirstArgType, typename... RestArgsType>
+ void FormatMsg( SSType &ss, const FirstArgType& FirstArg, const RestArgsType&... RestArgs )
+ {
+ FormatMsg( ss, FirstArg );
+ FormatMsg( ss, RestArgs... ); // recursive call using pack expansion syntax
+ }
+} \ No newline at end of file
diff --git a/Common/include/HashUtils.h b/Common/include/HashUtils.h
new file mode 100644
index 00000000..03cf54b6
--- /dev/null
+++ b/Common/include/HashUtils.h
@@ -0,0 +1,195 @@
+/* Copyright 2015 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#pragma once
+
+#include <functional>
+#include <memory>
+
+#define LOG_HASH_CONFLICTS 1
+
+namespace Diligent
+{
+ // http://www.boost.org/doc/libs/1_35_0/doc/html/hash/combine.html
+ template<typename T>
+ void HashCombine(std::size_t &Seed, const T& Val)
+ {
+ Seed ^= std::hash<T>()(Val) + 0x9e3779b9 + (Seed << 6) + (Seed >> 2);
+ }
+
+ template<typename FirstArgType, typename... RestArgsType>
+ void HashCombine( std::size_t &Seed, const FirstArgType& FirstArg, const RestArgsType&... RestArgs )
+ {
+ HashCombine( Seed, FirstArg );
+ HashCombine( Seed, RestArgs... ); // recursive call using pack expansion syntax
+ }
+
+ template<typename... ArgsType>
+ std::size_t ComputeHash( const ArgsType&... Args )
+ {
+ std::size_t Seed = 0;
+ HashCombine( Seed, Args... );
+ return Seed;
+ }
+
+ template<typename CharType>
+ struct CStringHash
+ {
+ size_t operator()( const CharType *str ) const
+ {
+ // http://www.cse.yorku.ca/~oz/hash.html
+ std::size_t Seed = 0;
+ while( size_t Ch = *(str++) )
+ Seed = Seed * 65599 + Ch;
+ return Seed;
+ }
+ };
+
+ template<typename CharType>
+ struct CStringCompare
+ {
+ bool operator()( const Char *str1, const Char *str2 )const
+ {
+ UNSUPPORTED( "Template specialization is not implemented" )
+ return false;
+ }
+ };
+
+ template<>
+ struct CStringCompare<Char>
+ {
+ bool operator()( const Char *str1, const Char *str2 )const
+ {
+ return strcmp( str1, str2 ) == 0;
+ }
+ };
+
+ /// This helper structure is intended to facilitate using strings as a
+ /// hash table key. It provides constructors that can make a copy of the
+ /// source string or just keep pointer to it, which enables searching in
+ /// the hash using raw const Char* pointers.
+ struct HashMapStringKey
+ {
+ public:
+ // This constructor can perform implicit const Char* -> HashMapStringKey
+ // conversion without copying the string
+ HashMapStringKey(const Char* Str, bool bMakeCopy = false) :
+ StrPtr(nullptr),
+ Hash(0)
+ {
+ VERIFY( Str, "String pointer cannot be null" );
+ if( bMakeCopy )
+ {
+ MakeCopy( Str );
+ }
+ else
+ {
+ StrPtr = Str;
+ }
+ }
+
+ explicit // Make this constructor explicit to avoid unintentional string copies
+ HashMapStringKey(const String &Str) :
+ StrPtr( nullptr ),
+ Hash(0)
+ {
+ MakeCopy( Str.c_str() );
+ }
+
+ HashMapStringKey(HashMapStringKey &&Key) :
+ StringBuff( std::move(Key.StringBuff) ),
+ StrPtr( std::move(Key.StrPtr) ),
+ Hash(0)
+ {
+ Key.StrPtr = nullptr;
+ Key.Hash = 0;
+ }
+
+ // Disable copy constuctor and assignments. The struct is designed
+ // to be initialized at creation time only
+ HashMapStringKey( const HashMapStringKey& ) = delete;
+ HashMapStringKey& operator = ( const HashMapStringKey& ) = delete;
+ HashMapStringKey& operator = ( HashMapStringKey&& ) = delete;
+
+ // Comparison operator
+ bool operator == (const HashMapStringKey& RHS)const
+ {
+ if( StrPtr == RHS.StrPtr )
+ return true;
+
+ // Hash member might not have been initialized
+ if( (Hash != 0 && RHS.Hash !=0 && Hash != RHS.Hash) || StrPtr == nullptr || RHS.StrPtr == nullptr )
+ return false;
+
+ bool IsEqual = strcmp( StrPtr, RHS.StrPtr ) == 0;
+
+#if LOG_HASH_CONFLICTS
+ if( Hash != 0 && RHS.Hash !=0 && Hash == RHS.Hash && !IsEqual )
+ {
+ LOG_WARNING_MESSAGE("Unequal strings \"", StrPtr, "\" and \"", RHS.StrPtr, "\" hashed to the same bucket. "
+ "You may want to use better hash function. You may disable this warning by defining LOG_HASH_CONFLICTS to 0");
+ }
+#endif
+ return IsEqual;
+ }
+
+ size_t GetHash()const
+ {
+ if( Hash == 0 )
+ Hash = CStringHash<Char>()(StrPtr);
+
+ return Hash;
+ }
+
+ const Char* GetStr()const{ return StrPtr; }
+
+ private:
+ void MakeCopy( const Char* Str )
+ {
+ auto LenWithZeroTerm = strlen( Str ) + 1;
+ StringBuff.reset( new char[ LenWithZeroTerm ] );
+ memcpy( StringBuff.get(), Str, LenWithZeroTerm );
+ StrPtr = StringBuff.get();
+ }
+
+ // !!! WARNING !!!
+ // We can't use String to store the buffer, because String default
+ // constructor always allocates memory even when the string is empty,
+ // nor can we use vector for the same reason
+ std::unique_ptr< Char[] > StringBuff; // Must be declared first
+ const Char* StrPtr;// Must be declared after StringBuff
+ mutable size_t Hash;
+ };
+}
+
+namespace std
+{
+ template<>
+ struct hash<Diligent::HashMapStringKey>
+ {
+ size_t operator()( const Diligent::HashMapStringKey &Key ) const
+ {
+ return Key.GetHash();
+ }
+ };
+}
diff --git a/Common/include/InterfaceID.h b/Common/include/InterfaceID.h
new file mode 100644
index 00000000..ce426b5e
--- /dev/null
+++ b/Common/include/InterfaceID.h
@@ -0,0 +1,50 @@
+/* Copyright 2015 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#pragma once
+
+#include "BasicTypes.h"
+
+/// Unique identification structures
+namespace Diligent
+{
+ /// Describes unique identifier
+ struct INTERFACE_ID
+ {
+ Diligent::Uint32 Data1;
+ Diligent::Uint16 Data2;
+ Diligent::Uint16 Data3;
+ Diligent::Uint8 Data4[8];
+
+ bool operator == (const INTERFACE_ID& rhs)const
+ {
+ return Data1 == rhs.Data1 &&
+ Data2 == rhs.Data2 &&
+ Data3 == rhs.Data3 &&
+ memcmp(Data4, rhs.Data4, sizeof(Data4)) == 0;
+ }
+ };
+
+ /// Unknown interface
+ static const INTERFACE_ID IID_Unknown = { 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0 } };
+}
diff --git a/Common/include/LockHelper.h b/Common/include/LockHelper.h
new file mode 100644
index 00000000..5f27aad3
--- /dev/null
+++ b/Common/include/LockHelper.h
@@ -0,0 +1,133 @@
+/* Copyright 2015 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#pragma once
+
+#include "Atomics.h"
+
+namespace ThreadingTools
+{
+
+class LockFlag
+{
+public:
+ enum {LOCK_FLAG_UNLOCKED = 0, LOCK_FLAG_LOCKED = 1};
+ LockFlag(Atomics::Long InitFlag = LOCK_FLAG_UNLOCKED)
+ {
+ m_Flag.store(InitFlag);
+ }
+
+ operator Atomics::Long()const{return m_Flag;}
+
+private:
+ friend class LockHelper;
+ Atomics::AtomicLong m_Flag;
+};
+
+class LockHelper
+{
+public:
+
+ LockHelper() :
+ m_pLockFlag(nullptr)
+ {
+ }
+ LockHelper(LockFlag &LockFlag) :
+ m_pLockFlag(nullptr)
+ {
+ Lock(LockFlag);
+ }
+
+ LockHelper( LockHelper &&LockHelper ) :
+ m_pLockFlag( std::move(LockHelper.m_pLockFlag) )
+ {
+ LockHelper.m_pLockFlag = nullptr;
+ }
+
+ const LockHelper& operator = (LockHelper &&LockHelper)
+ {
+ m_pLockFlag = std::move( LockHelper.m_pLockFlag );
+ LockHelper.m_pLockFlag = nullptr;
+ return *this;
+ }
+
+ ~LockHelper()
+ {
+ Unlock();
+ }
+
+ static bool UnsafeTryLock(LockFlag &LockFlag)
+ {
+ return Atomics::AtomicCompareExchange( LockFlag.m_Flag,
+ static_cast<Atomics::Long>( LockFlag::LOCK_FLAG_LOCKED ),
+ static_cast<Atomics::Long>( LockFlag::LOCK_FLAG_UNLOCKED) ) == LockFlag::LOCK_FLAG_UNLOCKED;
+ }
+
+ bool TryLock(LockFlag &LockFlag)
+ {
+ if( UnsafeTryLock( LockFlag) )
+ {
+ m_pLockFlag = &LockFlag;
+ return true;
+ }
+ else
+ return false;
+ }
+
+ static void UnsafeLock(LockFlag &LockFlag)
+ {
+ while( !UnsafeTryLock( LockFlag ) )
+ /*Sleep(5)*/
+ // TODO
+ ;
+ }
+
+ void Lock(LockFlag &LockFlag)
+ {
+ VERIFY( m_pLockFlag == NULL, "Object already locked" );
+ // Wait for the flag to become unlocked and lock it
+ while( !TryLock( LockFlag ) )
+ /*Sleep(5)*/
+ // TODO
+ ;
+ }
+
+ static void UnsafeUnlock(LockFlag &LockFlag)
+ {
+ LockFlag.m_Flag = LockFlag::LOCK_FLAG_UNLOCKED;
+ }
+
+ void Unlock()
+ {
+ if( m_pLockFlag )
+ UnsafeUnlock(*m_pLockFlag);
+ m_pLockFlag = NULL;
+ }
+
+private:
+ LockFlag *m_pLockFlag;
+ LockHelper( const LockHelper &LockHelper );
+ const LockHelper& operator = ( const LockHelper &LockHelper );
+};
+
+}
diff --git a/Common/include/ObjectBase.h b/Common/include/ObjectBase.h
new file mode 100644
index 00000000..c7de28c8
--- /dev/null
+++ b/Common/include/ObjectBase.h
@@ -0,0 +1,83 @@
+/* Copyright 2015 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#pragma once
+
+/// \file
+/// Implementation of the Diligent::ObjectBase template class
+
+#include "Object.h"
+#include "RefCountedObjectImpl.h"
+
+namespace Diligent
+{
+
+
+#define IMPLEMENT_QUERY_INTERFACE_BODY(InterfaceID, ParentClassName) \
+{ \
+ if( ppInterface == nullptr ) \
+ return; \
+ if( IID == InterfaceID ) \
+ { \
+ *ppInterface = this; \
+ (*ppInterface)->AddRef(); \
+ } \
+ else \
+ { \
+ ParentClassName::QueryInterface( IID, ppInterface ); \
+ } \
+}
+
+#define IMPLEMENT_QUERY_INTERFACE(ClassName, InterfaceID, ParentClassName) \
+ void ClassName :: QueryInterface(const Diligent::INTERFACE_ID &IID, IObject **ppInterface) \
+ IMPLEMENT_QUERY_INTERFACE_BODY(InterfaceID, ParentClassName)
+
+#define IMPLEMENT_QUERY_INTERFACE_IN_PLACE(InterfaceID, ParentClassName) \
+ virtual void QueryInterface(const Diligent::INTERFACE_ID &IID, IObject **ppInterface) \
+ IMPLEMENT_QUERY_INTERFACE_BODY(InterfaceID, ParentClassName)
+
+
+/// Template class implementing base functionality for an object
+template<typename BaseInterface>
+class ObjectBase : public RefCountedObject<BaseInterface>
+{
+public:
+ ObjectBase(IObject *pOwner = nullptr) :
+ RefCountedObject<BaseInterface>( pOwner )
+ {}
+
+ virtual void QueryInterface( const Diligent::INTERFACE_ID &IID, IObject **ppInterface )
+ {
+ if( ppInterface == nullptr )
+ return;
+
+ *ppInterface = nullptr;
+ if( IID == Diligent::IID_Unknown )
+ {
+ *ppInterface = this;
+ (*ppInterface)->AddRef();
+ }
+ }
+};
+
+}
diff --git a/Common/include/RefCntAutoPtr.h b/Common/include/RefCntAutoPtr.h
new file mode 100644
index 00000000..7df6f246
--- /dev/null
+++ b/Common/include/RefCntAutoPtr.h
@@ -0,0 +1,391 @@
+/* Copyright 2015 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#pragma once
+
+#include "DebugUtilities.h"
+#include "LockHelper.h"
+#include "Atomics.h"
+#include "ValidatedCast.h"
+#include "ReferenceCounters.h"
+#include "Object.h"
+
+namespace Diligent
+{
+
+
+template <typename T>
+class RefCntWeakPtr;
+
+// The main advantage of RefCntAutoPtr over the std::shared_ptr is that you can
+// attach the same raw pointer to different smart pointers.
+//
+// For instance, the following code will crash since p will be released twice:
+//
+// auto *p = new char;
+// std::shared_ptr<char> pTmp1(p);
+// std::shared_ptr<char> pTmp2(p);
+// ...
+
+// This code, in contrast, works perfectly fine:
+//
+// ObjectBase *pRawPtr(new ObjectBase);
+// RefCntAutoPtr<ObjectBase> pSmartPtr1(pRawPtr);
+// RefCntAutoPtr<ObjectBase> pSmartPtr2(pRawPtr);
+// ...
+
+// Other advantage is that weak pointers remain valid until the
+// object is alive, even if all smart pointers were destroyed:
+//
+// RefCntWeakPtr<ObjectBase> pWeakPtr(pSmartPtr1);
+// pSmartPtr1.Release();
+// auto pSmartPtr3 = pWeakPtr.Lock();
+// ..
+
+// Weak pointers can also be attached directly to the object:
+// RefCntWeakPtr<ObjectBase> pWeakPtr(pRawPtr);
+//
+
+template<typename T>
+class DefaultBlockAddRefRelease : public T
+{
+private:
+ // Note that the null pointer constant nullptr or any other value of type std::nullptr_t
+ // cannot be converted to a pointer with reinterpret_cast: implicit conversion or
+ // static_cast should be used for this purpose.
+ virtual decltype( static_cast<T*>(nullptr)->AddRef() ) AddRef()override = 0;
+ virtual decltype( static_cast<T*>(nullptr)->Release() ) Release()override = 0;
+};
+
+template <typename T, template<typename> class BlockAddRefRelease = DefaultBlockAddRefRelease>
+class RefCntAutoPtr
+{
+public:
+ explicit RefCntAutoPtr(T *pObj = nullptr) :
+ m_pObject(pObj)
+ {
+ if( m_pObject )
+ m_pObject->AddRef();
+ }
+
+ RefCntAutoPtr(const RefCntAutoPtr &AutoPtr) :
+ m_pObject(AutoPtr.m_pObject)
+ {
+ if(m_pObject)
+ m_pObject->AddRef();
+ }
+
+ RefCntAutoPtr(RefCntAutoPtr &&AutoPtr) :
+ m_pObject(std::move(AutoPtr.m_pObject))
+ {
+ //Make sure original pointer has no references to the object
+ AutoPtr.m_pObject = nullptr;
+ }
+
+ ~RefCntAutoPtr()
+ {
+ Release();
+ }
+
+ void swap(RefCntAutoPtr &AutoPtr)
+ {
+ std::swap(m_pObject, AutoPtr.m_pObject);
+ }
+
+ void Attach(T *pObj)
+ {
+ Release();
+ m_pObject = pObj;
+ }
+
+ T* Detach()
+ {
+ T* pObj = m_pObject;
+ m_pObject = nullptr;
+ return pObj;
+ }
+
+ void Release()
+ {
+ if( m_pObject )
+ {
+ m_pObject->Release();
+ m_pObject = nullptr;
+ }
+ }
+
+ RefCntAutoPtr& operator = (T *pObj)
+ {
+ if( static_cast<T*>(*this) == pObj )
+ return *this;
+
+ return operator= (RefCntAutoPtr(pObj));
+ }
+
+ RefCntAutoPtr& operator = (const RefCntAutoPtr &AutoPtr)
+ {
+ if( *this == AutoPtr )
+ return *this;
+
+ Release();
+ m_pObject = AutoPtr.m_pObject;
+ if(m_pObject)
+ m_pObject->AddRef();
+
+ return *this;
+ }
+
+ RefCntAutoPtr& operator = (RefCntAutoPtr &&AutoPtr)
+ {
+ if( *this == AutoPtr )
+ return *this;
+
+ Release();
+ m_pObject = std::move( AutoPtr.m_pObject );
+ //Make sure original pointer has no references to the object
+ AutoPtr.m_pObject = nullptr;
+ return *this;
+ }
+
+ // All the access functions do not require locking reference counters pointer because if it is valid,
+ // the smart pointer holds strong reference to the object and it thus cannot be released by
+ // ohter thread
+ bool operator ! () const{return m_pObject == nullptr;}
+ operator bool () const{return m_pObject != nullptr;}
+ bool operator == (const RefCntAutoPtr& Ptr)const{return m_pObject == Ptr.m_pObject;}
+ bool operator != (const RefCntAutoPtr& Ptr)const{return m_pObject != Ptr.m_pObject;}
+ bool operator < (const RefCntAutoPtr& Ptr)const{return static_cast<const T*>(*this) < static_cast<const T*>(Ptr);}
+
+ T& operator * () { return *m_pObject; }
+ const T& operator * ()const { return *m_pObject; }
+
+ T* RawPtr() { return m_pObject; }
+ const T* RawPtr()const{ return m_pObject; }
+
+ operator T* () { return RawPtr(); }
+ operator const T* ()const { return RawPtr(); }
+
+
+ BlockAddRefRelease<T>* operator -> () { return static_cast<BlockAddRefRelease<T>*> (m_pObject); }
+ const BlockAddRefRelease<T>* operator -> ()const{ return static_cast<BlockAddRefRelease<T>*> (m_pObject); }
+
+private:
+ // Note that the DoublePtrHelper is a private class, and can be created only by RefCntWeakPtr
+ // Thus if no special effort is made, the lifetime of the instances of this class cannot be
+ // longer than the lifetime of the creating object
+ class DoublePtrHelper
+ {
+ public:
+ DoublePtrHelper(RefCntAutoPtr &AutoPtr) :
+ NewRawPtr( static_cast<T*>(AutoPtr) ),
+ m_pAutoPtr( std::addressof(AutoPtr) )
+ {
+ }
+
+ DoublePtrHelper(DoublePtrHelper&& Helper) :
+ NewRawPtr(Helper.NewRawPtr),
+ m_pAutoPtr(Helper.m_pAutoPtr)
+ {
+ Helper.m_pAutoPtr = nullptr;
+ Helper.NewRawPtr = nullptr;
+ }
+
+ ~DoublePtrHelper()
+ {
+ if( m_pAutoPtr && static_cast<T*>(*m_pAutoPtr) != NewRawPtr )
+ {
+ m_pAutoPtr->Attach(NewRawPtr);
+ }
+ }
+
+ T*& operator*(){return NewRawPtr;}
+ const T* operator*()const{return NewRawPtr;}
+
+ operator T**(){return &NewRawPtr;}
+ operator const T**()const{return &NewRawPtr;}
+ private:
+ T *NewRawPtr;
+ RefCntAutoPtr *m_pAutoPtr;
+ DoublePtrHelper(const DoublePtrHelper&);
+ DoublePtrHelper& operator = (const DoublePtrHelper&);
+ DoublePtrHelper& operator = (DoublePtrHelper&&);
+ };
+
+public:
+ DoublePtrHelper operator& ()
+ {
+ return DoublePtrHelper(*this);
+ }
+
+ const DoublePtrHelper operator& ()const
+ {
+ return DoublePtrHelper(*this);
+ }
+
+private:
+ T *m_pObject;
+};
+
+/// Implementation of weak pointers
+template <typename T>
+class RefCntWeakPtr
+{
+public:
+ explicit RefCntWeakPtr(T *pObj = nullptr) :
+ m_pObject(pObj),
+ m_pRefCounters(nullptr)
+ {
+ if( m_pObject )
+ {
+ m_pRefCounters = m_pObject->GetReferenceCounters();
+ m_pRefCounters->AddWeakRef();
+ }
+ }
+
+ ~RefCntWeakPtr()
+ {
+ Release();
+ }
+
+ RefCntWeakPtr(const RefCntWeakPtr& WeakPtr) :
+ m_pObject(WeakPtr.m_pObject),
+ m_pRefCounters(WeakPtr.m_pRefCounters)
+ {
+ if( m_pRefCounters )
+ m_pRefCounters->AddWeakRef();
+ }
+
+ RefCntWeakPtr(RefCntWeakPtr&& WeakPtr) :
+ m_pObject(std::move(WeakPtr.m_pObject)),
+ m_pRefCounters(std::move(WeakPtr.m_pRefCounters))
+ {
+ WeakPtr.m_pRefCounters = nullptr;
+ WeakPtr.m_pObject = nullptr;
+ }
+
+ explicit RefCntWeakPtr(RefCntAutoPtr<T>& AutoPtr) :
+ m_pObject( static_cast<T*>(AutoPtr) ),
+ m_pRefCounters(AutoPtr ? AutoPtr->GetReferenceCounters() : nullptr)
+ {
+ if( m_pRefCounters )
+ m_pRefCounters->AddWeakRef();
+ }
+
+ RefCntWeakPtr& operator = (const RefCntWeakPtr& WeakPtr)
+ {
+ if( *this == WeakPtr )
+ return *this;
+
+ Release();
+ m_pObject = WeakPtr.m_pObject;
+ m_pRefCounters = WeakPtr.m_pRefCounters;
+ if( m_pRefCounters )
+ m_pRefCounters->AddWeakRef();
+ return *this;
+ }
+
+ RefCntWeakPtr& operator = (T *pObj)
+ {
+ return operator= (RefCntWeakPtr(pObj));
+ }
+
+ RefCntWeakPtr& operator = (RefCntWeakPtr&& WeakPtr)
+ {
+ if( *this == WeakPtr )
+ return *this;
+
+ Release();
+ m_pObject = std::move(WeakPtr.m_pObject);
+ m_pRefCounters = std::move(WeakPtr.m_pRefCounters);
+ WeakPtr.m_pRefCounters = nullptr;
+ WeakPtr.m_pObject = nullptr;
+ return *this;
+ }
+
+ RefCntWeakPtr& operator = (RefCntAutoPtr<T>& AutoPtr)
+ {
+ Release();
+ m_pObject = static_cast<T*>( AutoPtr );
+ m_pRefCounters = m_pObject ? m_pObject->GetReferenceCounters() : nullptr;
+ if( m_pRefCounters )
+ m_pRefCounters->AddWeakRef();
+ return *this;
+ }
+
+ void Release()
+ {
+ if( m_pRefCounters )
+ m_pRefCounters->ReleaseWeakRef();
+ m_pRefCounters = nullptr;
+ m_pObject = nullptr;
+ }
+
+ /// \note This method may not be reliable in a multithreaded environment.
+ /// However, when false is returned, the strong pointer created from
+ /// this weak pointer will reliably be empty.
+ bool IsValid()
+ {
+ return m_pObject != nullptr && m_pRefCounters != nullptr && m_pRefCounters->GetNumStrongRefs() > 0;
+ }
+
+ /// Obtains a strong reference to the object
+ RefCntAutoPtr<T> Lock()
+ {
+ RefCntAutoPtr<T> spObj;
+ if( m_pRefCounters )
+ {
+ // Try to obtain pointer to the owner object.
+ // spOwner is only used to keep the object
+ // alive while obtaining strong reference from
+ // the raw pointer m_pObject
+ RefCntAutoPtr<Diligent::IObject> spOwner;
+ m_pRefCounters->GetObject( &spOwner );
+ if( spOwner )
+ {
+ // If owner is alive, we can use our RAW pointer to
+ // create strong reference
+ spObj = m_pObject;
+ }
+ else
+ {
+ // Owner object has been destroyed. There is no reason
+ // to keep this weak reference anymore
+ Release();
+ }
+ }
+ return spObj;
+ }
+
+ bool operator == (const RefCntWeakPtr& Ptr)const{return m_pRefCounters == Ptr.m_pRefCounters;}
+ bool operator != (const RefCntWeakPtr& Ptr)const{return m_pRefCounters != Ptr.m_pRefCounters;}
+
+protected:
+ Diligent::IReferenceCounters *m_pRefCounters;
+ // We need to store raw pointer to object itself,
+ // because if the object is owned by another object,
+ // m_pRefCounters->GetObject( &pObj ) will return
+ // pointer to owner, which is not what we need.
+ T *m_pObject;
+};
+
+}
diff --git a/Common/include/RefCountedObjectImpl.h b/Common/include/RefCountedObjectImpl.h
new file mode 100644
index 00000000..dc5f7233
--- /dev/null
+++ b/Common/include/RefCountedObjectImpl.h
@@ -0,0 +1,332 @@
+/* Copyright 2015 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#pragma once
+
+/// \file
+/// Implementation of the template base class for reference counting objects
+
+#include "Object.h"
+#include "Atomics.h"
+#include "DebugUtilities.h"
+#include "LockHelper.h"
+#include "ValidatedCast.h"
+
+namespace Diligent
+{
+
+/// Base class for reference counting objects
+template<typename Base>
+class RefCountedObject : public Base
+{
+public:
+ RefCountedObject(IObject *pOwner = nullptr) :
+ m_pRefCounters(nullptr)
+ {
+ if( pOwner )
+ {
+ auto *pRefCounters = pOwner->GetReferenceCounters();
+ VERIFY(pRefCounters, "Reference counters are not initialized in the owner object");
+ m_pRefCounters = ValidatedCast<IReferenceCounters>( pRefCounters );
+ }
+ else
+ {
+ m_pRefCounters = RefCountersImpl::Create(this);
+ }
+ };
+
+ virtual ~RefCountedObject()
+ {
+ // WARNING! m_pRefCounters pointer might be expired in scenarios like this:
+ //
+ // A ==sp==> B ---wp---> A
+ //
+ // RefCounters_A.ReleaseStrongRef(){ // NumStrongRef == 0, NumWeakRef == 1
+ // delete A{
+ // A.~dtor(){
+ // B.~dtor(){
+ // wpA.ReleaseWeakRef(){ // NumStrongRef == 0, NumWeakRef == 0
+ // delete RefCounters_A;
+ // ...
+ // VERIFY( m_pRefCounters->GetNumStrongRefs() == 0 // Access violation!
+
+ // This also may happen if one thread is executing ReleaseStrongRef(), while
+ // another one is simultaneously running ReleaseWeakRef().
+
+ //VERIFY( m_pRefCounters->GetNumStrongRefs() == 0,
+ // "There remain strong references to the object being destroyed" );
+ };
+
+ virtual IReferenceCounters* GetReferenceCounters()const override
+ {
+ return m_pRefCounters;
+ }
+
+ virtual Atomics::Long AddRef()override
+ {
+ return m_pRefCounters->AddStrongRef();
+ }
+
+ virtual Atomics::Long Release()override
+ {
+ return m_pRefCounters->ReleaseStrongRef();
+ }
+
+
+private:
+
+ class RefCountersImpl : public IReferenceCounters
+ {
+ public:
+ static RefCountersImpl* Create( RefCountedObject *pOwner )
+ {
+ return new RefCountersImpl( pOwner );
+ }
+
+ virtual Atomics::Long AddStrongRef()override
+ {
+ VERIFY( m_pObject, "Attempting to increment strong reference counter for a destroyed object!" );
+ return Atomics::AtomicIncrement(m_lNumStrongReferences);
+ }
+
+ virtual Atomics::Long ReleaseStrongRef()override
+ {
+ // If the object is about to be destroyed, we must assure that no other
+ // thread is accessing the ENTIRE REFERENCE COUNTERS OBJECT at the same time.
+ // (Protecting only the pointer is not sufficient!)
+ // The problem may arise if a weak pointer in some other thread is trying to
+ // obtain access to the object.
+ // The safest way is to always protect the entire function:
+ ThreadingTools::LockHelper Lock(m_LockFlag);
+
+ // It is unsafe to not always lock.
+ // For instance, locking if there is only one strong reference left
+ // if( m_lNumStrongReferences == 1 )
+ // Lock.Lock( m_LockFlag );
+ // may fail. Suppose the following scenario:
+ //
+ // This thread | Another thread
+ // | 1. Start releasing another strong
+ // | reference to this object
+ // 1. Read m_lNumStrongReferences==2 | 2. Read m_lNumStrongReferences==2
+ // No lock acquired | 3. Decrement the counter,
+ // | m_lNumStrongReferences==1
+ // 2. Decrement the counter, |
+ // m_lNumStrongReferences==0, |
+ // and the object will be |
+ // destroyed without locking |
+
+
+ // Likewise locking if there is at least one weak reference
+ // if( m_lNumWeakReferences > 0 )
+ // Lock.Lock( m_LockFlag );
+ // may also fail. Suppose the following scenario:
+ //
+ // This thread | Another thread
+ // |
+ // 1. Read m_lNumWeakReferences==0 | 1. Start creating weak reference
+ // No lock acquired | from another strong reference object
+ // | 2. Call AddWeakRef(),
+ // | m_lNumWeakReferences==1
+ // | 3. Call Release() on the original strong
+ // | referenceo bject, m_lNumStrongReferences==1
+ // | 4. Start creating another strong reference
+ // | from the weak pointer, acquired lock and
+ // | read m_pObject
+ // 2. Destroy the object |
+ // | 5. Attempt to create strong reference from
+ // | invalidated pointer
+
+ // Both situations are unlikely to happen. However, they show that
+ // conditional locking is not safe. There might be other more probable
+ // situations
+ auto RefCount = Atomics::AtomicDecrement(m_lNumStrongReferences);
+ VERIFY( RefCount >= 0, "Inconsistent call to ReleaseStrongRef()" );
+ if( RefCount == 0 )
+ {
+ // Locking the object here is also not safe as antoher thread
+ // may be running GetObject(). If it obtains the lock first, it will
+ // get the pointer to the object which will then be destroyed by this
+ // thread
+
+ VERIFY(m_pObject, "Object pointer is null, which means it has already been destroyed");
+ // There are no more STRONG references to the object and it is about to be
+ // destroyed. There could be weak references, so reference counters
+ // can remain alive after the object itself is destroyed.
+
+ // Note that since reference counters are locked, no weak pointers can access
+ // m_pObject while the object is being deleted.
+
+ // We cannot destroy the object while reference counters are locked as this will
+ // cause a deadlock in cases like this:
+ //
+ // A ==sp==> B ---wp---> A
+ //
+ // RefCounters_A.Lock();
+ // delete A{
+ // A.~dtor(){
+ // B.~dtor(){
+ // wpA.ReleaseWeakRef(){
+ // RefCounters_A.Lock(); // Deadlock
+ //
+
+ // So we store the pointer to the object and destory it after unlocking the
+ // reference counters
+ auto *pObj = m_pObject;
+
+ // In a multithreaded environment, reference counters object may
+ // be destroyed at any time while m_pObject->~dtor() is running.
+ // NOTE: m_pObject may not be the only object referencing m_pRefCounters.
+ // All objects that are owned by m_pObject will point to the same
+ // reference counters object.
+ m_pObject->m_pRefCounters = nullptr;
+
+ // Note that this is the only place where m_pObject member can be modified
+ // after the reference counters object has been created
+ m_pObject = nullptr;
+ // The object is now detached from the reference counters and it is if
+ // it was destroyed since no one can obtain access to it.
+
+ // It is essentially important to check the number of weak references
+ // while the object is locked. Otherwise reference counters object
+ // may be destroyed twice if ReleaseWeakRef() is executed by other thread:
+ //
+ // This thread | Another thread - ReleaseWeakRef()
+ // |
+ // 1. Decrement m_lNumStrongReferences,| 1. Decrement m_lNumWeakReferences,
+ // m_lNumStrongReferences==0 | m_lNumWeakReferences == 0
+ // |
+ // 2. Destroy the object | 2. Destroy the object
+ //
+ bool bDestroyThis = m_lNumWeakReferences == 0;
+
+ // We must explicitly unlock the object now to avoid deadlocks. Also,
+ // if this is deleted, this->m_LockFlag will expire, which will cause
+ // Lock.~LockHelper() to crash
+ Lock.Unlock();
+
+ // Destroy referenced object
+ delete pObj;
+
+ // Note that this may be destroyed here already,
+ // see comments in ~RefCountedObject()
+ if( bDestroyThis )
+ delete this;
+ }
+
+ return RefCount;
+ }
+
+ virtual Atomics::Long AddWeakRef()override
+ {
+ return Atomics::AtomicIncrement(m_lNumWeakReferences);
+ }
+
+ virtual Atomics::Long ReleaseWeakRef()override
+ {
+ ThreadingTools::LockHelper Lock(m_LockFlag);
+ // It is essentially important to check the number of references
+ // while the object is locked. Otherwise reference counters object
+ // may be destroyed twice if ReleaseStrongRef() is executed by other
+ // thread.
+ auto NumWeakReferences = Atomics::AtomicDecrement(m_lNumWeakReferences);
+ VERIFY( NumWeakReferences >= 0, "Inconsistent call to ReleaseWeakRef()" );
+ if( NumWeakReferences == 0 && m_lNumStrongReferences == 0 )
+ {
+ // There are no more references to the ref counters object.
+ // We can safely unlock it and destroy.
+ // If we do not unlock it, this->m_LockFlag will expire,
+ // which will cause Lock.~LockHelper() to crash.
+ Lock.Unlock();
+ delete this;
+ }
+ return NumWeakReferences;
+ }
+
+ virtual void GetObject( class IObject **ppObject )override
+ {
+ // We need to lock the object before accessing it to prevent
+ // deletion of the referenced object in another thread.
+ // The thread which is about to delete the object locks it and
+ // decrements the reference counter only after it gets exclusive access.
+ // So if we obtain mutex first, we will increase the reference counter
+ // before the other thread decrements it. Thus the object will not
+ // be deleted.
+ ThreadingTools::LockHelper Lock(m_LockFlag);
+ if( m_pObject )
+ {
+ // QueryInterface() must not lock the object, or a deadlock happens.
+ // The only other two methods that lock the object are ReleaseStrongRef()
+ // and ReleaseWeakRef(), which are never called by QueryInterface()
+ m_pObject->QueryInterface(Diligent::IID_Unknown, ppObject);
+ }
+ }
+
+ virtual Atomics::Long GetNumStrongRefs()const override
+ {
+ return m_lNumStrongReferences;
+ }
+
+ virtual Atomics::Long GetNumWeakRefs()const override
+ {
+ return m_lNumWeakReferences;
+ }
+
+ private:
+ RefCountersImpl(RefCountedObject *pOwner) :
+ m_pObject(pOwner)
+ {
+ VERIFY(m_pObject, "Owner must not be null");
+ m_lNumStrongReferences = 0;
+ m_lNumWeakReferences = 0;
+ }
+
+ ~RefCountersImpl()
+ {
+ VERIFY( m_lNumStrongReferences == 0 && m_lNumWeakReferences == 0,
+ "There exist outstanding references to the object being destroyed" );
+ }
+
+ // No copies/moves
+ RefCountersImpl(const RefCountersImpl&);
+ RefCountersImpl(RefCountersImpl&&);
+ RefCountersImpl& operator = (const RefCountersImpl&);
+ RefCountersImpl& operator = (RefCountersImpl&&);
+
+ // It is crucially important that the type of the pointer
+ // is RefCountedObject and not IObject, since the latter
+ // does not have virtual dtor.
+ RefCountedObject *m_pObject;
+ Atomics::AtomicLong m_lNumStrongReferences;
+ Atomics::AtomicLong m_lNumWeakReferences;
+ ThreadingTools::LockFlag m_LockFlag;
+ };
+
+ // Reference counters pointer cannot be of type RefCountersImpl*,
+ // because when an owner pointer is provided to RefCountedObject(),
+ // the type of pOwner->GetReferenceCounters() may not be convertible
+ // to RefCountedObject<Base>::RefCountersImpl*.
+ IReferenceCounters *m_pRefCounters;
+};
+
+}
diff --git a/Common/include/StringTools.h b/Common/include/StringTools.h
new file mode 100644
index 00000000..687eeef8
--- /dev/null
+++ b/Common/include/StringTools.h
@@ -0,0 +1,75 @@
+/* Copyright 2015 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#pragma once
+
+#include <string>
+#include <sstream>
+#include <locale>
+
+namespace Diligent
+{
+
+inline std::string NarrowString(const std::wstring &WideStr)
+{
+ std::string NarrowStr;
+ const std::ctype<wchar_t>& ctfacet = std::use_facet< std::ctype<wchar_t> >( std::wstringstream().getloc() ) ;
+ for( std::wstring::const_iterator CurrWChar = WideStr.begin();
+ CurrWChar != WideStr.end();
+ CurrWChar++ )
+ NarrowStr.push_back( ctfacet.narrow( *CurrWChar, 0 ) );
+
+ return NarrowStr;
+}
+
+inline std::wstring WidenString(const std::string &Str)
+{
+ std::wstring WideStr;
+ const std::ctype<wchar_t>& ctfacet = std::use_facet< std::ctype<wchar_t> >( std::wstringstream().getloc() ) ;
+ for( std::string::const_iterator CurrChar = Str.begin();
+ CurrChar != Str.end();
+ CurrChar++ )
+ WideStr.push_back( ctfacet.widen( *CurrChar ) );
+
+ return WideStr;
+}
+
+inline int StrCmpNoCase(const char* Str1, const char* Str2, size_t NumChars)
+{
+#ifdef PLATFORM_ANDROID
+# define _strnicmp strncasecmp
+#endif
+
+ return _strnicmp( Str1, Str2, NumChars );
+}
+
+inline int StrCmpNoCase(const char* Str1, const char* Str2)
+{
+#ifdef PLATFORM_ANDROID
+# define _stricmp strcasecmp
+#endif
+
+ return _stricmp( Str1, Str2 );
+}
+
+}
diff --git a/Common/include/Timer.h b/Common/include/Timer.h
new file mode 100644
index 00000000..5e3dfe54
--- /dev/null
+++ b/Common/include/Timer.h
@@ -0,0 +1,41 @@
+/* Copyright 2015 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#pragma once
+
+#include <chrono>
+
+namespace Diligent
+{
+ class Timer
+ {
+ public:
+ Timer();
+ void Restart();
+ double GetElapsedTime()const;
+ float GetElapsedTimef()const;
+
+ private:
+ std::chrono::high_resolution_clock::time_point m_StartTime;
+ };
+}
diff --git a/Common/include/UniqueIdentifier.h b/Common/include/UniqueIdentifier.h
new file mode 100644
index 00000000..e4fd7159
--- /dev/null
+++ b/Common/include/UniqueIdentifier.h
@@ -0,0 +1,79 @@
+/* Copyright 2015 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#pragma once
+
+#include "Atomics.h"
+
+namespace Diligent
+{
+ typedef Atomics::Long UniqueIdentifier;
+
+ // Template switch is used to have distinct counters
+ // for unrelated groups of objects
+ template<typename ObjectsClass>
+ class UniqueIdHelper
+ {
+ public:
+ UniqueIdHelper() :
+ m_ID(0),
+ m_bIsInitialized( false )
+ {}
+
+ UniqueIdHelper( UniqueIdHelper&& RHS) :
+ m_ID( RHS.m_ID ),
+ m_bIsInitialized( RHS.m_bIsInitialized )
+ {
+ RHS.m_ID = 0;
+ RHS.m_bIsInitialized = false;
+ }
+
+ const UniqueIdHelper& operator = (UniqueIdHelper&& RHS)
+ {
+ m_ID = RHS.m_ID;
+ m_bIsInitialized = RHS.m_bIsInitialized;
+ RHS.m_ID = 0;
+ RHS.m_bIsInitialized = false;
+
+ return *this;
+ }
+
+ UniqueIdentifier GetID()const
+ {
+ if( !m_bIsInitialized )
+ {
+ static Atomics::AtomicLong sm_GlobalCounter;
+ m_ID = Atomics::AtomicIncrement(sm_GlobalCounter);
+ m_bIsInitialized = true;
+ }
+ return m_ID;
+ }
+
+ private:
+ UniqueIdHelper( const UniqueIdHelper& );
+ const UniqueIdHelper& operator = ( const UniqueIdHelper& );
+
+ mutable UniqueIdentifier m_ID;
+ mutable bool m_bIsInitialized;
+ };
+}
diff --git a/Common/include/ValidatedCast.h b/Common/include/ValidatedCast.h
new file mode 100644
index 00000000..916148c4
--- /dev/null
+++ b/Common/include/ValidatedCast.h
@@ -0,0 +1,33 @@
+/* Copyright 2015 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#pragma once
+
+#include "DebugUtilities.h"
+
+template<typename DstType, typename SrcType>
+DstType* ValidatedCast( SrcType *Ptr )
+{
+ CHECK_DYNAMIC_TYPE( DstType, Ptr );
+ return static_cast<DstType*>( Ptr );
+}
diff --git a/Common/include/pch.h b/Common/include/pch.h
new file mode 100644
index 00000000..8b5e042b
--- /dev/null
+++ b/Common/include/pch.h
@@ -0,0 +1,35 @@
+/* Copyright 2015 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+// stdafx.h : include file for standard system include files,
+// or project specific include files that are used frequently, but
+// are changed infrequently
+//
+
+#pragma once
+
+#include "PlatformDefinitions.h"
+#include "BasicTypes.h"
+#include "Errors.h"
+#include "FileWrapper.h"
+#include "RefCntAutoPtr.h" \ No newline at end of file