443 lines
8.1 KiB
C++
443 lines
8.1 KiB
C++
/*-------------------------------------------------------------------------
|
|
* drawElements C++ Base Library
|
|
* -----------------------------
|
|
*
|
|
* Copyright 2014 The Android Open Source Project
|
|
*
|
|
* 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
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*
|
|
*//*!
|
|
* \file
|
|
* \brief Shared pointer.
|
|
*//*--------------------------------------------------------------------*/
|
|
|
|
#include "deSharedPtr.hpp"
|
|
#include "deThread.hpp"
|
|
#include "deClock.h"
|
|
|
|
#include <exception>
|
|
|
|
namespace de
|
|
{
|
|
|
|
namespace
|
|
{
|
|
|
|
enum
|
|
{
|
|
THREAD_TEST_TIME = 200*1000
|
|
};
|
|
|
|
class Object
|
|
{
|
|
public:
|
|
Object (bool& exists)
|
|
: m_exists(exists)
|
|
{
|
|
m_exists = true;
|
|
}
|
|
|
|
virtual ~Object (void)
|
|
{
|
|
m_exists = false;
|
|
}
|
|
|
|
private:
|
|
bool& m_exists;
|
|
};
|
|
|
|
class DerivedObject : public Object
|
|
{
|
|
public:
|
|
DerivedObject (bool& exists)
|
|
: Object(exists)
|
|
{
|
|
}
|
|
};
|
|
|
|
class SharedPtrTestThread : public Thread
|
|
{
|
|
public:
|
|
SharedPtrTestThread (const SharedPtr<Object>& ptr, const bool& exists)
|
|
: m_ptr (ptr)
|
|
, m_exists (exists)
|
|
{
|
|
}
|
|
|
|
void run (void)
|
|
{
|
|
deUint64 startTime = deGetMicroseconds();
|
|
deUint64 cnt = 0;
|
|
|
|
for (;; cnt++)
|
|
{
|
|
if (((cnt&(1<<14)) != 0) && (deGetMicroseconds()-startTime >= THREAD_TEST_TIME))
|
|
break;
|
|
|
|
{
|
|
SharedPtr<Object> ptrA(m_ptr);
|
|
{
|
|
SharedPtr<Object> ptrB;
|
|
ptrB = ptrA;
|
|
ptrA = SharedPtr<Object>();
|
|
}
|
|
}
|
|
DE_TEST_ASSERT(m_exists);
|
|
}
|
|
}
|
|
|
|
private:
|
|
SharedPtr<Object> m_ptr;
|
|
const bool& m_exists;
|
|
};
|
|
|
|
class WeakPtrTestThread : public Thread
|
|
{
|
|
public:
|
|
WeakPtrTestThread (const SharedPtr<Object>& ptr, const bool& exists)
|
|
: m_ptr (ptr)
|
|
, m_exists (exists)
|
|
{
|
|
}
|
|
|
|
void run (void)
|
|
{
|
|
deUint64 startTime = deGetMicroseconds();
|
|
deUint64 cnt = 0;
|
|
|
|
for (;; cnt++)
|
|
{
|
|
if (((cnt&(1<<14)) != 0) && (deGetMicroseconds()-startTime >= THREAD_TEST_TIME))
|
|
break;
|
|
|
|
{
|
|
WeakPtr<Object> ptrA(m_ptr);
|
|
{
|
|
WeakPtr<Object> ptrB;
|
|
ptrB = ptrA;
|
|
ptrA = SharedPtr<Object>();
|
|
}
|
|
}
|
|
DE_TEST_ASSERT(m_exists);
|
|
}
|
|
}
|
|
|
|
private:
|
|
SharedPtr<Object> m_ptr;
|
|
const bool& m_exists;
|
|
};
|
|
|
|
SharedPtr<Object> makeObject (bool& exists)
|
|
{
|
|
return SharedPtr<Object>(new Object(exists));
|
|
}
|
|
|
|
struct CustomDeleter
|
|
{
|
|
CustomDeleter (bool* called) : m_called(called) {}
|
|
|
|
void operator() (Object* ptr)
|
|
{
|
|
DE_TEST_ASSERT(!*m_called);
|
|
delete ptr;
|
|
*m_called = true;
|
|
}
|
|
|
|
bool* m_called;
|
|
};
|
|
|
|
} // anonymous
|
|
|
|
void SharedPtr_selfTest (void)
|
|
{
|
|
// Empty pointer test.
|
|
{
|
|
SharedPtr<Object> ptr;
|
|
DE_TEST_ASSERT(ptr.get() == DE_NULL);
|
|
DE_TEST_ASSERT(!ptr);
|
|
}
|
|
|
|
// Empty pointer copy.
|
|
{
|
|
SharedPtr<Object> ptrA;
|
|
SharedPtr<Object> ptrB(ptrA);
|
|
DE_TEST_ASSERT(ptrB.get() == DE_NULL);
|
|
}
|
|
|
|
// Empty pointer assignment.
|
|
{
|
|
SharedPtr<Object> ptrA;
|
|
SharedPtr<Object> ptrB;
|
|
ptrB = ptrA;
|
|
ptrB = *&ptrB;
|
|
}
|
|
|
|
// Basic test.
|
|
{
|
|
bool exists = false;
|
|
{
|
|
SharedPtr<Object> ptr(new Object(exists));
|
|
DE_TEST_ASSERT(exists);
|
|
DE_TEST_ASSERT(ptr.get() != DE_NULL);
|
|
DE_TEST_ASSERT(ptr);
|
|
}
|
|
DE_TEST_ASSERT(!exists);
|
|
}
|
|
|
|
// Exception test.
|
|
{
|
|
bool exists = false;
|
|
try
|
|
{
|
|
SharedPtr<Object> ptr(new Object(exists));
|
|
DE_TEST_ASSERT(exists);
|
|
DE_TEST_ASSERT(ptr.get() != DE_NULL);
|
|
throw std::exception();
|
|
}
|
|
catch (const std::exception&)
|
|
{
|
|
DE_TEST_ASSERT(!exists);
|
|
}
|
|
DE_TEST_ASSERT(!exists);
|
|
}
|
|
|
|
// Expression test.
|
|
{
|
|
bool exists = false;
|
|
bool test = (SharedPtr<Object>(new Object(exists))).get() != DE_NULL && exists;
|
|
DE_TEST_ASSERT(!exists);
|
|
DE_TEST_ASSERT(test);
|
|
}
|
|
|
|
// Assignment test.
|
|
{
|
|
bool exists = false;
|
|
SharedPtr<Object> ptr(new Object(exists));
|
|
DE_TEST_ASSERT(exists);
|
|
ptr = SharedPtr<Object>();
|
|
DE_TEST_ASSERT(!exists);
|
|
}
|
|
|
|
// Self-assignment test.
|
|
{
|
|
bool exists = false;
|
|
{
|
|
SharedPtr<Object> ptr(new Object(exists));
|
|
DE_TEST_ASSERT(exists);
|
|
DE_TEST_ASSERT(ptr.get() != DE_NULL);
|
|
ptr = *&ptr;
|
|
}
|
|
DE_TEST_ASSERT(!exists);
|
|
}
|
|
|
|
// Basic multi-reference via copy ctor.
|
|
{
|
|
bool exists = false;
|
|
{
|
|
SharedPtr<Object> ptrA(new Object(exists));
|
|
DE_TEST_ASSERT(exists);
|
|
{
|
|
SharedPtr<Object> ptrB(ptrA);
|
|
DE_TEST_ASSERT(exists);
|
|
}
|
|
DE_TEST_ASSERT(exists);
|
|
}
|
|
DE_TEST_ASSERT(!exists);
|
|
}
|
|
|
|
// Basic multi-reference via assignment to empty.
|
|
{
|
|
bool exists = false;
|
|
{
|
|
SharedPtr<Object> ptrA(new Object(exists));
|
|
DE_TEST_ASSERT(exists);
|
|
{
|
|
SharedPtr<Object> ptrB;
|
|
ptrB = ptrA;
|
|
DE_TEST_ASSERT(exists);
|
|
}
|
|
DE_TEST_ASSERT(exists);
|
|
}
|
|
DE_TEST_ASSERT(!exists);
|
|
}
|
|
|
|
// Multi-reference via assignment to non-empty.
|
|
{
|
|
bool existsA = false;
|
|
bool existsB = false;
|
|
{
|
|
SharedPtr<Object> ptrA(new Object(existsA));
|
|
DE_TEST_ASSERT(existsA);
|
|
{
|
|
SharedPtr<Object> ptrB(new Object(existsB));
|
|
DE_TEST_ASSERT(existsB);
|
|
ptrA = ptrB;
|
|
DE_TEST_ASSERT(!existsA);
|
|
DE_TEST_ASSERT(existsB);
|
|
}
|
|
DE_TEST_ASSERT(existsB);
|
|
}
|
|
DE_TEST_ASSERT(!existsB);
|
|
}
|
|
|
|
// Return from function.
|
|
{
|
|
bool exists = false;
|
|
{
|
|
SharedPtr<Object> ptr;
|
|
ptr = makeObject(exists);
|
|
DE_TEST_ASSERT(exists);
|
|
}
|
|
DE_TEST_ASSERT(!exists);
|
|
}
|
|
|
|
// Equality comparison.
|
|
{
|
|
bool existsA = false;
|
|
bool existsB = false;
|
|
SharedPtr<Object> ptrA(new Object(existsA));
|
|
SharedPtr<Object> ptrB(new Object(existsB));
|
|
SharedPtr<Object> ptrC(ptrA);
|
|
|
|
DE_TEST_ASSERT(ptrA == ptrA);
|
|
DE_TEST_ASSERT(ptrA != ptrB);
|
|
DE_TEST_ASSERT(ptrA == ptrC);
|
|
DE_TEST_ASSERT(ptrC != ptrB);
|
|
}
|
|
|
|
// Conversion via assignment.
|
|
{
|
|
bool exists = false;
|
|
{
|
|
SharedPtr<Object> basePtr;
|
|
{
|
|
SharedPtr<DerivedObject> derivedPtr(new DerivedObject(exists));
|
|
DE_TEST_ASSERT(exists);
|
|
basePtr = derivedPtr;
|
|
DE_TEST_ASSERT(exists);
|
|
}
|
|
DE_TEST_ASSERT(exists);
|
|
}
|
|
DE_TEST_ASSERT(!exists);
|
|
}
|
|
|
|
// Conversion via copy ctor.
|
|
{
|
|
bool exists = false;
|
|
{
|
|
SharedPtr<DerivedObject> derivedPtr (new DerivedObject(exists));
|
|
SharedPtr<Object> basePtr (derivedPtr);
|
|
DE_TEST_ASSERT(exists);
|
|
derivedPtr = SharedPtr<DerivedObject>();
|
|
DE_TEST_ASSERT(exists);
|
|
}
|
|
DE_TEST_ASSERT(!exists);
|
|
}
|
|
|
|
// Explicit conversion operator.
|
|
{
|
|
bool exists = false;
|
|
{
|
|
SharedPtr<DerivedObject> derivedPtr (new DerivedObject(exists));
|
|
DE_TEST_ASSERT(exists);
|
|
|
|
SharedPtr<Object> basePtr = (SharedPtr<Object>)(derivedPtr);
|
|
derivedPtr = SharedPtr<DerivedObject>();
|
|
DE_TEST_ASSERT(exists);
|
|
}
|
|
DE_TEST_ASSERT(!exists);
|
|
}
|
|
|
|
// Basic weak reference.
|
|
{
|
|
bool exists = false;
|
|
SharedPtr<Object> ptr(new Object(exists));
|
|
DE_TEST_ASSERT(exists);
|
|
|
|
WeakPtr<Object> weakPtr(ptr);
|
|
try
|
|
{
|
|
SharedPtr<Object> newRef(weakPtr);
|
|
DE_TEST_ASSERT(exists);
|
|
}
|
|
catch (const DeadReferenceException&)
|
|
{
|
|
DE_TEST_ASSERT(false);
|
|
}
|
|
|
|
ptr = SharedPtr<Object>();
|
|
DE_TEST_ASSERT(!exists);
|
|
try
|
|
{
|
|
SharedPtr<Object> newRef(weakPtr);
|
|
DE_TEST_ASSERT(false);
|
|
}
|
|
catch (const DeadReferenceException&)
|
|
{
|
|
}
|
|
}
|
|
|
|
// Basic SharedPtr threaded test.
|
|
{
|
|
bool exists = false;
|
|
{
|
|
SharedPtr<Object> ptr(new Object(exists));
|
|
|
|
SharedPtrTestThread threadA(ptr, exists);
|
|
SharedPtrTestThread threadB(ptr, exists);
|
|
|
|
threadA.start();
|
|
threadB.start();
|
|
|
|
threadA.join();
|
|
threadB.join();
|
|
DE_TEST_ASSERT(exists);
|
|
}
|
|
DE_TEST_ASSERT(!exists);
|
|
}
|
|
|
|
// Basic WeakPtr threaded test.
|
|
{
|
|
bool exists = false;
|
|
{
|
|
SharedPtr<Object> ptr(new Object(exists));
|
|
WeakPtrTestThread threadA(ptr, exists);
|
|
WeakPtrTestThread threadB(ptr, exists);
|
|
|
|
threadA.start();
|
|
threadB.start();
|
|
|
|
threadA.join();
|
|
threadB.join();
|
|
DE_TEST_ASSERT(exists);
|
|
}
|
|
DE_TEST_ASSERT(!exists);
|
|
}
|
|
|
|
// Basic custom deleter.
|
|
{
|
|
bool exists = false;
|
|
bool deleterCalled = false;
|
|
{
|
|
SharedPtr<Object> ptr(new Object(exists), CustomDeleter(&deleterCalled));
|
|
DE_TEST_ASSERT(exists);
|
|
DE_TEST_ASSERT(!deleterCalled);
|
|
DE_TEST_ASSERT(ptr.get() != DE_NULL);
|
|
}
|
|
DE_TEST_ASSERT(!exists);
|
|
DE_TEST_ASSERT(deleterCalled);
|
|
}
|
|
}
|
|
|
|
} // de
|