merging MiscBranch into Physics with conflict fixes
This commit is contained in:
parent
4672984b51
commit
d241298308
|
@ -0,0 +1,65 @@
|
||||||
|
|
||||||
|
#include "..\OResource.h"
|
||||||
|
#include "..\..\Utilities.h"
|
||||||
|
|
||||||
|
#include <fstream>
|
||||||
|
|
||||||
|
using namespace Oyster::Resource;
|
||||||
|
|
||||||
|
|
||||||
|
OResource* OResource::CustomLoader(const wchar_t filename[], CustomLoadFunction fnc)
|
||||||
|
{
|
||||||
|
<<<<<<< HEAD
|
||||||
|
const CustomData &data = fnc();
|
||||||
|
=======
|
||||||
|
CustomData data;
|
||||||
|
memset(&data, 0, sizeof(CustomData));
|
||||||
|
|
||||||
|
fnc(filename, data);
|
||||||
|
|
||||||
|
if(!data.loadedData)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if(!data.resourceUnloadFnc)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/** For some wierd reason that i don't understand when trying to send data.loadedData directly as a
|
||||||
|
* parameter to OResource constructor, the value is changed when it arrives in the constructor.
|
||||||
|
* Doing it like this, storing in a temporary variable, the value stays correct. (What the fuck! I must be overloking something...)*/
|
||||||
|
//OHRESOURCE temp = data.loadedData;
|
||||||
|
OResource *resource = new OResource(data.loadedData, ResourceType_UNKNOWN, 0, 0, filename);
|
||||||
|
>>>>>>> origin/MiscBranch
|
||||||
|
|
||||||
|
resource->customData = new CustomResourceData();
|
||||||
|
resource->customData->unloadingFunction = data.resourceUnloadFnc;
|
||||||
|
resource->customData->loadingFunction = fnc;
|
||||||
|
|
||||||
|
return resource;
|
||||||
|
}
|
||||||
|
void OResource::CustomUnloader()
|
||||||
|
{
|
||||||
|
this->customData->unloadingFunction(this->resourceData);
|
||||||
|
}
|
||||||
|
OResource* OResource::CustomReloader()
|
||||||
|
{
|
||||||
|
CustomUnloader();
|
||||||
|
|
||||||
|
<<<<<<< HEAD
|
||||||
|
const CustomData &data = this->customData->loadingFunction();
|
||||||
|
=======
|
||||||
|
CustomData data;
|
||||||
|
memset(&data, 0, sizeof(CustomData));
|
||||||
|
|
||||||
|
this->customData->loadingFunction(this->resourceFilename.c_str(), data);
|
||||||
|
>>>>>>> origin/MiscBranch
|
||||||
|
this->resourceData = (OHRESOURCE)data.loadedData;
|
||||||
|
|
||||||
|
if(data.resourceUnloadFnc)
|
||||||
|
{
|
||||||
|
this->customData->unloadingFunction = data.resourceUnloadFnc;
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,258 @@
|
||||||
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
// Created by [Dennis Andersen] [2013]
|
||||||
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
|
#include "OysterResource.h"
|
||||||
|
#include "OResource.h"
|
||||||
|
#include <string>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
using namespace Oyster::Resource;
|
||||||
|
|
||||||
|
class ResourcePrivate
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
std::map<std::wstring, OResource*> resources;
|
||||||
|
|
||||||
|
OResource* FindResource(const OHRESOURCE& h) const;
|
||||||
|
OResource* FindResource(const wchar_t c[]) const;
|
||||||
|
void SaveResource(OResource* r, bool addNew = true);
|
||||||
|
|
||||||
|
} resourcePrivate;
|
||||||
|
|
||||||
|
|
||||||
|
OHRESOURCE OysterResource::LoadResource(const wchar_t* filename, ResourceType type, int customID, bool force)
|
||||||
|
{
|
||||||
|
if(!filename) return 0;
|
||||||
|
|
||||||
|
OResource *resourceData = resourcePrivate.FindResource(filename);
|
||||||
|
|
||||||
|
if(resourceData)
|
||||||
|
{
|
||||||
|
if(force)
|
||||||
|
{
|
||||||
|
return OysterResource::ReloadResource(filename);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//Add new reference
|
||||||
|
resourcePrivate.SaveResource(resourceData, false);
|
||||||
|
return resourceData->GetResourceHandle();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
resourceData = OResource::Load(filename, type);
|
||||||
|
if(resourceData)
|
||||||
|
{
|
||||||
|
resourceData->SetResourceID(customID);
|
||||||
|
resourcePrivate.SaveResource(resourceData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return resourceData->GetResourceHandle();
|
||||||
|
}
|
||||||
|
OHRESOURCE OysterResource::LoadResource(const wchar_t filename[], CustomLoadFunction loadFnc, int customId, bool force)
|
||||||
|
{
|
||||||
|
if(!filename)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if(!loadFnc)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
OResource *resourceData = resourcePrivate.FindResource(filename);
|
||||||
|
if(resourceData)
|
||||||
|
{
|
||||||
|
if(force)
|
||||||
|
{
|
||||||
|
return OysterResource::ReloadResource(filename);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//Add new reference
|
||||||
|
resourcePrivate.SaveResource(resourceData, false);
|
||||||
|
return resourceData->GetResourceHandle();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
resourceData = OResource::Load(filename, loadFnc);
|
||||||
|
if(resourceData)
|
||||||
|
{
|
||||||
|
resourceData->SetResourceID(customId);
|
||||||
|
resourcePrivate.SaveResource(resourceData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
<<<<<<< HEAD
|
||||||
|
|
||||||
|
resourceData = OResource::Load(filename, loadFnc);
|
||||||
|
|
||||||
|
if(!resourceData) return 0;
|
||||||
|
|
||||||
|
if(resourceData) resourceData->SetResourceID(CustomId);
|
||||||
|
resourcePrivate.SaveResource(resourceData);
|
||||||
|
=======
|
||||||
|
>>>>>>> origin/MiscBranch
|
||||||
|
|
||||||
|
return (OHRESOURCE)resourceData->GetResourceHandle();
|
||||||
|
}
|
||||||
|
|
||||||
|
OHRESOURCE OysterResource::ReloadResource(const wchar_t filename[])
|
||||||
|
{
|
||||||
|
OResource *resourceData = resourcePrivate.FindResource(filename);
|
||||||
|
if(!resourceData) return 0; //The resource has not been loaded
|
||||||
|
|
||||||
|
return OResource::Reload(resourceData)->GetResourceHandle();
|
||||||
|
}
|
||||||
|
OHRESOURCE OysterResource::ReloadResource(OHRESOURCE resource)
|
||||||
|
{
|
||||||
|
OResource *resourceData = resourcePrivate.FindResource(resource);
|
||||||
|
if(!resourceData) return 0; //The resource has not been loaded
|
||||||
|
|
||||||
|
return OResource::Reload(resourceData)->GetResourceHandle();
|
||||||
|
}
|
||||||
|
|
||||||
|
void OysterResource::Clean()
|
||||||
|
{
|
||||||
|
auto i = resourcePrivate.resources.begin();
|
||||||
|
auto last = resourcePrivate.resources.end();
|
||||||
|
|
||||||
|
for (i; i != last; i++)
|
||||||
|
{
|
||||||
|
//Remove all the references
|
||||||
|
while (!OResource::Release(i->second));
|
||||||
|
|
||||||
|
const wchar_t* temp = i->second->GetResourceFilename();
|
||||||
|
delete resourcePrivate.resources[temp];
|
||||||
|
resourcePrivate.resources.erase(temp);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void OysterResource::ReleaseResource(const OHRESOURCE& resourceData)
|
||||||
|
{
|
||||||
|
OResource* t = resourcePrivate.FindResource(resourceData);
|
||||||
|
if(t)
|
||||||
|
{
|
||||||
|
if(OResource::Release(t))
|
||||||
|
{
|
||||||
|
const wchar_t* temp = t->GetResourceFilename();
|
||||||
|
delete resourcePrivate.resources[temp];
|
||||||
|
resourcePrivate.resources.erase(temp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void OysterResource::ReleaseResource(const wchar_t filename[])
|
||||||
|
{
|
||||||
|
OResource* t = resourcePrivate.FindResource(filename);
|
||||||
|
if(t)
|
||||||
|
{
|
||||||
|
if(OResource::Release(t))
|
||||||
|
{
|
||||||
|
const wchar_t* temp = t->GetResourceFilename();
|
||||||
|
delete resourcePrivate.resources[temp];
|
||||||
|
resourcePrivate.resources.erase(temp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void OysterResource::SetResourceId (const OHRESOURCE& resourceData, unsigned int id)
|
||||||
|
{
|
||||||
|
OResource* t = resourcePrivate.FindResource(resourceData);
|
||||||
|
|
||||||
|
if(t) t->SetResourceID(id);
|
||||||
|
}
|
||||||
|
void OysterResource::SetResourceId(const wchar_t c[], unsigned int id)
|
||||||
|
{
|
||||||
|
OResource* t = resourcePrivate.FindResource(c);
|
||||||
|
|
||||||
|
if(t) t->SetResourceID(id);
|
||||||
|
}
|
||||||
|
ResourceType OysterResource::GetResourceType (const OHRESOURCE& resourceData)
|
||||||
|
{
|
||||||
|
OResource* t = resourcePrivate.FindResource(resourceData);
|
||||||
|
|
||||||
|
if(t) return t->GetResourceType();
|
||||||
|
|
||||||
|
return ResourceType_INVALID;
|
||||||
|
}
|
||||||
|
ResourceType OysterResource::GetResourceType (const wchar_t c[])
|
||||||
|
{
|
||||||
|
OResource* t = resourcePrivate.FindResource(c);
|
||||||
|
|
||||||
|
if(t) return t->GetResourceType();
|
||||||
|
|
||||||
|
return ResourceType_INVALID;
|
||||||
|
}
|
||||||
|
const wchar_t* OysterResource::GetResourceFilename (const OHRESOURCE& resourceData)
|
||||||
|
{
|
||||||
|
OResource* t = resourcePrivate.FindResource(resourceData);
|
||||||
|
|
||||||
|
if(t) return t->GetResourceFilename();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
OHRESOURCE OysterResource::GetResourceHandle(const wchar_t filename[])
|
||||||
|
{
|
||||||
|
OResource* t = resourcePrivate.FindResource(filename);
|
||||||
|
|
||||||
|
if(t) return t->GetResourceHandle();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
int OysterResource::GetResourceId (const OHRESOURCE& resourceData)
|
||||||
|
{
|
||||||
|
OResource* t = resourcePrivate.FindResource(resourceData);
|
||||||
|
|
||||||
|
if(t) return t->GetResourceID();
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
int OysterResource::GetResourceId(const wchar_t c[])
|
||||||
|
{
|
||||||
|
OResource* t = resourcePrivate.FindResource(c);
|
||||||
|
|
||||||
|
if(t) return t->GetResourceID();
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
OResource* ResourcePrivate::FindResource(const OHRESOURCE& h) const
|
||||||
|
{
|
||||||
|
for (auto i = this->resources.begin(); i != this->resources.end() ; i++)
|
||||||
|
{
|
||||||
|
if(i->second->GetResourceHandle() == h)
|
||||||
|
{
|
||||||
|
return i->second;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
OResource* ResourcePrivate::FindResource(const wchar_t c[]) const
|
||||||
|
{
|
||||||
|
std::wstring temp = c;
|
||||||
|
auto t = this->resources.find(c);
|
||||||
|
if(t == this->resources.end()) return 0;
|
||||||
|
|
||||||
|
return t->second;
|
||||||
|
}
|
||||||
|
void ResourcePrivate::SaveResource( OResource* r, bool addNew )
|
||||||
|
{
|
||||||
|
if(!r) return;
|
||||||
|
|
||||||
|
if(addNew)
|
||||||
|
{
|
||||||
|
this->resources[r->GetResourceFilename()] = r;
|
||||||
|
}
|
||||||
|
|
||||||
|
r->resourceRef.Incref();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,164 @@
|
||||||
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
// Created by [Dennis Andersen] [2013]
|
||||||
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#ifndef MISC_OYSTER_RESOURCE_H
|
||||||
|
#define MISC_OYSTER_RESOURCE_H
|
||||||
|
|
||||||
|
|
||||||
|
namespace Oyster
|
||||||
|
{
|
||||||
|
namespace Resource
|
||||||
|
{
|
||||||
|
struct CustomData;
|
||||||
|
/** A Resource handle representing various resources */
|
||||||
|
<<<<<<< HEAD
|
||||||
|
typedef unsigned long OHRESOURCE;
|
||||||
|
typedef void(*CustomUnloadFunction)(void*);
|
||||||
|
typedef const CustomData&(*CustomLoadFunction)();
|
||||||
|
=======
|
||||||
|
typedef void* OHRESOURCE;
|
||||||
|
/** Typedef on a fuction required for custom unloading */
|
||||||
|
typedef void(*CustomUnloadFunction)(void* loadedData);
|
||||||
|
/** Typedef on a fuction required for custom loading */
|
||||||
|
typedef void(*CustomLoadFunction)(const wchar_t filename[], CustomData& outData);
|
||||||
|
>>>>>>> origin/MiscBranch
|
||||||
|
|
||||||
|
/** An enum class representing all avalible resources that is supported. */
|
||||||
|
enum ResourceType
|
||||||
|
{
|
||||||
|
//Byte
|
||||||
|
ResourceType_Byte_Raw, /**< Handle can be interpeted as char[] or char* */
|
||||||
|
ResourceType_Byte_ANSI, /**< Handle can be interpeted as char[] or char* */
|
||||||
|
ResourceType_Byte_UTF8, /**< Handle can be interpeted as char[] or char* */
|
||||||
|
ResourceType_Byte_UNICODE, /**< Handle can be interpeted as char[] or char* */
|
||||||
|
ResourceType_Byte_UTF16LE, /**< Handle can be interpeted as char[] or char* */
|
||||||
|
|
||||||
|
ResourceType_COUNT, /**< Handle can be interpeted as ? */
|
||||||
|
|
||||||
|
ResourceType_UNKNOWN = -1, /**< Handle can be interpeted as void* */
|
||||||
|
ResourceType_INVALID = -2, /**< Invalid or non existing resource */
|
||||||
|
};
|
||||||
|
|
||||||
|
/** A struct to fill when doing a custom resource Load. */
|
||||||
|
struct CustomData
|
||||||
|
{
|
||||||
|
void* loadedData; //<! The loaded resource interpeted as a void*.
|
||||||
|
CustomUnloadFunction resourceUnloadFnc; //<! The function that will be used to free the resource when needed.
|
||||||
|
};
|
||||||
|
|
||||||
|
/** A resource handler interface to interact with when loading resources.
|
||||||
|
* The resource handler uses the filename to make resources unuiqe.
|
||||||
|
*/
|
||||||
|
class OysterResource
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* Load a resource given a type.
|
||||||
|
* @param filename The path to the resource.
|
||||||
|
* @param type The resource type to load.
|
||||||
|
* @param force If set to true, the resource will be reloaded if it already exists. If it does not, nothing happens.
|
||||||
|
* @return If function suceeds, a handle to the resource will be returned. If failed 0 is returned.
|
||||||
|
*/
|
||||||
|
static OHRESOURCE LoadResource(const wchar_t filename[], ResourceType type, int customId = -1, bool force = false);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load a resource with a custom loading function
|
||||||
|
* @param filename The path to the resource.
|
||||||
|
* @param loadFnc If set, this gives you the right to do custom resource loading if your recource type is not supported.
|
||||||
|
* @param customId A custom ID that can be used.
|
||||||
|
* @param force If set to true, the resource will be reloaded even if exists.
|
||||||
|
* @return If function suceeds, a handle to the resource will be returned. If failed 0 is returned.
|
||||||
|
*/
|
||||||
|
static OHRESOURCE LoadResource(const wchar_t filename[], CustomLoadFunction loadFnc = 0, int customId = -1, bool force = false);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reload a resource
|
||||||
|
* @param filename The path to the resource.
|
||||||
|
* @return If function suceeds, a handle to the resource will be returned. If failed 0 is returned.
|
||||||
|
*/
|
||||||
|
static OHRESOURCE ReloadResource(const wchar_t filename[]);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reload a resource
|
||||||
|
* @param filename The path to the resource.
|
||||||
|
* @return If function suceeds, a handle to the resource will be returned. If failed 0 is returned.
|
||||||
|
*/
|
||||||
|
static OHRESOURCE ReloadResource(OHRESOURCE resource);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Releases all resources loaded by the resource handler.
|
||||||
|
* @return Nothing
|
||||||
|
*/
|
||||||
|
static void Clean();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Release a reference to the resource handle
|
||||||
|
* @param resource The handle to release.
|
||||||
|
* @return Nothing
|
||||||
|
*/
|
||||||
|
static void ReleaseResource(const OHRESOURCE& resource);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Release a reference to the resource handle
|
||||||
|
* @param resource The resource filename to release reference.
|
||||||
|
* @return Nothing
|
||||||
|
*/
|
||||||
|
static void ReleaseResource(const wchar_t filename[]);
|
||||||
|
|
||||||
|
/** Set a user defined ID
|
||||||
|
* @param resource A handle to accociate the id with.
|
||||||
|
* @param id A user defined identifier that the resource handler does not touch.
|
||||||
|
*/
|
||||||
|
static void SetResourceId(const OHRESOURCE& resource, unsigned int id);
|
||||||
|
|
||||||
|
/** Set a user defined ID
|
||||||
|
* If the resource is not loaded the id will not be set.
|
||||||
|
* @param resource A filename to accociate the id with.
|
||||||
|
* @param id A user defined identifier that the resource handler does not touch.
|
||||||
|
*/
|
||||||
|
static void SetResourceId(const wchar_t filename[], unsigned int id);
|
||||||
|
|
||||||
|
/** Get a resource type given a OHRESOURCE handle
|
||||||
|
* @param resource The handle to check
|
||||||
|
* @return Returns the resource type of the handle
|
||||||
|
*/
|
||||||
|
static ResourceType GetResourceType(const OHRESOURCE& resource);
|
||||||
|
|
||||||
|
/** Get a resource type given a filename
|
||||||
|
* If the resource is not loaded the id will not be set.
|
||||||
|
* @param resource The filename to check
|
||||||
|
* @return Returns the resource type of the handle
|
||||||
|
*/
|
||||||
|
static ResourceType GetResourceType (const wchar_t filename[]);
|
||||||
|
|
||||||
|
/** Get a resource filename given a OHRESOURCE handle
|
||||||
|
* @param resource The handle to check
|
||||||
|
* @return Returns the accociated filename
|
||||||
|
*/
|
||||||
|
static const wchar_t* GetResourceFilename(const OHRESOURCE& resource);
|
||||||
|
|
||||||
|
/** Get a resource handle given a filename
|
||||||
|
* If the resource is not loaded function returns 0.
|
||||||
|
* @param resource The filename to check
|
||||||
|
* @return Returns the accociated handle
|
||||||
|
*/
|
||||||
|
static OHRESOURCE GetResourceHandle(const wchar_t filename[]);
|
||||||
|
|
||||||
|
/** Get a user defined ID accociated with a handle
|
||||||
|
* @param resource The handle to check
|
||||||
|
* @return Returns the accociated ID
|
||||||
|
*/
|
||||||
|
static int GetResourceId(const OHRESOURCE& resource);
|
||||||
|
|
||||||
|
/** Get a user defined ID accociated with a filename
|
||||||
|
* @param resource The filename to check
|
||||||
|
* @return Returns the accociated ID
|
||||||
|
*/
|
||||||
|
static int GetResourceId(const wchar_t filename[]);
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,67 @@
|
||||||
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
// Created by [Dennis Andersen] [2013]
|
||||||
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#include "OysterMutex.h"
|
||||||
|
|
||||||
|
#include <chrono>
|
||||||
|
#include <thread>
|
||||||
|
#include <future>
|
||||||
|
|
||||||
|
using namespace Oyster::Thread;
|
||||||
|
|
||||||
|
|
||||||
|
OysterMutex::OysterMutex()
|
||||||
|
{}
|
||||||
|
|
||||||
|
OysterMutex::OysterMutex(bool initialOwnership)
|
||||||
|
{
|
||||||
|
if(initialOwnership)
|
||||||
|
{
|
||||||
|
this->mutex.lock();
|
||||||
|
this->id = std::this_thread::get_id();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
OysterMutex::~OysterMutex()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
void OysterMutex::LockMutex()
|
||||||
|
{
|
||||||
|
if(std::this_thread::get_id() == this->id) return;
|
||||||
|
|
||||||
|
this->mutex.lock();
|
||||||
|
|
||||||
|
this->id = std::this_thread::get_id();
|
||||||
|
}
|
||||||
|
void OysterMutex::LockMutex(unsigned int msec)
|
||||||
|
{
|
||||||
|
if(std::this_thread::get_id() == this->id) return;
|
||||||
|
|
||||||
|
auto start = std::chrono::high_resolution_clock::now();
|
||||||
|
auto end = start + std::chrono::milliseconds(msec);
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if(this->mutex.try_lock())
|
||||||
|
{
|
||||||
|
this->mutex.lock();
|
||||||
|
this->id = std::this_thread::get_id();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} while (std::chrono::high_resolution_clock::now() < end);
|
||||||
|
|
||||||
|
this->mutex.lock();
|
||||||
|
}
|
||||||
|
void OysterMutex::UnlockMutex()
|
||||||
|
{
|
||||||
|
//Let the owner unlock
|
||||||
|
if(std::this_thread::get_id() != this->id) return;
|
||||||
|
|
||||||
|
this->mutex.unlock();
|
||||||
|
this->id = std::thread::id();
|
||||||
|
|
||||||
|
}
|
||||||
|
bool OysterMutex::IsTaken()
|
||||||
|
{
|
||||||
|
return !this->mutex.try_lock();
|
||||||
|
}
|
|
@ -0,0 +1,37 @@
|
||||||
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
// Created by [Dennis Andersen] [2013]
|
||||||
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#ifndef MISC_OYSTER_MUTEX_H
|
||||||
|
#define MISC_OYSTER_MUTEX_H
|
||||||
|
|
||||||
|
#include <mutex>
|
||||||
|
#include <thread>
|
||||||
|
#include <atomic>
|
||||||
|
|
||||||
|
namespace Oyster
|
||||||
|
{
|
||||||
|
namespace Thread
|
||||||
|
{
|
||||||
|
class OysterMutex
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
OysterMutex();
|
||||||
|
OysterMutex(bool initialOwnership);
|
||||||
|
virtual~OysterMutex();
|
||||||
|
void LockMutex();
|
||||||
|
void LockMutex(unsigned int timeSpan);
|
||||||
|
void UnlockMutex();
|
||||||
|
/** Returns true if mutex is taken */
|
||||||
|
bool IsTaken();
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::mutex mutex;
|
||||||
|
std::thread::id id;
|
||||||
|
|
||||||
|
OysterMutex(const OysterMutex&);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // !MISC_OYSTER_MUTEX_H
|
|
@ -0,0 +1,47 @@
|
||||||
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
// Created by [Dennis Andersen] [2013]
|
||||||
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#ifndef MISC_OYSTER_THREAD_H
|
||||||
|
#define MISC_OYSTER_THREAD_H
|
||||||
|
|
||||||
|
#include "IThreadObject.h"
|
||||||
|
namespace Oyster
|
||||||
|
{
|
||||||
|
namespace Thread
|
||||||
|
{
|
||||||
|
enum OYSTER_THREAD_ERROR
|
||||||
|
{
|
||||||
|
OYSTER_THREAD_ERROR_FAILED,
|
||||||
|
OYSTER_THREAD_ERROR_SUCCESS,
|
||||||
|
};
|
||||||
|
|
||||||
|
class OysterThread
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
struct PrivateData;
|
||||||
|
PrivateData *privateData;
|
||||||
|
|
||||||
|
public:
|
||||||
|
OysterThread();
|
||||||
|
OysterThread(const OysterThread& original);
|
||||||
|
const OysterThread& operator=(const OysterThread& original);
|
||||||
|
virtual~OysterThread();
|
||||||
|
|
||||||
|
OYSTER_THREAD_ERROR Create(IThreadObject* worker, bool start);
|
||||||
|
OYSTER_THREAD_ERROR Start();
|
||||||
|
void Stop();
|
||||||
|
void Pause();
|
||||||
|
void Pause(int mSec);
|
||||||
|
void Resume();
|
||||||
|
OYSTER_THREAD_ERROR Reset(IThreadObject* worker = 0);
|
||||||
|
void Terminate();
|
||||||
|
void Wait();
|
||||||
|
void Wait(int mSec);
|
||||||
|
OYSTER_THREAD_ERROR Swap(const OysterThread* other);
|
||||||
|
bool IsActive();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // !MISC_OYSTER_THREAD_H
|
|
@ -0,0 +1,281 @@
|
||||||
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
// Created by [Dennis Andersen] [2013]
|
||||||
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#include "OysterThread.h"
|
||||||
|
#include "OysterMutex.h"
|
||||||
|
#include "..\Utilities.h"
|
||||||
|
#include <thread>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <atomic>
|
||||||
|
|
||||||
|
using namespace Oyster::Thread;
|
||||||
|
using namespace Utility::DynamicMemory::SmartPointer;
|
||||||
|
|
||||||
|
|
||||||
|
#pragma region Declerations
|
||||||
|
|
||||||
|
struct ThreadData;
|
||||||
|
/** A typical Oyster thread function */
|
||||||
|
typedef void (*ThreadFunction)(StdSmartPointer<ThreadData>&);
|
||||||
|
|
||||||
|
enum OYSTER_THREAD_STATE
|
||||||
|
{
|
||||||
|
OYSTER_THREAD_STATE_RESET,
|
||||||
|
OYSTER_THREAD_STATE_RUNNING,
|
||||||
|
OYSTER_THREAD_STATE_PAUSED,
|
||||||
|
OYSTER_THREAD_STATE_STOPED,
|
||||||
|
OYSTER_THREAD_STATE_DEAD,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct ThreadData
|
||||||
|
{
|
||||||
|
std::atomic<OYSTER_THREAD_STATE> state; //<! The current thread state.
|
||||||
|
//OYSTER_THREAD_STATE state; //<! The current thread state.
|
||||||
|
StdSmartPointer<std::thread> workerThread; //<! The worker thread.
|
||||||
|
std::thread::id callingThread; //<! The owner thread.
|
||||||
|
IThreadObject *owner; //<! The owner of the thread as IThread.
|
||||||
|
std::atomic<int> msec; //<! A timer in miliseconds.
|
||||||
|
//OysterMutex mutexLock; //<! The lock, locking the member variabls.
|
||||||
|
|
||||||
|
ThreadData() {}
|
||||||
|
~ThreadData() {}
|
||||||
|
ThreadData(const ThreadData&) {};
|
||||||
|
};
|
||||||
|
struct OysterThread::PrivateData
|
||||||
|
{
|
||||||
|
StdSmartPointer<ThreadData> threadData;
|
||||||
|
|
||||||
|
PrivateData()
|
||||||
|
:threadData(new ThreadData())
|
||||||
|
{
|
||||||
|
threadData->owner = 0;
|
||||||
|
threadData->workerThread = 0;
|
||||||
|
threadData->callingThread;
|
||||||
|
threadData->state = OYSTER_THREAD_STATE_STOPED;
|
||||||
|
}
|
||||||
|
PrivateData(const PrivateData& o)
|
||||||
|
{
|
||||||
|
threadData = o.threadData;
|
||||||
|
}
|
||||||
|
~PrivateData()
|
||||||
|
{
|
||||||
|
//@todo TODO: Make detatch avalible.
|
||||||
|
this->threadData->workerThread->detach();
|
||||||
|
|
||||||
|
this->threadData->owner = 0;
|
||||||
|
|
||||||
|
this->threadData->state = OYSTER_THREAD_STATE_DEAD;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#pragma endregion
|
||||||
|
|
||||||
|
|
||||||
|
int tempId = 0;
|
||||||
|
std::vector<int> IDS;
|
||||||
|
static void ThreadingFunction(StdSmartPointer<ThreadData> &origin)
|
||||||
|
{
|
||||||
|
|
||||||
|
bool shouldContinue;
|
||||||
|
StdSmartPointer<ThreadData> w = origin;
|
||||||
|
|
||||||
|
theBegining:
|
||||||
|
|
||||||
|
while(w->state == OYSTER_THREAD_STATE_STOPED)
|
||||||
|
{
|
||||||
|
std::this_thread::yield();
|
||||||
|
}
|
||||||
|
|
||||||
|
// w->mutexLock.LockMutex();
|
||||||
|
if(w->owner)
|
||||||
|
{
|
||||||
|
w->owner->ThreadEntry();
|
||||||
|
}
|
||||||
|
// w->mutexLock.UnlockMutex();
|
||||||
|
|
||||||
|
while (w->state != OYSTER_THREAD_STATE_STOPED && w->state != OYSTER_THREAD_STATE_DEAD)
|
||||||
|
{
|
||||||
|
// w->mutexLock.LockMutex();
|
||||||
|
{
|
||||||
|
if(w->owner)
|
||||||
|
{
|
||||||
|
shouldContinue = w->owner->DoWork();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// w->mutexLock.UnlockMutex();
|
||||||
|
|
||||||
|
if(!shouldContinue)
|
||||||
|
{
|
||||||
|
goto theEnd;
|
||||||
|
}
|
||||||
|
if(w->state == OYSTER_THREAD_STATE_DEAD)
|
||||||
|
{
|
||||||
|
goto theEnd;
|
||||||
|
}
|
||||||
|
else if(w->state == OYSTER_THREAD_STATE_RESET)
|
||||||
|
{
|
||||||
|
goto theBegining;
|
||||||
|
}
|
||||||
|
else if(w->msec > 0)
|
||||||
|
{
|
||||||
|
std::this_thread::sleep_for(std::chrono::milliseconds(w->msec));
|
||||||
|
}
|
||||||
|
|
||||||
|
while (w->state == OYSTER_THREAD_STATE_PAUSED)
|
||||||
|
{
|
||||||
|
std::this_thread::yield();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(w->state == OYSTER_THREAD_STATE_DEAD)
|
||||||
|
{
|
||||||
|
w->workerThread->detach();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
theEnd:
|
||||||
|
|
||||||
|
// w->mutexLock.LockMutex();
|
||||||
|
if(w->owner)
|
||||||
|
{
|
||||||
|
w->owner->ThreadExit();
|
||||||
|
}
|
||||||
|
// w->mutexLock.UnlockMutex();
|
||||||
|
|
||||||
|
w->state = OYSTER_THREAD_STATE_DEAD;
|
||||||
|
}
|
||||||
|
|
||||||
|
OysterThread::OysterThread()
|
||||||
|
{
|
||||||
|
this->privateData = new PrivateData();
|
||||||
|
}
|
||||||
|
OysterThread::OysterThread(const OysterThread& original)
|
||||||
|
{
|
||||||
|
this->privateData = new PrivateData(*original.privateData);
|
||||||
|
}
|
||||||
|
const OysterThread& OysterThread::operator=(const OysterThread& original)
|
||||||
|
{
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
OysterThread::~OysterThread()
|
||||||
|
{
|
||||||
|
delete this->privateData;
|
||||||
|
this->privateData = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
OYSTER_THREAD_ERROR OysterThread::Create(IThreadObject* worker, bool start)
|
||||||
|
{
|
||||||
|
if(!this->privateData) return OYSTER_THREAD_ERROR_FAILED;
|
||||||
|
if(this->privateData->threadData->workerThread) return OYSTER_THREAD_ERROR_FAILED;
|
||||||
|
|
||||||
|
this->privateData->threadData->owner = worker;
|
||||||
|
|
||||||
|
ThreadFunction fnc = ThreadingFunction;
|
||||||
|
|
||||||
|
//Maby move this thread creation to a seperate Start() function because std::thread fires the thread when it is created. :(
|
||||||
|
this->privateData->threadData->workerThread = new std::thread(fnc, this->privateData->threadData);
|
||||||
|
|
||||||
|
if(!this->privateData->threadData->workerThread)
|
||||||
|
return OYSTER_THREAD_ERROR_FAILED;
|
||||||
|
|
||||||
|
if(start)
|
||||||
|
{
|
||||||
|
this->privateData->threadData->state = OYSTER_THREAD_STATE_RUNNING;
|
||||||
|
}
|
||||||
|
return OYSTER_THREAD_ERROR_SUCCESS;
|
||||||
|
}
|
||||||
|
OYSTER_THREAD_ERROR OysterThread::Start()
|
||||||
|
{
|
||||||
|
if(!this->privateData->threadData->owner)
|
||||||
|
return OYSTER_THREAD_ERROR_FAILED;
|
||||||
|
if(!this->privateData->threadData->workerThread)
|
||||||
|
return OYSTER_THREAD_ERROR_FAILED;
|
||||||
|
if(this->privateData->threadData->state == OYSTER_THREAD_STATE_DEAD)
|
||||||
|
return OYSTER_THREAD_ERROR_FAILED;
|
||||||
|
|
||||||
|
this->privateData->threadData->state = OYSTER_THREAD_STATE_RUNNING;
|
||||||
|
return OYSTER_THREAD_ERROR_SUCCESS;
|
||||||
|
}
|
||||||
|
void OysterThread::Stop()
|
||||||
|
{
|
||||||
|
//this->privateData->threadData->mutexLock.LockMutex();
|
||||||
|
this->privateData->threadData->state = OYSTER_THREAD_STATE_STOPED;
|
||||||
|
//this->privateData->threadData->mutexLock.UnlockMutex();
|
||||||
|
}
|
||||||
|
void OysterThread::Pause()
|
||||||
|
{
|
||||||
|
//this->privateData->threadData->mutexLock.LockMutex();
|
||||||
|
this->privateData->threadData->state = OYSTER_THREAD_STATE_PAUSED;
|
||||||
|
//this->privateData->threadData->mutexLock.UnlockMutex();
|
||||||
|
}
|
||||||
|
void OysterThread::Pause(int msec)
|
||||||
|
{
|
||||||
|
|
||||||
|
if(std::this_thread::get_id() == this->privateData->threadData->workerThread->get_id())
|
||||||
|
{
|
||||||
|
this->privateData->threadData->msec = msec;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//this->privateData->threadData->mutexLock.LockMutex();
|
||||||
|
this->privateData->threadData->state = OYSTER_THREAD_STATE_PAUSED;
|
||||||
|
this->privateData->threadData->msec = msec;
|
||||||
|
//this->privateData->threadData->mutexLock.UnlockMutex();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void OysterThread::Resume()
|
||||||
|
{
|
||||||
|
// this->privateData->threadData->mutexLock.LockMutex();
|
||||||
|
this->privateData->threadData->state = OYSTER_THREAD_STATE_RUNNING;
|
||||||
|
// this->privateData->threadData->mutexLock.UnlockMutex();
|
||||||
|
}
|
||||||
|
OYSTER_THREAD_ERROR OysterThread::Reset(IThreadObject* worker)
|
||||||
|
{
|
||||||
|
// this->privateData->threadData->mutexLock.LockMutex();
|
||||||
|
if(worker)
|
||||||
|
{
|
||||||
|
this->privateData->threadData->owner = worker;
|
||||||
|
}
|
||||||
|
this->privateData->threadData->callingThread = std::this_thread::get_id();
|
||||||
|
this->privateData->threadData->msec = 0;
|
||||||
|
// this->privateData->threadData->mutexLock.UnlockMutex();
|
||||||
|
|
||||||
|
return OYSTER_THREAD_ERROR_SUCCESS;
|
||||||
|
}
|
||||||
|
void OysterThread::Terminate()
|
||||||
|
{
|
||||||
|
this->privateData->threadData->state = OYSTER_THREAD_STATE_DEAD;
|
||||||
|
}
|
||||||
|
void OysterThread::Wait()
|
||||||
|
{
|
||||||
|
if(this->privateData->threadData->state == OYSTER_THREAD_STATE_DEAD)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(this->privateData->threadData->workerThread->get_id() == std::this_thread::get_id()) return;
|
||||||
|
|
||||||
|
this->privateData->threadData->workerThread->join();
|
||||||
|
}
|
||||||
|
void OysterThread::Wait(int msec)
|
||||||
|
{
|
||||||
|
if(this->privateData->threadData->workerThread->get_id() == std::this_thread::get_id()) return;
|
||||||
|
|
||||||
|
std::this_thread::sleep_for(std::chrono::milliseconds(msec));
|
||||||
|
}
|
||||||
|
OYSTER_THREAD_ERROR OysterThread::Swap(const OysterThread* other)
|
||||||
|
{
|
||||||
|
this->privateData->threadData->workerThread->swap(*other->privateData->threadData->workerThread);
|
||||||
|
return OYSTER_THREAD_ERROR_SUCCESS;
|
||||||
|
}
|
||||||
|
bool OysterThread::IsActive()
|
||||||
|
{
|
||||||
|
if (this->privateData->threadData->state == OYSTER_THREAD_STATE_RUNNING)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,315 @@
|
||||||
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
// Inline and template implementations for
|
||||||
|
// the Utility Collection of Miscellanious Handy Functions
|
||||||
|
// © Dan Andersson 2013
|
||||||
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#ifndef UTILITIES_INLINE_IMPL_H
|
||||||
|
#define UTILITIES_INLINE_IMPL_H
|
||||||
|
|
||||||
|
#include "Utilities.h"
|
||||||
|
|
||||||
|
namespace Utility
|
||||||
|
{
|
||||||
|
namespace DynamicMemory
|
||||||
|
{
|
||||||
|
template<typename Type>
|
||||||
|
inline void SafeDeleteInstance( Type *dynamicInstance )
|
||||||
|
{
|
||||||
|
if( dynamicInstance )
|
||||||
|
{
|
||||||
|
delete dynamicInstance;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Type>
|
||||||
|
void SafeDeleteArray( Type dynamicArray[] )
|
||||||
|
{
|
||||||
|
if( dynamicArray )
|
||||||
|
{
|
||||||
|
delete [] dynamicArray;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Type>
|
||||||
|
UniquePointer<Type>::UniquePointer( Type *assignedInstance )
|
||||||
|
{
|
||||||
|
this->ownedInstance = assignedInstance;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Type>
|
||||||
|
UniquePointer<Type>::UniquePointer( const UniquePointer<Type> &donor )
|
||||||
|
{
|
||||||
|
this->ownedInstance = donor.ownedInstance;
|
||||||
|
donor.ownedInstance = NULL;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Type>
|
||||||
|
UniquePointer<Type>::~UniquePointer()
|
||||||
|
{
|
||||||
|
SafeDeleteInstance( this->ownedInstance );
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Type>
|
||||||
|
UniquePointer<Type> & UniquePointer<Type>::operator = ( Type *assignedInstance )
|
||||||
|
{
|
||||||
|
SafeDeleteInstance( this->ownedInstance );
|
||||||
|
this->ownedInstance = assignedInstance;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Type>
|
||||||
|
UniquePointer<Type> & UniquePointer<Type>::operator = ( const UniquePointer<Type> &donor )
|
||||||
|
{
|
||||||
|
SafeDeleteInstance( this->ownedInstance );
|
||||||
|
this->ownedInstance = donor.ownedInstance;
|
||||||
|
donor.ownedInstance = NULL;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Type>
|
||||||
|
UniquePointer<Type>::operator Type* ()
|
||||||
|
{
|
||||||
|
return this->ownedInstance;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Type>
|
||||||
|
UniquePointer<Type>::operator const Type* () const
|
||||||
|
{
|
||||||
|
return this->ownedInstance;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Type>
|
||||||
|
Type * UniquePointer<Type>::operator -> ()
|
||||||
|
{
|
||||||
|
return this->ownedInstance;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Type>
|
||||||
|
const Type * UniquePointer<Type>::operator -> () const
|
||||||
|
{
|
||||||
|
return this->ownedInstance;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Type>
|
||||||
|
UniquePointer<Type>::operator bool() const
|
||||||
|
{
|
||||||
|
return this->ownedInstance != NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Type>
|
||||||
|
bool UniquePointer<Type>::operator == ( Type *stray ) const
|
||||||
|
{
|
||||||
|
return this->ownedInstance == stray;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Type>
|
||||||
|
bool UniquePointer<Type>::operator != ( Type *stray ) const
|
||||||
|
{
|
||||||
|
return this->ownedInstance != stray;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Type>
|
||||||
|
Type* UniquePointer<Type>::Release()
|
||||||
|
{
|
||||||
|
Type *copy = this->ownedInstance;
|
||||||
|
this->ownedInstance = NULL;
|
||||||
|
return copy;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Type>
|
||||||
|
inline bool UniquePointer<Type>::HaveOwnership() const
|
||||||
|
{
|
||||||
|
return this->operator bool();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Type>
|
||||||
|
UniqueArray<Type>::UniqueArray( Type assignedArray[] )
|
||||||
|
{
|
||||||
|
this->ownedArray = assignedArray;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Type>
|
||||||
|
UniqueArray<Type>::UniqueArray( const UniqueArray<Type> &donor )
|
||||||
|
{
|
||||||
|
this->ownedArray = donor.ownedArray;
|
||||||
|
donor.ownedArray = NULL;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Type>
|
||||||
|
UniqueArray<Type>::~UniqueArray()
|
||||||
|
{
|
||||||
|
SafeDeleteArray( this->ownedArray );
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Type>
|
||||||
|
UniqueArray<Type> & UniqueArray<Type>::operator = ( Type assignedArray[] )
|
||||||
|
{
|
||||||
|
SafeDeleteArray( this->ownedArray );
|
||||||
|
this->ownedArray = assignedArray;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Type>
|
||||||
|
UniqueArray<Type> & UniqueArray<Type>::operator = ( const UniqueArray<Type> &donor )
|
||||||
|
{
|
||||||
|
SafeDeleteArray( this->ownedArray );
|
||||||
|
this->ownedArray = donor.ownedInstance;
|
||||||
|
donor.owned = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Type> template<typename Index>
|
||||||
|
Type & UniqueArray<Type>::operator [] ( Index i )
|
||||||
|
{
|
||||||
|
return this->ownedArray[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Type> template<typename Index>
|
||||||
|
const Type & UniqueArray<Type>::operator [] ( Index i ) const
|
||||||
|
{
|
||||||
|
return this->ownedArray[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Type>
|
||||||
|
UniqueArray<Type>::operator bool () const
|
||||||
|
{
|
||||||
|
return this->ownedArray != NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Type>
|
||||||
|
bool UniqueArray<Type>::operator == ( Type *stray ) const
|
||||||
|
{
|
||||||
|
return this->ownedArray == stray;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Type>
|
||||||
|
bool UniqueArray<Type>::operator != ( Type *stray ) const
|
||||||
|
{
|
||||||
|
return this->ownedArray != stray;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Type>
|
||||||
|
Type* UniqueArray<Type>::Release()
|
||||||
|
{
|
||||||
|
Type *copy = this->ownedArray;
|
||||||
|
this->ownedArray = NULL;
|
||||||
|
return copy;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Type>
|
||||||
|
inline bool UniqueArray<Type>::HaveOwnership() const
|
||||||
|
{
|
||||||
|
return this->operator bool();
|
||||||
|
}
|
||||||
|
<<<<<<< HEAD
|
||||||
|
=======
|
||||||
|
|
||||||
|
namespace SmartPointer
|
||||||
|
{
|
||||||
|
template<typename T> void StdSmartPointer<T>::Destroy()
|
||||||
|
{
|
||||||
|
delete this->_rc;
|
||||||
|
this->_rc = NULL;
|
||||||
|
delete this->_ptr;
|
||||||
|
this->_ptr = NULL;
|
||||||
|
}
|
||||||
|
template<typename T> StdSmartPointer<T>::StdSmartPointer()
|
||||||
|
:_rc(0), _ptr(0)
|
||||||
|
{ }
|
||||||
|
template<typename T> StdSmartPointer<T>::StdSmartPointer(T* p)
|
||||||
|
:_ptr(p)
|
||||||
|
{
|
||||||
|
this->_rc = new ReferenceCount();
|
||||||
|
this->_rc->Incref();
|
||||||
|
}
|
||||||
|
template<typename T> StdSmartPointer<T>::StdSmartPointer(const StdSmartPointer& d)
|
||||||
|
:_ptr(d._ptr), _rc(d._rc)
|
||||||
|
{
|
||||||
|
if(this->_rc)
|
||||||
|
this->_rc->Incref();
|
||||||
|
}
|
||||||
|
template<typename T> StdSmartPointer<T>::~StdSmartPointer()
|
||||||
|
{
|
||||||
|
if (this->_rc && this->_rc->Decref() == 0)
|
||||||
|
{
|
||||||
|
Destroy();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
template<typename T> StdSmartPointer<T>& StdSmartPointer<T>::operator= (const StdSmartPointer<T>& p)
|
||||||
|
{
|
||||||
|
if (this != &p)
|
||||||
|
{
|
||||||
|
//Last to go?
|
||||||
|
if(this->_rc && this->_rc->Decref() == 0)
|
||||||
|
{
|
||||||
|
//Call child specific
|
||||||
|
Destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
this->_ptr = p._ptr;
|
||||||
|
this->_rc = p._rc;
|
||||||
|
this->_rc->Incref();
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
template<typename T> StdSmartPointer<T>& StdSmartPointer<T>::operator= (T* p)
|
||||||
|
{
|
||||||
|
if (this->_ptr != p)
|
||||||
|
{
|
||||||
|
//Last to go?
|
||||||
|
if(this->_rc)
|
||||||
|
{
|
||||||
|
if(this->_rc->Decref() == 0)
|
||||||
|
{
|
||||||
|
//Call child specific
|
||||||
|
Destroy();
|
||||||
|
this->_rc = new ReferenceCount();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
this->_rc = new ReferenceCount();
|
||||||
|
|
||||||
|
this->_ptr = p;
|
||||||
|
this->_rc->Incref();
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
template<typename T> inline bool StdSmartPointer<T>::operator== (const StdSmartPointer<T>& d)
|
||||||
|
{
|
||||||
|
return d._ptr == this->_ptr;
|
||||||
|
}
|
||||||
|
template<typename T> inline bool StdSmartPointer<T>::operator== (const T& p)
|
||||||
|
{
|
||||||
|
return &p == this->_ptr;
|
||||||
|
}
|
||||||
|
template<typename T> inline T& StdSmartPointer<T>::operator* ()
|
||||||
|
{
|
||||||
|
return *this->_ptr;
|
||||||
|
}
|
||||||
|
template<typename T> inline T* StdSmartPointer<T>::operator-> ()
|
||||||
|
{
|
||||||
|
return this->_ptr;
|
||||||
|
}
|
||||||
|
template<typename T> inline StdSmartPointer<T>::operator T* ()
|
||||||
|
{
|
||||||
|
return this->_ptr;
|
||||||
|
}
|
||||||
|
template<typename T> inline StdSmartPointer<T>::operator bool()
|
||||||
|
{
|
||||||
|
return (this->_ptr != 0);
|
||||||
|
}
|
||||||
|
template<typename T> inline T* StdSmartPointer<T>::Get()
|
||||||
|
{
|
||||||
|
return this->_ptr;
|
||||||
|
}
|
||||||
|
template<typename T> inline bool StdSmartPointer<T>::IsValid()
|
||||||
|
{
|
||||||
|
return (this->_ptr != NULL) ? true : false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
>>>>>>> origin/MiscBranch
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,347 @@
|
||||||
|
//!//!//!//!//!//!//!//!//!//!//!//!//!//!//!//!//!//!//!//!//!//!//!
|
||||||
|
// Utility Collection of Miscellanious Handy Functions
|
||||||
|
// © Dan Andersson 2013
|
||||||
|
//!//!//!//!//!//!//!//!//!//!//!//!//!//!//!//!//!//!//!//!//!//!//!
|
||||||
|
|
||||||
|
#ifndef UTILITIES_H
|
||||||
|
#define UTILITIES_H
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <istream>
|
||||||
|
#include <vector>
|
||||||
|
#include <locale>
|
||||||
|
#include <limits>
|
||||||
|
#include <atomic>
|
||||||
|
|
||||||
|
namespace Utility
|
||||||
|
{
|
||||||
|
namespace DynamicMemory
|
||||||
|
{
|
||||||
|
//! If dynamicInstance is not NULL, then delete
|
||||||
|
template<typename Type> void SafeDeleteInstance( Type *dynamicInstance );
|
||||||
|
|
||||||
|
//! If dynamicArray is not NULL, then delete []
|
||||||
|
template<typename Type> void SafeDeleteArray( Type dynamicArray[] );
|
||||||
|
|
||||||
|
//! Wrapper to safely transfer dynamic ownership/responsibility
|
||||||
|
template<typename Type> struct UniquePointer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
//! Assigns assignedInstance ownership to this UniquePonter, old owned instance will be deleted.
|
||||||
|
//! If NULL is assigned is equivalent with clearing all responsibilities from this UniquePointer.
|
||||||
|
UniquePointer( Type *assignedInstance = NULL );
|
||||||
|
|
||||||
|
//! Transfers assignedInstance ownership from donor to this UniquePonter, old owned instance will be deleted.
|
||||||
|
//! If donor had nothing, is equivalent with clearing all responsibilities from this UniquePointer.
|
||||||
|
UniquePointer( const UniquePointer<Type> &donor );
|
||||||
|
|
||||||
|
//! Will auto delete assigned dynamic instance.
|
||||||
|
~UniquePointer();
|
||||||
|
|
||||||
|
//! Assigns assignedInstance ownership to this UniquePonter, old owned instance will be deleted.
|
||||||
|
//! If NULL is assigned is equivalent with clearing all responsibilities from this UniquePointer.
|
||||||
|
UniquePointer<Type> & operator = ( Type *assignedInstance );
|
||||||
|
|
||||||
|
//! Transfers assignedInstance ownership from donor to this UniquePonter, old owned instance will be deleted.
|
||||||
|
//! If donor had nothing, is equivalent with clearing all responsibilities from this UniquePointer.
|
||||||
|
UniquePointer<Type> & operator = ( const UniquePointer<Type> &donor );
|
||||||
|
|
||||||
|
//! Access the assigned dynamic instance. Will crash if nothing there
|
||||||
|
operator Type* ();
|
||||||
|
|
||||||
|
//! Access the assigned dynamic instance. Will crash if nothing there
|
||||||
|
operator const Type* () const;
|
||||||
|
|
||||||
|
//! Access members of the assigned dynamic instance. Will crash if nothing there
|
||||||
|
Type * operator -> ();
|
||||||
|
|
||||||
|
//! Access members of the assigned dynamic instance. Will crash if nothing there
|
||||||
|
const Type * operator -> () const;
|
||||||
|
|
||||||
|
//! If true, this UniquePointer have a current ownership/responsibility of a dynamic instance.
|
||||||
|
operator bool () const;
|
||||||
|
|
||||||
|
//! @return true if this ownedInstance matches with stray
|
||||||
|
bool operator == ( Type *stray ) const;
|
||||||
|
|
||||||
|
//! @return false if this ownedInstance matches with stray
|
||||||
|
bool operator != ( Type *stray ) const;
|
||||||
|
|
||||||
|
//! This UniquePointer drops all claims of ownership/responsibility and returns the dynamic instance. Now it is your responsibility to delete.
|
||||||
|
Type* Release();
|
||||||
|
|
||||||
|
//! (inline) If true, this UniquePointer have a current ownership/responsibility of a dynamic instance.
|
||||||
|
bool HaveOwnership() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
mutable Type *ownedInstance;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename Type>
|
||||||
|
struct UniqueArray
|
||||||
|
{ //! Wrapper to safely transfer dynamic ownership/responsibility
|
||||||
|
public:
|
||||||
|
//! Assigns assignedInstance ownership to this UniquePonter, old owned array will be deleted.
|
||||||
|
//! If NULL is assigned is equivalent with clearing all responsibilities from this UniqueArray.
|
||||||
|
UniqueArray( Type assignedArray[] = NULL );
|
||||||
|
|
||||||
|
//! Transfers assignedInstance ownership from donor to this UniquePonter, old owned array will be deleted.
|
||||||
|
//! If donor had nothing, is equivalent with clearing all responsibilities from this UniqueArray.
|
||||||
|
UniqueArray( const UniqueArray<Type> &donor );
|
||||||
|
|
||||||
|
//! Will auto delete assigned dynamic array.
|
||||||
|
~UniqueArray();
|
||||||
|
|
||||||
|
//! Assigns assignedInstance ownership to this UniquePonter, old owned array will be deleted.
|
||||||
|
//! If NULL is assigned is equivalent with clearing all responsibilities from this UniqueArray.
|
||||||
|
UniqueArray<Type> & operator = ( Type assignedArray[] );
|
||||||
|
|
||||||
|
//! Transfers assignedInstance ownership from donor to this UniquePonter, old owned array will be deleted.
|
||||||
|
//! If donor had nothing, is equivalent with clearing all responsibilities from this UniqueArray.
|
||||||
|
UniqueArray<Type> & operator = ( const UniqueArray<Type> &donor );
|
||||||
|
|
||||||
|
//! Accesses the instance at index i of this UniqeArray's owned dynamic array.
|
||||||
|
//! Will crash if out-of-bound or there is no assigned array.
|
||||||
|
template<typename Index> Type & operator [] ( Index i );
|
||||||
|
|
||||||
|
//! Accesses the instance at index i of this UniqeArray's owned dynamic array.
|
||||||
|
//! Will crash if out-of-bound or there is no assigned array.
|
||||||
|
template<typename Index> const Type & operator [] ( Index i ) const;
|
||||||
|
|
||||||
|
//! If true, this UniqueArray have a current ownership/responsibility of a dynamic instance.
|
||||||
|
operator bool () const;
|
||||||
|
|
||||||
|
//! @return true if this ownedInstance matches with stray
|
||||||
|
bool operator == ( Type *stray ) const;
|
||||||
|
|
||||||
|
//! @return false if this ownedInstance matches with stray
|
||||||
|
bool operator != ( Type *stray ) const;
|
||||||
|
|
||||||
|
//! This UniqueArray drops all claims of ownership/responsibility and returns the dynamic array. Now it is your responsibility to delete.
|
||||||
|
Type* Release();
|
||||||
|
|
||||||
|
//! (inline) If true, this UniqueArray have a current ownership/responsibility of a dynamic array.
|
||||||
|
bool HaveOwnership() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
mutable Type *ownedArray;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct RefCount
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
std::atomic<int> count;
|
||||||
|
|
||||||
|
public:
|
||||||
|
<<<<<<< HEAD
|
||||||
|
RefCount() :count(0) { }
|
||||||
|
RefCount(const RefCount& o) { count = o.count; }
|
||||||
|
const RefCount& operator=(const RefCount& o) { count = o.count; return *this;}
|
||||||
|
void Incref() { this->count++; }
|
||||||
|
void Incref(int c) { this->count += c; }
|
||||||
|
int Decref() { return --this->count;}
|
||||||
|
void Reset() { this->count = 0; }
|
||||||
|
};
|
||||||
|
=======
|
||||||
|
ReferenceCount() :count(0) { }
|
||||||
|
ReferenceCount(const ReferenceCount& o) { count.store(o.count); }
|
||||||
|
inline const ReferenceCount& operator=(const ReferenceCount& o) { count.store(o.count); return *this;}
|
||||||
|
inline void Incref() { this->count++; }
|
||||||
|
inline void Incref(int c) { this->count += c; }
|
||||||
|
inline int Decref() { return --this->count;}
|
||||||
|
inline void Reset() { this->count = 0; }
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace SmartPointer
|
||||||
|
{
|
||||||
|
//! Smart pointer for a regular object.
|
||||||
|
/**
|
||||||
|
* Regular objects, objects that is deleted normaly (ie not COM objects, or array pointers)
|
||||||
|
* can use this class to easy the use of dynamic memory
|
||||||
|
*/
|
||||||
|
template<typename T>
|
||||||
|
struct StdSmartPointer
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
ReferenceCount *_rc;
|
||||||
|
T *_ptr;
|
||||||
|
|
||||||
|
/** Destroys the pointer and returns the memory allocated. */
|
||||||
|
void Destroy();
|
||||||
|
|
||||||
|
public:
|
||||||
|
StdSmartPointer();
|
||||||
|
StdSmartPointer(T* p);
|
||||||
|
StdSmartPointer(const StdSmartPointer& d);
|
||||||
|
virtual~StdSmartPointer();
|
||||||
|
StdSmartPointer<T>& operator= (const StdSmartPointer<T>& p);
|
||||||
|
StdSmartPointer<T>& operator= (T* p);
|
||||||
|
bool operator== (const StdSmartPointer<T>& d);
|
||||||
|
bool operator== (const T& p);
|
||||||
|
T& operator* ();
|
||||||
|
T* operator-> ();
|
||||||
|
operator T* ();
|
||||||
|
operator bool();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the connected pointer */
|
||||||
|
T* Get();
|
||||||
|
|
||||||
|
/** Checks if the pointer is valid (not NULL)
|
||||||
|
Returns true for valid, else false. */
|
||||||
|
bool IsValid();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
>>>>>>> origin/MiscBranch
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace String
|
||||||
|
{
|
||||||
|
// string
|
||||||
|
|
||||||
|
::std::vector<::std::string> & Split( ::std::vector<::std::string> &output, const ::std::string &str, char delim, ::std::string::size_type offset = 0 );
|
||||||
|
::std::vector<::std::string> & Split( ::std::vector<::std::string> &output, const ::std::string &str, const ::std::string &delim, ::std::string::size_type offset = 0 );
|
||||||
|
::std::vector<::std::string> & Split( ::std::vector<::std::string> &output, const ::std::string &str, const ::std::vector<::std::string> &delim, ::std::string::size_type offset = 0 );
|
||||||
|
::std::string Trim( const ::std::string &str );
|
||||||
|
::std::string & ToLowerCase( ::std::string &output, const ::std::string &str );
|
||||||
|
::std::string & ToLowerCase( ::std::string &str );
|
||||||
|
::std::string & ToUpperCase( ::std::string &output, const ::std::string &str );
|
||||||
|
::std::string & ToUpperCase( ::std::string &str );
|
||||||
|
::std::string & ExtractDirPath( ::std::string &output, const ::std::string &file, char dirDelimeter );
|
||||||
|
::std::string & ExtractDirPath( ::std::string &output, const ::std::string &file, const ::std::string &dirDelimeter );
|
||||||
|
::std::string & ReplaceCharacters( ::std::string &str, char characterToReplace, char newCharacter, const ::std::string::size_type &offset = 0, const ::std::string::size_type &end = ::std::string::npos );
|
||||||
|
|
||||||
|
// wstring
|
||||||
|
|
||||||
|
::std::vector<::std::wstring> & Split( ::std::vector<::std::wstring> &output, const ::std::wstring &str, char delim, ::std::wstring::size_type offset = 0 );
|
||||||
|
::std::vector<::std::wstring> & Split( ::std::vector<::std::wstring> &output, const ::std::wstring &str, const ::std::wstring &delim, ::std::wstring::size_type offset = 0 );
|
||||||
|
::std::vector<::std::wstring> & Split( ::std::vector<::std::wstring> &output, const ::std::wstring &str, const ::std::vector<::std::wstring> &delim, ::std::wstring::size_type offset = 0 );
|
||||||
|
::std::wstring & wToLowerCase( ::std::wstring &output, const ::std::wstring &str );
|
||||||
|
::std::wstring & wToLowerCase( ::std::wstring &str );
|
||||||
|
|
||||||
|
//To wstring
|
||||||
|
|
||||||
|
::std::wstring & StringToWstring( const ::std::string &str, ::std::wstring &wstr );
|
||||||
|
::std::string & WStringToString( const ::std::wstring &wstr, ::std::string &str );
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace Stream
|
||||||
|
{
|
||||||
|
float* ReadFloats( float *output, ::std::istream &input, unsigned int numFloats );
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace StaticArray
|
||||||
|
{
|
||||||
|
template<typename ScalarType, unsigned int num>
|
||||||
|
inline unsigned int NumElementsOf( const ScalarType(&)[num] )
|
||||||
|
{ return num; }
|
||||||
|
|
||||||
|
template<typename ScalarType, unsigned int num>
|
||||||
|
inline ScalarType & FirstElementOf( ScalarType (&arr)[num] )
|
||||||
|
{ return arr[0]; }
|
||||||
|
|
||||||
|
template<typename ScalarType, unsigned int num>
|
||||||
|
inline ScalarType & LastElementOf( ScalarType (&arr)[num] )
|
||||||
|
{ return arr[num-1]; }
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace Element
|
||||||
|
{
|
||||||
|
template<typename ScalarType>
|
||||||
|
inline void Swap( ScalarType &elementA, ScalarType &elementB, ScalarType &swapSpace )
|
||||||
|
{ swapSpace = elementA; elementA = elementB; elementB = swapSpace; }
|
||||||
|
|
||||||
|
template<typename ScalarType>
|
||||||
|
inline void Swap( ScalarType &elementA, ScalarType &elementB )
|
||||||
|
{ ScalarType swapSpace; Swap( elementA, elementB, swapSpace ); }
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace Value
|
||||||
|
{
|
||||||
|
using ::std::numeric_limits;
|
||||||
|
|
||||||
|
template<typename ValueType>
|
||||||
|
inline ValueType Abs( const ValueType &value )
|
||||||
|
{ return value < 0 ? value * -1 : value; }
|
||||||
|
|
||||||
|
template<typename ValueType>
|
||||||
|
inline ValueType Max( const ValueType &valueA, const ValueType &valueB )
|
||||||
|
{ return valueA > valueB ? valueA : valueB; }
|
||||||
|
|
||||||
|
template<typename ValueType>
|
||||||
|
inline ValueType Min( const ValueType &valueA, const ValueType &valueB )
|
||||||
|
{ return valueA < valueB ? valueA : valueB; }
|
||||||
|
|
||||||
|
template<typename ValueType>
|
||||||
|
inline ValueType Average( const ValueType &valueA, const ValueType &valueB )
|
||||||
|
{ return (valueA + valueB) * 0.5f; }
|
||||||
|
|
||||||
|
template<typename ValueType>
|
||||||
|
inline ValueType AverageWithDelta( const ValueType &origin, const ValueType &delta )
|
||||||
|
{ return origin + (delta * 0.5f); }
|
||||||
|
|
||||||
|
template<typename ValueType>
|
||||||
|
inline ValueType Radian( const ValueType °ree )
|
||||||
|
{ return degree * (3.1415926535897932384626433832795f / 180.0f); }
|
||||||
|
|
||||||
|
template<typename ValueType>
|
||||||
|
inline ValueType Degree( const ValueType &radian )
|
||||||
|
{ return radian * (180.0f / 3.1415926535897932384626433832795f); }
|
||||||
|
|
||||||
|
// SPECIALIZATIONS //!//!//!//!//!//!//!//!//!//!//!//!//!//!
|
||||||
|
|
||||||
|
template<> inline char Average<char>( const char &valueA, const char &valueB )
|
||||||
|
{ return (valueA + valueB) >> 1; }
|
||||||
|
|
||||||
|
template<> inline unsigned char Average<unsigned char>( const unsigned char &valueA, const unsigned char &valueB )
|
||||||
|
{ return (valueA + valueB) >> 1; }
|
||||||
|
|
||||||
|
template<> inline int Average<int>( const int &valueA, const int &valueB )
|
||||||
|
{ return (valueA + valueB) >> 1; }
|
||||||
|
|
||||||
|
template<> inline unsigned int Average<unsigned int>( const unsigned int &valueA, const unsigned int &valueB )
|
||||||
|
{ return (valueA + valueB) >> 1; }
|
||||||
|
|
||||||
|
template<> inline long Average<long>( const long &valueA, const long &valueB )
|
||||||
|
{ return (valueA + valueB) >> 1; }
|
||||||
|
|
||||||
|
template<> inline unsigned long Average<unsigned long>( const unsigned long &valueA, const unsigned long &valueB )
|
||||||
|
{ return (valueA + valueB) >> 1; }
|
||||||
|
|
||||||
|
template<> inline long long Average<long long>( const long long &valueA, const long long &valueB )
|
||||||
|
{ return (valueA + valueB) >> 1; }
|
||||||
|
|
||||||
|
template<> inline unsigned long long Average<unsigned long long>( const unsigned long long &valueA, const unsigned long long &valueB )
|
||||||
|
{ return (valueA + valueB) >> 1; }
|
||||||
|
|
||||||
|
template<> inline char AverageWithDelta<char>( const char &origin, const char &delta )
|
||||||
|
{ return origin + (delta >> 1); }
|
||||||
|
|
||||||
|
template<> inline unsigned char AverageWithDelta<unsigned char>( const unsigned char &origin, const unsigned char &delta )
|
||||||
|
{ return origin + (delta >> 1); }
|
||||||
|
|
||||||
|
template<> inline int AverageWithDelta<int>( const int &origin, const int &delta )
|
||||||
|
{ return origin + (delta >> 1); }
|
||||||
|
|
||||||
|
template<> inline unsigned int AverageWithDelta<unsigned int>( const unsigned int &origin, const unsigned int &delta )
|
||||||
|
{ return origin + (delta >> 1); }
|
||||||
|
|
||||||
|
template<> inline long AverageWithDelta<long>( const long &origin, const long &delta )
|
||||||
|
{ return origin + (delta >> 1); }
|
||||||
|
|
||||||
|
template<> inline unsigned long AverageWithDelta<unsigned long>( const unsigned long &origin, const unsigned long &delta )
|
||||||
|
{ return origin + (delta >> 1); }
|
||||||
|
|
||||||
|
template<> inline long long AverageWithDelta<long long>( const long long &origin, const long long &delta )
|
||||||
|
{ return origin + (delta >> 1); }
|
||||||
|
|
||||||
|
template<> inline unsigned long long AverageWithDelta<unsigned long long>( const unsigned long long &origin, const unsigned long long &delta )
|
||||||
|
{ return origin + (delta >> 1); }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#include "Utilities-InlineImpl.h"
|
||||||
|
|
||||||
|
#endif
|
Loading…
Reference in New Issue