<commit_before>/* Copyright (c) David Cunningham and the Grit Game Engine project 2012
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * 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. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

#include <sleep.h>

#include "gfx/gfx_disk_resource.h"

#include "background_loader.h"
#include "main.h"

#define SYNCHRONISED std::lock_guard<std::recursive_mutex> _scoped_lock(lock)
#define SYNCHRONISED2(bgl) std::lock_guard<std::recursive_mutex> _scoped_lock(bgl->lock)

bool Demand::requestLoad (float dist)
{
        // called by main thread only
        mDist = dist;
        {
                SYNCHRONISED2(bgl);
                if (mInBackgroundQueue) return false;
        }

        if (!incremented) {
                //CVERB << "Incrementing resources: " << resources << std::endl;
                for (unsigned i=0 ; i<resources.size() ; ++i) {
                        // increment all the resource counters so that we know they're in use
                        resources[i]->increment();
                }
                incremented = true;
        }

        // if all the resources are in a loaded state then return true
        if (!loaded()) {
                //CVERB << "Requesting background load: " << resources << std::endl;
                // else get the bgl to do the right thing and return false
                bgl->checkRAMHost();
                bgl->checkRAMGPU();
                bgl->add(this);
        }

        return true;
}

bool Demand::loaded (void)
{
        //CVERB << "Checking if resources are loaded: " << resources << std::endl;
        for (unsigned i=0 ; i<resources.size() ; ++i) {
                if (!resources[i]->isLoaded()) {
                        return false;
                }
        }
        return true;
}

void Demand::immediateLoad (void)
{
        //CVERB << "Immediate load" << std::endl;
        SYNCHRONISED2(bgl);
        if (!incremented) {
                for (unsigned i=0 ; i<resources.size() ; ++i) {
                        resources[i]->increment();
                }
                incremented = true;
        }
        for (unsigned i=0 ; i<resources.size() ; ++i) {
                if (!resources[i]->isLoaded()) resources[i]->load();
        }
}

void Demand::immediateReload (void)
{
        //CVERB << "Immediate load" << std::endl;
        SYNCHRONISED2(bgl);
        for (unsigned i=0 ; i<resources.size() ; ++i) {
                if (resources[i]->isLoaded()) resources[i]->reload();
        }
}

// called by main thread only
void Demand::finishedWith (void)
{
        //CVERB << "No longer need: " << resources << std::endl;

        // we could be called because a grit object is being destroyed (unusual)
        // in which case, the Demand may get destructed pretty soon

        // or we could also be called if the grit object is simply deactivating (hot path)

        // certainly do not bother continuing to load if a load is in progress
        bgl->remove(this);

        // consider putting the resources up for reclamation
        if (incremented) {
                for (unsigned i=0 ; i<resources.size() ; ++i) {
                        resources[i]->decrement();
                }
                incremented = false;
        }
        for (unsigned i=0 ; i<resources.size() ; ++i) {
                bgl->finishedWith(resources[i]);
        }
}

BackgroundLoader::BackgroundLoader (void)
      : mNumBastards(0), mThread(NULL), mCurrent(NULL),
        mQuit(false), mAllowance(0)
{
        SYNCHRONISED;

        mThread = new std::thread((void (*)(BackgroundLoader*))thread_main, const_cast<BackgroundLoader*>(this));
}

BackgroundLoader::~BackgroundLoader (void)
{
        shutdown();
}

void BackgroundLoader::shutdown (void)
{
        if (mQuit) return;
        {
                SYNCHRONISED;
                mQuit = true;
                cVar.notify_one();
        }
        mThread->join();
        handleBastards();
        mDeathRowGPU.clear();
        mDeathRowHost.clear();
        mDemands.clear();
        delete mThread;
}

// called by main thread only
void BackgroundLoader::add (Demand *d)
{
        SYNCHRONISED;
        mDemands.push_back(d);
        d->mInBackgroundQueue = true;
        d->causedError = false;
        cVar.notify_one();
}

// called by main thread only
void BackgroundLoader::remove (Demand *d)
{
        SYNCHRONISED;
        if (!d->mInBackgroundQueue) return;
        mDemands.erase(d);
        //CVERB << "Retracted demand." << std::endl;
        if (mCurrent == d) {
                //CVERB << "making a bastard..." << std::endl;
                mCurrent = NULL;
        }
        d->mInBackgroundQueue = false;
}

void BackgroundLoader::handleBastards (void)
{
        // access volatile field without taking lock first
        // worst case we return early, i.e. will pick up bastards next time
        if (mNumBastards==0) return;
        DiskResources s;
        {
                SYNCHRONISED;
                if (mNumBastards==0) return;
                s = mBastards;
                mBastards.clear();
                mNumBastards = 0;
        }

        for (unsigned i=0 ; i<s.size() ; ++i) {
                finishedWith(s[i]);
        }
}

void BackgroundLoader::thread_main (BackgroundLoader *self)
{
        self->thread_main();
}

void BackgroundLoader::thread_main (void)
{
        //APP_VERBOSE("BackgroundLoader: thread started");
        DiskResources pending;
        bool caused_error = false;
        while (!mQuit) {
                {
                        SYNCHRONISED;
                        if (mCurrent) {
                                // Usual case:
                                // demand was not retracted while we were
                                // processing it
                                mCurrent->mInBackgroundQueue = false;
                                mCurrent->causedError = caused_error;
                                // cache in d to suppress compiler error
                                Demand *d = mCurrent;
                                mDemands.erase(d);
                                mCurrent = NULL;
                        } else {
                                // demand was retracted, and we actually
                                // loaded stuff
                                // (this can also get called before the first wait,
                                // in which case pending is empty)
                                typedef DiskResources::const_iterator DRCI;
                                for (DRCI i=pending.begin(), i_=pending.end() ; i!=i_ ; ++i) {
                                        //CVERB << "Poor bastard: " << (*i)->getName() << " (" << (*i)->getUsers() << ")" << std::endl;
                                        mBastards.push_back(*i);
                                        mNumBastards = mBastards.size();
                                }
                               //asynchronously call sm.finishedWith(resource);
                        }
                        pending.clear();
                        if (mAllowance <= 0 || !nearestDemand(mCurrent)) {
                                cVar.wait(lock);
                                continue;
                        }
                        pending = mCurrent->resources;
                }
                //APP_VERBOSE("BackgroundLoader: loading: "+name);
                caused_error = false;
                for (DiskResources::iterator i=pending.begin(), i_=pending.end() ; i!=i_ ; ++i) {
                        DiskResource *rp = *i;
                        try {
                                if (!rp->isLoaded()) {
                                        rp->load();
                                        mAllowance--;
                                        //CVERB << "Loaded a resource: " << *rp << std::endl;
                                }
                        } catch (Exception &e) {
                                CERR << e << std::endl;
                                caused_error = true;
                        }
                }

                //mysleep(100000);
        }
        //APP_VERBOSE("BackgroundLoader: thread terminated");
}

bool BackgroundLoader::nearestDemand (Demand * volatile &return_demand)
{
        if (mDemands.size() == 0) return false;

        float closest_dist = mDemands[0]->mDist;
        Demand *rd = mDemands[0];

        for (unsigned i=1 ; i<mDemands.size() ; ++i) {

                Demand *d = mDemands[i];

                float this_dist = d->mDist;

                if (this_dist<closest_dist) {
                        closest_dist = this_dist;
                        rd = d;
                }

        }

        return_demand = rd;
        return true;
}

void BackgroundLoader::setAllowance (float m)
{
        SYNCHRONISED;
        mAllowance = std::max(mAllowance+m, m);
        cVar.notify_one();
}

// unloading of resources /////////////////////////////////////////////////////////

void BackgroundLoader::finishedWith (DiskResource *de)
{
        if (mQuit) return;
        if (de->noUsers()) {
                if (de->isGPUResource()) {
                       mDeathRowGPU.push(de);
                } else {
                        mDeathRowHost.push(de);
                }
        }
}

void BackgroundLoader::checkRAMGPU ()
{

        double budget = gfx_gpu_ram_available();

        while (true) {

                double usage = gfx_gpu_ram_used();

                if (usage < budget || mDeathRowGPU.size() == 0) break;

                DiskResource *r = mDeathRowGPU.pop();

                if (r->noUsers() && r->isLoaded()) r->unload();
        }

}

void BackgroundLoader::checkRAMHost ()
{

        double budget = host_ram_available();

        while (true) {

                double usage = host_ram_used();

                if (usage < budget || mDeathRowHost.size() == 0) break;

                DiskResource *r = mDeathRowHost.pop();

                if (r->noUsers() && r->isLoaded()) r->unload();
        }

}

// vim: shiftwidth=8:tabstop=8:expandtab
<commit_msg>First Linux build without Boost.<commit_after>/* Copyright (c) David Cunningham and the Grit Game Engine project 2012
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * 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. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

#include <sleep.h>

#include "gfx/gfx_disk_resource.h"

#include "background_loader.h"
#include "main.h"

#define SYNCHRONISED std::unique_lock<std::recursive_mutex> _scoped_lock(lock)
#define SYNCHRONISED2(bgl) std::unique_lock<std::recursive_mutex> _scoped_lock(bgl->lock)

bool Demand::requestLoad (float dist)
{
        // called by main thread only
        mDist = dist;
        {
                SYNCHRONISED2(bgl);
                if (mInBackgroundQueue) return false;
        }

        if (!incremented) {
                //CVERB << "Incrementing resources: " << resources << std::endl;
                for (unsigned i=0 ; i<resources.size() ; ++i) {
                        // increment all the resource counters so that we know they're in use
                        resources[i]->increment();
                }
                incremented = true;
        }

        // if all the resources are in a loaded state then return true
        if (!loaded()) {
                //CVERB << "Requesting background load: " << resources << std::endl;
                // else get the bgl to do the right thing and return false
                bgl->checkRAMHost();
                bgl->checkRAMGPU();
                bgl->add(this);
        }

        return true;
}

bool Demand::loaded (void)
{
        //CVERB << "Checking if resources are loaded: " << resources << std::endl;
        for (unsigned i=0 ; i<resources.size() ; ++i) {
                if (!resources[i]->isLoaded()) {
                        return false;
                }
        }
        return true;
}

void Demand::immediateLoad (void)
{
        //CVERB << "Immediate load" << std::endl;
        SYNCHRONISED2(bgl);
        if (!incremented) {
                for (unsigned i=0 ; i<resources.size() ; ++i) {
                        resources[i]->increment();
                }
                incremented = true;
        }
        for (unsigned i=0 ; i<resources.size() ; ++i) {
                if (!resources[i]->isLoaded()) resources[i]->load();
        }
}

void Demand::immediateReload (void)
{
        //CVERB << "Immediate load" << std::endl;
        SYNCHRONISED2(bgl);
        for (unsigned i=0 ; i<resources.size() ; ++i) {
                if (resources[i]->isLoaded()) resources[i]->reload();
        }
}

// called by main thread only
void Demand::finishedWith (void)
{
        //CVERB << "No longer need: " << resources << std::endl;

        // we could be called because a grit object is being destroyed (unusual)
        // in which case, the Demand may get destructed pretty soon

        // or we could also be called if the grit object is simply deactivating (hot path)

        // certainly do not bother continuing to load if a load is in progress
        bgl->remove(this);

        // consider putting the resources up for reclamation
        if (incremented) {
                for (unsigned i=0 ; i<resources.size() ; ++i) {
                        resources[i]->decrement();
                }
                incremented = false;
        }
        for (unsigned i=0 ; i<resources.size() ; ++i) {
                bgl->finishedWith(resources[i]);
        }
}

BackgroundLoader::BackgroundLoader (void)
      : mNumBastards(0), mThread(NULL), mCurrent(NULL),
        mQuit(false), mAllowance(0)
{
        SYNCHRONISED;

        mThread = new std::thread((void (*)(BackgroundLoader*))thread_main, const_cast<BackgroundLoader*>(this));
}

BackgroundLoader::~BackgroundLoader (void)
{
        shutdown();
}

void BackgroundLoader::shutdown (void)
{
        if (mQuit) return;
        {
                SYNCHRONISED;
                mQuit = true;
                cVar.notify_one();
        }
        mThread->join();
        handleBastards();
        mDeathRowGPU.clear();
        mDeathRowHost.clear();
        mDemands.clear();
        delete mThread;
}

// called by main thread only
void BackgroundLoader::add (Demand *d)
{
        SYNCHRONISED;
        mDemands.push_back(d);
        d->mInBackgroundQueue = true;
        d->causedError = false;
        cVar.notify_one();
}

// called by main thread only
void BackgroundLoader::remove (Demand *d)
{
        SYNCHRONISED;
        if (!d->mInBackgroundQueue) return;
        mDemands.erase(d);
        //CVERB << "Retracted demand." << std::endl;
        if (mCurrent == d) {
                //CVERB << "making a bastard..." << std::endl;
                mCurrent = NULL;
        }
        d->mInBackgroundQueue = false;
}

void BackgroundLoader::handleBastards (void)
{
        // access volatile field without taking lock first
        // worst case we return early, i.e. will pick up bastards next time
        if (mNumBastards==0) return;
        DiskResources s;
        {
                SYNCHRONISED;
                if (mNumBastards==0) return;
                s = mBastards;
                mBastards.clear();
                mNumBastards = 0;
        }

        for (unsigned i=0 ; i<s.size() ; ++i) {
                finishedWith(s[i]);
        }
}

void BackgroundLoader::thread_main (BackgroundLoader *self)
{
        self->thread_main();
}

void BackgroundLoader::thread_main (void)
{
        //APP_VERBOSE("BackgroundLoader: thread started");
        DiskResources pending;
        bool caused_error = false;
        while (!mQuit) {
                {
                        SYNCHRONISED;
                        if (mCurrent) {
                                // Usual case:
                                // demand was not retracted while we were
                                // processing it
                                mCurrent->mInBackgroundQueue = false;
                                mCurrent->causedError = caused_error;
                                // cache in d to suppress compiler error
                                Demand *d = mCurrent;
                                mDemands.erase(d);
                                mCurrent = NULL;
                        } else {
                                // demand was retracted, and we actually
                                // loaded stuff
                                // (this can also get called before the first wait,
                                // in which case pending is empty)
                                typedef DiskResources::const_iterator DRCI;
                                for (DRCI i=pending.begin(), i_=pending.end() ; i!=i_ ; ++i) {
                                        //CVERB << "Poor bastard: " << (*i)->getName() << " (" << (*i)->getUsers() << ")" << std::endl;
                                        mBastards.push_back(*i);
                                        mNumBastards = mBastards.size();
                                }
                               //asynchronously call sm.finishedWith(resource);
                        }
                        pending.clear();
                        if (mAllowance <= 0 || !nearestDemand(mCurrent)) {
                                cVar.wait(_scoped_lock);
                                continue;
                        }
                        pending = mCurrent->resources;
                }
                //APP_VERBOSE("BackgroundLoader: loading: "+name);
                caused_error = false;
                for (DiskResources::iterator i=pending.begin(), i_=pending.end() ; i!=i_ ; ++i) {
                        DiskResource *rp = *i;
                        try {
                                if (!rp->isLoaded()) {
                                        rp->load();
                                        mAllowance--;
                                        //CVERB << "Loaded a resource: " << *rp << std::endl;
                                }
                        } catch (Exception &e) {
                                CERR << e << std::endl;
                                caused_error = true;
                        }
                }

                //mysleep(100000);
        }
        //APP_VERBOSE("BackgroundLoader: thread terminated");
}

bool BackgroundLoader::nearestDemand (Demand * volatile &return_demand)
{
        if (mDemands.size() == 0) return false;

        float closest_dist = mDemands[0]->mDist;
        Demand *rd = mDemands[0];

        for (unsigned i=1 ; i<mDemands.size() ; ++i) {

                Demand *d = mDemands[i];

                float this_dist = d->mDist;

                if (this_dist<closest_dist) {
                        closest_dist = this_dist;
                        rd = d;
                }

        }

        return_demand = rd;
        return true;
}

void BackgroundLoader::setAllowance (float m)
{
        SYNCHRONISED;
        mAllowance = std::max(mAllowance+m, m);
        cVar.notify_one();
}

// unloading of resources /////////////////////////////////////////////////////////

void BackgroundLoader::finishedWith (DiskResource *de)
{
        if (mQuit) return;
        if (de->noUsers()) {
                if (de->isGPUResource()) {
                       mDeathRowGPU.push(de);
                } else {
                        mDeathRowHost.push(de);
                }
        }
}

void BackgroundLoader::checkRAMGPU ()
{

        double budget = gfx_gpu_ram_available();

        while (true) {

                double usage = gfx_gpu_ram_used();

                if (usage < budget || mDeathRowGPU.size() == 0) break;

                DiskResource *r = mDeathRowGPU.pop();

                if (r->noUsers() && r->isLoaded()) r->unload();
        }

}

void BackgroundLoader::checkRAMHost ()
{

        double budget = host_ram_available();

        while (true) {

                double usage = host_ram_used();

                if (usage < budget || mDeathRowHost.size() == 0) break;

                DiskResource *r = mDeathRowHost.pop();

                if (r->noUsers() && r->isLoaded()) r->unload();
        }

}

// vim: shiftwidth=8:tabstop=8:expandtab
<|endoftext|>


<commit_before>// Copyright 2015-2017 Joy Machine, LLC. All rights reserved.

#include "steelhunters.h"

#include "ObjectPool.h"

#include "DateTime.h"

#include "IPooledObject.h"

// Console variable definition.
static TAutoConsoleVariable< bool > CVarDebugObjectPooling( TEXT( "joy.DebugObjectPooling" ),
	false,
	TEXT( "Verbose output from the object pooling system for debugging." ),
	ECVF_Default );

// Static class definitions.
const int64 UObjectPool::kDefaultPruneStaleSeconds = 60;

uint32 UObjectPool::IDCounter = 0;
uint32 UObjectPool::PoolCount = 0;

//----------------------------------------------------------------------------------------------------
UObjectPool::UObjectPool( const class FObjectInitializer& ObjectInitializer )
: Name( *FString::Printf( TEXT( "Pool-%d" ), PoolCount ) )
, PoolID( PoolCount )
, PoolSizeOptimal( 256 )
, PoolSizeMaximum( 2048 )
, PruneStale( false )
, PruneLastTimestamp( FDateTime::Now( ).ToUnixTimestamp( ) )
, PruneStale_Seconds( kDefaultPruneStaleSeconds )
{
	Pool.Empty( );

	// Set this pool ID.
	PoolID = ++PoolCount;

	{
		const bool debug = CVarDebugObjectPooling.GetValueOnGameThread( );
		if( debug )
		{
			// Just toss out some debug information.
			UE_LOG( SteelHuntersLog, Log, TEXT( "[UObjectPool] Creating new pool (Pool Count: %d)." ), PoolCount );
		}
	}
}

//----------------------------------------------------------------------------------------------------
void UObjectPool::OnObjectReturn( IPooledObject* pObject )
{
	check( pObject != nullptr );

	// Reset the object (pure virtual method, so the logic is reliant on the child class).
	pObject->IsActive = false;
	pObject->Reset( );
}

//----------------------------------------------------------------------------------------------------
void UObjectPool::Prune( )
{
	const int64 currentTime = FDateTime::Now( ).ToUnixTimestamp( );
	int32 prunedObjectCount = Pool.RemoveAll( [&]( TWeakObjectPtr< UObject > pObject ) {
		if( !pObject.IsStale( ) && pObject.IsValid( ) )
		{
			// The object pointer is either stale or no longer valid.
			return false;
		}

		IPooledObject* pPooledObject = dynamic_cast< IPooledObject* >( pObject.Get( ) );
		if( !pPooledObject->GetIsActive( ) && !pPooledObject->Check( ) || ( PruneStale && ( ( currentTime - pPooledObject->LastActiveTimestamp ) > PruneStale_Seconds ) ) )
		{
			// This object is invalid or stale. Remove it.
			if( pPooledObject != nullptr )
			{
				// Just in case any logic in ::Deactivate is necessary, execute that, and then the ::Destroy method.
				pPooledObject->ReturnToPool.Unbind( );

				pPooledObject->DestroyInstance( );
				pPooledObject = nullptr;
			}

			return true;
		}

		return false;
	} );

	{
		const bool debug = CVarDebugObjectPooling.GetValueOnGameThread( );
		if( debug )
		{
			// Log the number of pruned objects.
			UE_LOG( SteelHuntersLog, Log, TEXT( "[UObjectPool] Pool pruning logic completed (Pool: %s, Object Count: %d, Pruned Count: %d." ), *Name.ToString( ), Pool.Num( ), prunedObjectCount );
		}
	}

	PruneLastTimestamp = currentTime;
}

//----------------------------------------------------------------------------------------------------
void UObjectPool::SetName( const FName& PoolName )
{
	// Just set the pool name; doesn't have to be unique.
	Name = GenerateName( PoolName );
}

//----------------------------------------------------------------------------------------------------
FName UObjectPool::GenerateName( const FName& BaseName )
{
	return( *FString::Printf( TEXT( "%s-%d" ), *BaseName.ToString( ), PoolCount ) );
}

//----------------------------------------------------------------------------------------------------
void UObjectPool::Empty( bool SeparateActiveInstances )
{
	const bool debug = CVarDebugObjectPooling.GetValueOnGameThread( );

	// Remove all objects from the pool and destroy them (unless SeparateActiveInstances is true, in which case leave them alone for now).
	int32 destroyedObjectCount = Pool.RemoveAll( [&]( TWeakObjectPtr< UObject > pObject ) {
		IPooledObject* pPooledObject = dynamic_cast< IPooledObject* >( pObject.Get( ) );
		if( !( SeparateActiveInstances && ( pPooledObject != nullptr ) && pPooledObject->GetIsActive( ) ) )
		{
			// Just in case any logic in ::Deactivate is necessary, execute that, and then the ::Destroy method.
			pPooledObject->ReturnToPool.Unbind( );

			pPooledObject->DestroyInstance( );
			pPooledObject = nullptr;
			return true;
		}

		return false;
	} );

	if( !SeparateActiveInstances )
	{
		if( debug )
		{
			// Log the object destroyed count and the destruction of the pool.
			UE_LOG( SteelHuntersLog, Log, TEXT( "[UObjectPool] Pool destroy completed (Pool: %s, Destroyed Object Count: %d)." ), *Name.ToString( ), destroyedObjectCount );
		}

		return;
	}

	// Now handle the separation of objects.
	int32 separatedObjectCount = Pool.RemoveAll( [&]( TWeakObjectPtr< UObject > pObject ) {
		IPooledObject* pPooledObject = dynamic_cast< IPooledObject* >( pObject.Get( ) );
		pPooledObject->ReturnToPool.Unbind( );

		pPooledObject->OnPoolRemovalWhileActive( );
		return true;
	} );

	if( debug )
	{
		// Log the object destroyed count and the destruction of the pool.
		UE_LOG( SteelHuntersLog, Log, TEXT( "[UObjectPool] Pool destroy completed with object separation (Pool: %s, Separated Object Count: %d, Destroyed Object Count: %d)." ), *Name.ToString( ), separatedObjectCount, destroyedObjectCount );
	}

#if !UE_BUILD_SHIPPING
	ensure( Pool.Num( ) == 0 );
#endif	// !UE_BUILD_SHIPPING.
}

//----------------------------------------------------------------------------------------------------
bool UObjectPool::Add( IPooledObject* ObjectIn, bool Active )
{
	check( ObjectIn != nullptr );

	// Check to ensure that IPooledObject is a derivative of UObject.
	UObject* pUObject = dynamic_cast< UObject* >( ObjectIn );

#if !UE_BUILD_SHIPPING
	ensure( IsValid( pUObject ) );
#endif	// !UE_BUILD_SHIPPING.

	// Predicate to check if this object is already in the pool.
	const uint32 objectID = ObjectIn->ID;
	if( Pool.ContainsByPredicate( [objectID]( TWeakObjectPtr< UObject > pObject ) {
		IPooledObject* pPooledObject = dynamic_cast< IPooledObject* >( pObject.Get( ) );
		return( objectID == pPooledObject->ID );
	} ) )
	{
		// Object is already in the pool.
		return false;
	}

	// Add this object to the pool.
	Pool.Add( pUObject );

	// Set whether or not the object is active (if being added, it usually is), and give it an ID.
	ObjectIn->IsActive = Active;
	ObjectIn->ID = IDCounter++;

	// Setup the object's pool return delegate (executed when the object is deactivated).
	ObjectIn->ReturnToPool.BindSP( this, &UObjectPool::OnObjectReturn );

	{
		const bool debug = CVarDebugObjectPooling.GetValueOnGameThread( );
		if( debug )
		{
			// Debug logging.
			UE_LOG( SteelHuntersLog, Log, TEXT( "[UObjectPool] Adding object to pool (Pool: %s, Object Count: %d)." ), *Name.ToString( ), Pool.Num( ) );
		}
	}
}

//----------------------------------------------------------------------------------------------------
template< typename T >
T* UObjectPool::GetPooledObject( )
{
	IPooledObject* pPooledObject = GetPooledObject( );
	if( pPooledObject == nullptr )
	{
		// No valid pooled objects.
		return nullptr;
	}

	T* pTemplateObject = Cast< T >( pPooledObject );
	check( IsValid( pTemplateObject ) );

	return pTemplateObject;
}

//----------------------------------------------------------------------------------------------------
IPooledObject* UObjectPool::GetPooledObject( )
{
	const int64 currentTime = FDateTime::Now( ).ToUnixTimestamp( );
	bool executePrune = PruneStale && ( ( currentTime - PruneLastTimestamp ) > PruneStale_Seconds );		// If this isn't true, then it may be time to prune anyway if the search finds an invalid object.

	// Find the first inactive and valid object.
	int32 idx = Pool.IndexOfByPredicate( [&]( TWeakObjectPtr< UObject > pObject ) {
		IPooledObject* pPooledObject = dynamic_cast< IPooledObject* >( pObject.Get( ) );
		if( !pPooledObject->GetIsActive( ) )
		{
			if( !pPooledObject->Check( ) )
			{
				// This object is invalid. Prune the pool after this search.
				executePrune = true;
				return false;
			}

			return true;
		}

		return false;
	} );

	if( idx == INDEX_NONE )
	{
		const bool debug = CVarDebugObjectPooling.GetValueOnGameThread( );
		if( debug )
		{
			// Debug logging.
			UE_LOG( SteelHuntersLog, Log, TEXT( "[UObjectPool] Unable to get a free object from the pool using ::GetPooledObject (Pool: %s, Object Count: %d)." ), *Name.ToString( ), Pool.Num( ) );
		}
	}

	// Get the found valid object, remove its place in the array, and add it to the back for a more efficient check later.
	//	NOTE (trent, 12/10/17): Ensure that this is actually an optimization.
	UObject* pUObject = Pool[idx].Get( );
	IPooledObject* pValidObject = dynamic_cast< IPooledObject* >( pUObject );
	Pool.RemoveAtSwap( idx, 1, false );
	Pool.Add( pUObject );

	// Activate the object.
	pValidObject->IsActive = true;
	pValidObject->LastActiveTimestamp = FDateTime::Now( ).ToUnixTimestamp( );

	if( executePrune )
	{
		// Prune the pool if need be (or if it's just time).
		//	NOTE: Since the object that was just found has already been reactivated and given an updated timestamp, it won't be pruned.
		Prune( );
	}

	return pValidObject;
}

//----------------------------------------------------------------------------------------------------
void UObjectPool::SetPruneStale( bool PruneStaleIn )
{
	PruneStale = PruneStaleIn;
}

//----------------------------------------------------------------------------------------------------
void UObjectPool::SetPruneInactiveTime( int64 PruneInactivitySeconds )
{
	PruneStale_Seconds = PruneInactivitySeconds;
}<commit_msg>The UE4 buildchain really likes piecemealing out those errors one-by-one, huh.<commit_after>// Copyright 2015-2017 Joy Machine, LLC. All rights reserved.

#include "steelhunters.h"

#include "ObjectPool.h"

#include "DateTime.h"

#include "IPooledObject.h"

// Console variable definition.
static TAutoConsoleVariable< int > CVarDebugObjectPooling( TEXT( "joy.DebugObjectPooling" ),
	0,
	TEXT( "Verbose output from the object pooling system for debugging." ),
	ECVF_Default );

// Static class definitions.
const int64 UObjectPool::kDefaultPruneStaleSeconds = 60;

uint32 UObjectPool::IDCounter = 0;
uint32 UObjectPool::PoolCount = 0;

//----------------------------------------------------------------------------------------------------
UObjectPool::UObjectPool( const class FObjectInitializer& ObjectInitializer )
: Name( *FString::Printf( TEXT( "Pool-%d" ), PoolCount ) )
, PoolID( PoolCount )
, PoolSizeOptimal( 256 )
, PoolSizeMaximum( 2048 )
, PruneStale( false )
, PruneLastTimestamp( FDateTime::Now( ).ToUnixTimestamp( ) )
, PruneStale_Seconds( kDefaultPruneStaleSeconds )
{
	Pool.Empty( );

	// Set this pool ID.
	PoolID = ++PoolCount;

	{
		const bool debug = CVarDebugObjectPooling.GetValueOnGameThread( );
		if( debug )
		{
			// Just toss out some debug information.
			UE_LOG( SteelHuntersLog, Log, TEXT( "[UObjectPool] Creating new pool (Pool Count: %d)." ), PoolCount );
		}
	}
}

//----------------------------------------------------------------------------------------------------
void UObjectPool::OnObjectReturn( IPooledObject* pObject )
{
	check( pObject != nullptr );

	// Reset the object (pure virtual method, so the logic is reliant on the child class).
	pObject->IsActive = false;
	pObject->Reset( );
}

//----------------------------------------------------------------------------------------------------
void UObjectPool::Prune( )
{
	const int64 currentTime = FDateTime::Now( ).ToUnixTimestamp( );
	int32 prunedObjectCount = Pool.RemoveAll( [&]( TWeakObjectPtr< UObject > pObject ) {
		if( !pObject.IsStale( ) && pObject.IsValid( ) )
		{
			// The object pointer is either stale or no longer valid.
			return false;
		}

		IPooledObject* pPooledObject = dynamic_cast< IPooledObject* >( pObject.Get( ) );
		if( !pPooledObject->GetIsActive( ) && !pPooledObject->Check( ) || ( PruneStale && ( ( currentTime - pPooledObject->LastActiveTimestamp ) > PruneStale_Seconds ) ) )
		{
			// This object is invalid or stale. Remove it.
			if( pPooledObject != nullptr )
			{
				// Just in case any logic in ::Deactivate is necessary, execute that, and then the ::Destroy method.
				pPooledObject->ReturnToPool.Unbind( );

				pPooledObject->DestroyInstance( );
				pPooledObject = nullptr;
			}

			return true;
		}

		return false;
	} );

	{
		const bool debug = CVarDebugObjectPooling.GetValueOnGameThread( );
		if( debug )
		{
			// Log the number of pruned objects.
			UE_LOG( SteelHuntersLog, Log, TEXT( "[UObjectPool] Pool pruning logic completed (Pool: %s, Object Count: %d, Pruned Count: %d." ), *Name.ToString( ), Pool.Num( ), prunedObjectCount );
		}
	}

	PruneLastTimestamp = currentTime;
}

//----------------------------------------------------------------------------------------------------
void UObjectPool::SetName( const FName& PoolName )
{
	// Just set the pool name; doesn't have to be unique.
	Name = GenerateName( PoolName );
}

//----------------------------------------------------------------------------------------------------
FName UObjectPool::GenerateName( const FName& BaseName )
{
	return( *FString::Printf( TEXT( "%s-%d" ), *BaseName.ToString( ), PoolCount ) );
}

//----------------------------------------------------------------------------------------------------
void UObjectPool::Empty( bool SeparateActiveInstances )
{
	const bool debug = CVarDebugObjectPooling.GetValueOnGameThread( );

	// Remove all objects from the pool and destroy them (unless SeparateActiveInstances is true, in which case leave them alone for now).
	int32 destroyedObjectCount = Pool.RemoveAll( [&]( TWeakObjectPtr< UObject > pObject ) {
		IPooledObject* pPooledObject = dynamic_cast< IPooledObject* >( pObject.Get( ) );
		if( !( SeparateActiveInstances && ( pPooledObject != nullptr ) && pPooledObject->GetIsActive( ) ) )
		{
			// Just in case any logic in ::Deactivate is necessary, execute that, and then the ::Destroy method.
			pPooledObject->ReturnToPool.Unbind( );

			pPooledObject->DestroyInstance( );
			pPooledObject = nullptr;
			return true;
		}

		return false;
	} );

	if( !SeparateActiveInstances )
	{
		if( debug )
		{
			// Log the object destroyed count and the destruction of the pool.
			UE_LOG( SteelHuntersLog, Log, TEXT( "[UObjectPool] Pool destroy completed (Pool: %s, Destroyed Object Count: %d)." ), *Name.ToString( ), destroyedObjectCount );
		}

		return;
	}

	// Now handle the separation of objects.
	int32 separatedObjectCount = Pool.RemoveAll( [&]( TWeakObjectPtr< UObject > pObject ) {
		IPooledObject* pPooledObject = dynamic_cast< IPooledObject* >( pObject.Get( ) );
		pPooledObject->ReturnToPool.Unbind( );

		pPooledObject->OnPoolRemovalWhileActive( );
		return true;
	} );

	if( debug )
	{
		// Log the object destroyed count and the destruction of the pool.
		UE_LOG( SteelHuntersLog, Log, TEXT( "[UObjectPool] Pool destroy completed with object separation (Pool: %s, Separated Object Count: %d, Destroyed Object Count: %d)." ), *Name.ToString( ), separatedObjectCount, destroyedObjectCount );
	}

#if !UE_BUILD_SHIPPING
	ensure( Pool.Num( ) == 0 );
#endif	// !UE_BUILD_SHIPPING.
}

//----------------------------------------------------------------------------------------------------
bool UObjectPool::Add( IPooledObject* ObjectIn, bool Active )
{
	check( ObjectIn != nullptr );

	// Check to ensure that IPooledObject is a derivative of UObject.
	UObject* pUObject = dynamic_cast< UObject* >( ObjectIn );

#if !UE_BUILD_SHIPPING
	ensure( IsValid( pUObject ) );
#endif	// !UE_BUILD_SHIPPING.

	// Predicate to check if this object is already in the pool.
	const uint32 objectID = ObjectIn->ID;
	if( Pool.ContainsByPredicate( [objectID]( TWeakObjectPtr< UObject > pObject ) {
		IPooledObject* pPooledObject = dynamic_cast< IPooledObject* >( pObject.Get( ) );
		return( objectID == pPooledObject->ID );
	} ) )
	{
		// Object is already in the pool.
		return false;
	}

	// Add this object to the pool.
	Pool.Add( pUObject );

	// Set whether or not the object is active (if being added, it usually is), and give it an ID.
	ObjectIn->IsActive = Active;
	ObjectIn->ID = IDCounter++;

	// Setup the object's pool return delegate (executed when the object is deactivated).
	ObjectIn->ReturnToPool.BindUObject( this, &UObjectPool::OnObjectReturn );

	{
		const bool debug = CVarDebugObjectPooling.GetValueOnGameThread( );
		if( debug )
		{
			// Debug logging.
			UE_LOG( SteelHuntersLog, Log, TEXT( "[UObjectPool] Adding object to pool (Pool: %s, Object Count: %d)." ), *Name.ToString( ), Pool.Num( ) );
		}
	}

	return true;
}

//----------------------------------------------------------------------------------------------------
template< typename T >
T* UObjectPool::GetPooledObject( )
{
	IPooledObject* pPooledObject = GetPooledObject( );
	if( pPooledObject == nullptr )
	{
		// No valid pooled objects.
		return nullptr;
	}

	T* pTemplateObject = Cast< T >( pPooledObject );
	check( IsValid( pTemplateObject ) );

	return pTemplateObject;
}

//----------------------------------------------------------------------------------------------------
IPooledObject* UObjectPool::GetPooledObject( )
{
	const int64 currentTime = FDateTime::Now( ).ToUnixTimestamp( );
	bool executePrune = PruneStale && ( ( currentTime - PruneLastTimestamp ) > PruneStale_Seconds );		// If this isn't true, then it may be time to prune anyway if the search finds an invalid object.

	// Find the first inactive and valid object.
	int32 idx = Pool.IndexOfByPredicate( [&]( TWeakObjectPtr< UObject > pObject ) {
		IPooledObject* pPooledObject = dynamic_cast< IPooledObject* >( pObject.Get( ) );
		if( !pPooledObject->GetIsActive( ) )
		{
			if( !pPooledObject->Check( ) )
			{
				// This object is invalid. Prune the pool after this search.
				executePrune = true;
				return false;
			}

			return true;
		}

		return false;
	} );

	if( idx == INDEX_NONE )
	{
		const bool debug = CVarDebugObjectPooling.GetValueOnGameThread( );
		if( debug )
		{
			// Debug logging.
			UE_LOG( SteelHuntersLog, Log, TEXT( "[UObjectPool] Unable to get a free object from the pool using ::GetPooledObject (Pool: %s, Object Count: %d)." ), *Name.ToString( ), Pool.Num( ) );
		}
	}

	// Get the found valid object, remove its place in the array, and add it to the back for a more efficient check later.
	//	NOTE (trent, 12/10/17): Ensure that this is actually an optimization.
	UObject* pUObject = Pool[idx].Get( );
	IPooledObject* pValidObject = dynamic_cast< IPooledObject* >( pUObject );
	Pool.RemoveAtSwap( idx, 1, false );
	Pool.Add( pUObject );

	// Activate the object.
	pValidObject->IsActive = true;
	pValidObject->LastActiveTimestamp = FDateTime::Now( ).ToUnixTimestamp( );

	if( executePrune )
	{
		// Prune the pool if need be (or if it's just time).
		//	NOTE: Since the object that was just found has already been reactivated and given an updated timestamp, it won't be pruned.
		Prune( );
	}

	return pValidObject;
}

//----------------------------------------------------------------------------------------------------
void UObjectPool::SetPruneStale( bool PruneStaleIn )
{
	PruneStale = PruneStaleIn;
}

//----------------------------------------------------------------------------------------------------
void UObjectPool::SetPruneInactiveTime( int64 PruneInactivitySeconds )
{
	PruneStale_Seconds = PruneInactivitySeconds;
}<|endoftext|>


<commit_before>// stress inversion of matrices with varios methods
#include "Math/SMatrix.h"
#include "TMatrixTSym.h"
#include "TDecompChol.h"
#include "TDecompBK.h"

#include "TRandom.h"
#include <vector>
#include <string>
#include <iostream>
#include <cmath>
#include <limits>

#include "TStopwatch.h"

// matrix size
#ifndef N
#define N 5
#endif

bool doSelfTest = true;

//timer
namespace test {

#ifdef REPORT_TIME
   void reportTime( std::string s, double time);
#endif

   void printTime(TStopwatch & time, std::string s) {
      int pr = std::cout.precision(8);
      std::cout << s << "\t" << " time = " << time.RealTime() << "\t(sec)\t"
         //    << time.CpuTime()
                << std::endl;
      std::cout.precision(pr);
   }

   class Timer {

   public:

      Timer(const std::string & s = "") : fName(s), fTime(0)
      {
         fWatch.Start();
      }
      Timer(double & t, const std::string & s = "") : fName(s), fTime(&t)
      {
         fWatch.Start();
      }

      ~Timer() {
         fWatch.Stop();
         printTime(fWatch,fName);
#ifdef REPORT_TIME
         // report time
         reportTime(fName, fWatch.RealTime() );
#endif
         if (fTime) *fTime += fWatch.RealTime();
      }

   private:

      std::string fName;
      double * fTime;
      TStopwatch fWatch;

   };
}

using namespace ROOT::Math;

typedef  SMatrix<double,N,N, MatRepSym<double,N> >  SymMatrix;

// create matrix
template<class M>
M * createMatrix() {
   return new M();
}
// specialized for TMatrix
template<>
TMatrixTSym<double> * createMatrix<TMatrixTSym<double> >() {
   return new TMatrixTSym<double>(N);
}

//print matrix
template<class M>
void printMatrix(const M & m) {
   std::cout << m << std::endl;
}
template<>
void printMatrix<TMatrixTSym<double> >(const TMatrixTSym<double> & m ) {
   m.Print();
}

// generate all matrices
template<class M>
void generate(std::vector<M*> & v) {
   int n = v.size();
   gRandom->SetSeed(111);
   for (int i = 0; i < n; ++i) {
      v[i] = createMatrix<M>();
      genMatrix(*v[i] );
   }
}

// generate matrices
template<class M>
void genMatrix(M  & m ) {
   TRandom & r = *gRandom;
   // generate first diagonal elemets
   for (int i = 0; i < N; ++i) {
      double maxVal = i*10000/(N-1) + 1;  // max condition is 10^4
      m(i,i) = r.Uniform(0, maxVal);
   }
   for (int i = 0; i < N; ++i) {
      for (int j = 0; j < i; ++j) {
         double v = 0.3*std::sqrt( m(i,i) * m(j,j) ); // this makes the matrix pos defined
         m(i,j) = r.Uniform(0, v);
         m(j,i) = m(i,j); // needed for TMatrix
      }
   }
}

struct Choleski {};
struct BK {};
struct QR {};
struct Cramer {};
struct Default {};

template <class M, class Type>
struct TestInverter {
   static bool Inv ( const M & , M & ) { return false;}
   static bool Inv2 ( M & ) { return false;}
};

template <>
struct TestInverter<SymMatrix, Choleski> {
   static bool Inv ( const SymMatrix & m, SymMatrix & result ) {
      int ifail = 0;
      result = m.InverseChol(ifail);
      return  ifail == 0;
   }
   static bool Inv2 ( SymMatrix & m ) {
      return m.InvertChol();
   }
};

template <>
struct TestInverter<SymMatrix, BK> {
   static bool Inv ( const SymMatrix & m, SymMatrix & result ) {
      int ifail = 0;
      result = m.Inverse(ifail);
      return ifail==0;
   }
   static bool Inv2 ( SymMatrix & m ) {
      return m.Invert();
   }
};

template <>
struct TestInverter<SymMatrix, Cramer> {
   static bool Inv ( const SymMatrix & m, SymMatrix & result ) {
      int ifail = 0;
      result = m.InverseFast(ifail);
      return ifail==0;
   }
   static bool Inv2 ( SymMatrix & m ) {
      return m.InvertFast();
   }
};

#ifdef LATER
template <>
struct TestInverter<SymMatrix, QR> {
   static bool Inv ( const SymMatrix & m, SymMatrix & result ) {
      ROOT::Math::QRDecomposition<double> d;
      int ifail = 0;
      result = m.InverseFast(ifail);
      return ifail==0;
   }
};
#endif

//TMatrix functions

template <>
struct TestInverter<TMatrixDSym, Default> {
   static bool Inv ( const TMatrixDSym & m, TMatrixDSym & result ) {
      result = m;
      result.Invert();
      return true;
   }
   static bool Inv2 ( TMatrixDSym & m ) {
      m.Invert();
      return true;
   }
};

template <>
struct TestInverter<TMatrixDSym, Cramer> {
   static bool Inv ( const TMatrixDSym & m, TMatrixDSym & result ) {
      result = m;
      result.InvertFast();
      return true;
   }
   static bool Inv2 ( TMatrixDSym & m ) {
      m.InvertFast();
      return true;
   }
};

template <>
struct TestInverter<TMatrixDSym, Choleski> {
   static bool Inv ( const TMatrixDSym & m, TMatrixDSym & result ) {
      TDecompChol chol(m);
      if (!chol.Decompose() ) return false;
      chol.Invert(result);
      return true;
   }
};

template <>
struct TestInverter<TMatrixDSym, BK> {
   static bool Inv ( const TMatrixDSym & m, TMatrixDSym & result ) {
      TDecompBK d(m);
      if (!d.Decompose() ) return false;
      d.Invert(result);
      return true;
   }
};

template<class M, class T>
double invert( const std::vector<M* >  & matlist, double & time,std::string s) {
   M result = *(matlist.front());
   test::Timer t(time,s);
   int nloop = matlist.size();
   double sum = 0;
   for (int l = 0; l < nloop; l++)
   {
      const M & m = *(matlist[l]);
      bool ok = TestInverter<M,T>::Inv(m,result);
      if (!ok) {
         std::cout << "inv failed for matrix " << l << std::endl;
         printMatrix<M>( m);
         return -1;
      }
      sum += result(0,1);
   }
   return sum;
}

// invert without copying the matrices (une INv2)

template<class M, class T>
double invert2( const std::vector<M* >  & matlist, double & time,std::string s) {

   // copy vector of matrices
   int nloop = matlist.size();
   std::vector<M *> vmat(nloop);
   for (int l = 0; l < nloop; l++)
   {
      vmat[l] = new M( *matlist[l] );
   }

   test::Timer t(time,s);
   double sum = 0;
   for (int l = 0; l < nloop; l++)
   {
      M & m = *(vmat[l]);
      bool ok = TestInverter<M,T>::Inv2(m);
      if (!ok) {
         std::cout << "inv failed for matrix " << l << std::endl;
         printMatrix<M>( m);
         return -1;
      }
      sum += m(0,1);
   }
   return sum;
}

bool equal(double d1, double d2, double stol = 10000) {
   std::cout.precision(12);  // tolerance is 1E-12
   double eps = stol * std::numeric_limits<double>::epsilon();
   if ( std::abs(d1) > 0 && std::abs(d2) > 0 )
      return  ( std::abs( d1-d2) < eps * std::max(std::abs(d1), std::abs(d2) ) );
   else if ( d1 == 0 )
      return std::abs(d2) < eps;
   else // d2 = 0
      return std::abs(d1) < eps;
}

// test matrices symmetric and positive defines
bool stressSymPosInversion(int n, bool selftest ) {

   // test smatrix

   std::vector<SymMatrix *> v1(n);
   generate(v1);
   std::vector<TMatrixDSym *> v2(n);
   generate(v2);

   bool iret = true;
   double time = 0;
   double s1 = invert<SymMatrix, Choleski> (v1, time,"SMatrix Chol");
   double s2 = invert<SymMatrix, BK> (v1, time,"SMatrix   BK");
   double s3 = invert<SymMatrix, Cramer> (v1, time,"SMatrix Cram");
   bool ok = ( equal(s1,s2) && equal(s1,s3) );
   if (!ok) {
      std::cout << "result SMatrix choleski  " << s1 << " BK   " << s2 << " cramer " << s3 << std::endl;
      std::cerr <<"Error:  inversion test for SMatrix FAILED ! " << std::endl;
   }
   iret  &= ok;
   std::cout << std::endl;

   double m1 = invert<TMatrixDSym, Choleski> (v2, time,"TMatrix Chol");
   double m2 = invert<TMatrixDSym, BK> (v2, time,"TMatrix   BK");
   double m3 = invert<TMatrixDSym, Cramer> (v2, time,"TMatrix Cram");
   double m4 = invert<TMatrixDSym, Default> (v2, time,"TMatrix  Def");

   ok =  ( equal(m1,m2) && equal(m1,m3) && equal(m1,m4) );
   if (!ok) {
      std::cout << "result TMatrix choleski  " << m1 << " BK   " << m2
                << " cramer " << m3 << " default " << m4 << std::endl;
      std::cerr <<"Error:  inversion test for TMatrix FAILED ! " << std::endl;
   }
   iret  &= ok;
   std::cout << std::endl;

      // test using self inversion
   if (selftest) {
      std::cout << "\n - self inversion test \n";
      double s11 = invert2<SymMatrix, Choleski> (v1, time,"SMatrix Chol");
      double s12 = invert2<SymMatrix, BK> (v1, time,"SMatrix   BK");
      double s13 = invert2<SymMatrix, Cramer> (v1, time,"SMatrix Cram");
      ok =  ( equal(s11,s12) && equal(s11,s13) );
      if (!ok) {
         std::cout << "result SMatrix choleski  " << s11 << " BK   " << s12 << " cramer " << s13 << std::endl;
         std::cerr <<"Error:  self inversion test for SMatrix FAILED ! " << std::endl;
      }
      iret  &= ok;
      std::cout << std::endl;

      double m13 = invert2<TMatrixDSym, Cramer> (v2, time,"TMatrix Cram");
      double m14 = invert2<TMatrixDSym, Default> (v2, time,"TMatrix  Def");
      ok =  ( equal(m13,m14)  );
      if (!ok) {
         std::cout << "result TMatrix  cramer " << m13 << " default " << m14 << std::endl;
         std::cerr <<"Error:  self inversion test for TMatrix FAILED ! " << std::endl;
      }
      iret  &= ok;
      std::cout << std::endl;
   }

   return iret;
}

bool testInversion(int n = 100000) {
   bool ok = stressSymPosInversion(n, doSelfTest);
   std::cerr << "Test inversion of positive defined matrix ....... ";
   if (ok) std::cerr << "OK \n";
   else std::cerr << "FAILED \n";
   return ok;
}

int main() {
   return (testInversion() ) ? 0 : -1;
}
<commit_msg>apply changes for roottest<commit_after>// stress inversion of matrices with varios methods
#include "Math/SMatrix.h"
#include "TMatrixTSym.h"
#include "TDecompChol.h"
#include "TDecompBK.h"

#include "TRandom.h"
#include <vector>
#include <string>
#include <iostream>
#include <cmath>
#include <limits>

#include "TStopwatch.h"

// matrix size
#ifndef N
#define N 5
#endif

bool doSelfTest = true;

//timer
namespace test {

#ifdef REPORT_TIME
   void reportTime( std::string s, double time);
#endif

   void printTime(TStopwatch & time, std::string s) {
      int pr = std::cout.precision(8);
      std::cout << s << "\t" << " time = " << time.RealTime() << "\t(sec)\t"
         //    << time.CpuTime()
                << std::endl;
      std::cout.precision(pr);
   }

   class Timer {

   public:

      Timer(const std::string & s = "") : fName(s), fTime(0)
      {
         fWatch.Start();
      }
      Timer(double & t, const std::string & s = "") : fName(s), fTime(&t)
      {
         fWatch.Start();
      }

      ~Timer() {
         fWatch.Stop();
         printTime(fWatch,fName);
#ifdef REPORT_TIME
         // report time
         reportTime(fName, fWatch.RealTime() );
#endif
         if (fTime) *fTime += fWatch.RealTime();
      }

   private:

      std::string fName;
      double * fTime;
      TStopwatch fWatch;

   };
}

using namespace ROOT::Math;

typedef  SMatrix<double,N,N, MatRepSym<double,N> >  SymMatrix;

// create matrix
template<class M>
M * createMatrix() {
   return new M();
}
// specialized for TMatrix
template<>
TMatrixTSym<double> * createMatrix<TMatrixTSym<double> >() {
   return new TMatrixTSym<double>(N);
}

//print matrix
template<class M>
void printMatrix(const M & m) {
   std::cout << m << std::endl;
}
template<>
void printMatrix<TMatrixTSym<double> >(const TMatrixTSym<double> & m ) {
   m.Print();
}

// generate all matrices
template<class M>
void generate(std::vector<M*> & v) {
   int n = v.size();
   gRandom->SetSeed(111);
   for (int i = 0; i < n; ++i) {
      v[i] = createMatrix<M>();
      genMatrix(*v[i] );
   }
}

// generate matrices
template<class M>
void genMatrix(M  & m ) {
   TRandom & r = *gRandom;
   // generate first diagonal elemets
   for (int i = 0; i < N; ++i) {
      double maxVal = i*10000/(N-1) + 1;  // max condition is 10^4
      m(i,i) = r.Uniform(0, maxVal);
   }
   for (int i = 0; i < N; ++i) {
      for (int j = 0; j < i; ++j) {
         double v = 0.3*std::sqrt( m(i,i) * m(j,j) ); // this makes the matrix pos defined
         m(i,j) = r.Uniform(0, v);
         m(j,i) = m(i,j); // needed for TMatrix
      }
   }
}

struct Choleski {};
struct BK {};
struct QR {};
struct Cramer {};
struct Default {};

template <class M, class Type>
struct TestInverter {
   static bool Inv ( const M & , M & ) { return false;}
   static bool Inv2 ( M & ) { return false;}
};

template <>
struct TestInverter<SymMatrix, Choleski> {
   static bool Inv ( const SymMatrix & m, SymMatrix & result ) {
      int ifail = 0;
      result = m.InverseChol(ifail);
      return  ifail == 0;
   }
   static bool Inv2 ( SymMatrix & m ) {
      return m.InvertChol();
   }
};

template <>
struct TestInverter<SymMatrix, BK> {
   static bool Inv ( const SymMatrix & m, SymMatrix & result ) {
      int ifail = 0;
      result = m.Inverse(ifail);
      return ifail==0;
   }
   static bool Inv2 ( SymMatrix & m ) {
      return m.Invert();
   }
};

template <>
struct TestInverter<SymMatrix, Cramer> {
   static bool Inv ( const SymMatrix & m, SymMatrix & result ) {
      int ifail = 0;
      result = m.InverseFast(ifail);
      return ifail==0;
   }
   static bool Inv2 ( SymMatrix & m ) {
      return m.InvertFast();
   }
};

#ifdef LATER
template <>
struct TestInverter<SymMatrix, QR> {
   static bool Inv ( const SymMatrix & m, SymMatrix & result ) {
      ROOT::Math::QRDecomposition<double> d;
      int ifail = 0;
      result = m.InverseFast(ifail);
      return ifail==0;
   }
};
#endif

//TMatrix functions

template <>
struct TestInverter<TMatrixDSym, Default> {
   static bool Inv ( const TMatrixDSym & m, TMatrixDSym & result ) {
      result = m;
      result.Invert();
      return true;
   }
   static bool Inv2 ( TMatrixDSym & m ) {
      m.Invert();
      return true;
   }
};

template <>
struct TestInverter<TMatrixDSym, Cramer> {
   static bool Inv ( const TMatrixDSym & m, TMatrixDSym & result ) {
      result = m;
      result.InvertFast();
      return true;
   }
   static bool Inv2 ( TMatrixDSym & m ) {
      m.InvertFast();
      return true;
   }
};

template <>
struct TestInverter<TMatrixDSym, Choleski> {
   static bool Inv ( const TMatrixDSym & m, TMatrixDSym & result ) {
      TDecompChol chol(m);
      if (!chol.Decompose() ) return false;
      chol.Invert(result);
      return true;
   }
};

template <>
struct TestInverter<TMatrixDSym, BK> {
   static bool Inv ( const TMatrixDSym & m, TMatrixDSym & result ) {
      TDecompBK d(m);
      if (!d.Decompose() ) return false;
      d.Invert(result);
      return true;
   }
};

template<class M, class T>
double invert( const std::vector<M* >  & matlist, double & time,std::string s) {
   M result = *(matlist.front());
   test::Timer t(time,s);
   int nloop = matlist.size();
   double sum = 0;
   for (int l = 0; l < nloop; l++)
   {
      const M & m = *(matlist[l]);
      bool ok = TestInverter<M,T>::Inv(m,result);
      if (!ok) {
         std::cout << "inv failed for matrix " << l << std::endl;
         printMatrix<M>( m);
         return -1;
      }
      sum += result(0,1);
   }
   return sum;
}

// invert without copying the matrices (une INv2)

template<class M, class T>
double invert2( const std::vector<M* >  & matlist, double & time,std::string s) {

   // copy vector of matrices
   int nloop = matlist.size();
   std::vector<M *> vmat(nloop);
   for (int l = 0; l < nloop; l++)
   {
      vmat[l] = new M( *matlist[l] );
   }

   test::Timer t(time,s);
   double sum = 0;
   for (int l = 0; l < nloop; l++)
   {
      M & m = *(vmat[l]);
      bool ok = TestInverter<M,T>::Inv2(m);
      if (!ok) {
         std::cout << "inv failed for matrix " << l << std::endl;
         printMatrix<M>( m);
         return -1;
      }
      sum += m(0,1);
   }
   return sum;
}

bool equal(double d1, double d2, double stol = 10000) {
   std::cout.precision(12);  // tolerance is 1E-12
   double eps = stol * std::numeric_limits<double>::epsilon();
   if ( std::abs(d1) > 0 && std::abs(d2) > 0 )
      return  ( std::abs( d1-d2) < eps * std::max(std::abs(d1), std::abs(d2) ) );
   else if ( d1 == 0 )
      return std::abs(d2) < eps;
   else // d2 = 0
      return std::abs(d1) < eps;
}

// test matrices symmetric and positive defines
bool stressSymPosInversion(int n, bool selftest ) {

   // test smatrix

   std::vector<SymMatrix *> v1(n);
   generate(v1);
   std::vector<TMatrixDSym *> v2(n);
   generate(v2);

   bool iret = true;
   double time = 0;
   double s1 = invert<SymMatrix, Choleski> (v1, time,"SMatrix Chol");
   double s2 = invert<SymMatrix, BK> (v1, time,"SMatrix   BK");
   double s3 = invert<SymMatrix, Cramer> (v1, time,"SMatrix Cram");
   bool ok = ( equal(s1,s2) && equal(s1,s3) );
   if (!ok) {
      std::cout << "result SMatrix choleski  " << s1 << " BK   " << s2 << " cramer " << s3 << std::endl;
      std::cerr <<"Error:  inversion test for SMatrix FAILED ! " << std::endl;
   }
   iret  &= ok;
   std::cout << std::endl;

   double m1 = invert<TMatrixDSym, Choleski> (v2, time,"TMatrix Chol");
   double m2 = invert<TMatrixDSym, BK> (v2, time,"TMatrix   BK");
   double m3 = invert<TMatrixDSym, Cramer> (v2, time,"TMatrix Cram");
   double m4 = invert<TMatrixDSym, Default> (v2, time,"TMatrix  Def");

   ok =  ( equal(m1,m2) && equal(m1,m3) && equal(m1,m4) );
   if (!ok) {
      std::cout << "result TMatrix choleski  " << m1 << " BK   " << m2
                << " cramer " << m3 << " default " << m4 << std::endl;
      std::cerr <<"Error:  inversion test for TMatrix FAILED ! " << std::endl;
   }
   iret  &= ok;
   std::cout << std::endl;

      // test using self inversion
   if (selftest) {
      std::cout << "\n - self inversion test \n";
      double s11 = invert2<SymMatrix, Choleski> (v1, time,"SMatrix Chol");
      double s12 = invert2<SymMatrix, BK> (v1, time,"SMatrix   BK");
      double s13 = invert2<SymMatrix, Cramer> (v1, time,"SMatrix Cram");
      ok =  ( equal(s11,s12) && equal(s11,s13) );
      if (!ok) {
         std::cout << "result SMatrix choleski  " << s11 << " BK   " << s12 << " cramer " << s13 << std::endl;
         std::cerr <<"Error:  self inversion test for SMatrix FAILED ! " << std::endl;
      }
      iret  &= ok;
      std::cout << std::endl;

      double m13 = invert2<TMatrixDSym, Cramer> (v2, time,"TMatrix Cram");
      double m14 = invert2<TMatrixDSym, Default> (v2, time,"TMatrix  Def");
      ok =  ( equal(m13,m14)  );
      if (!ok) {
         std::cout << "result TMatrix  cramer " << m13 << " default " << m14 << std::endl;
         std::cerr <<"Error:  self inversion test for TMatrix FAILED ! " << std::endl;
      }
      iret  &= ok;
      std::cout << std::endl;
   }

   return iret;
}

int testInversion(int n = 100000) {
   bool ok = stressSymPosInversion(n, doSelfTest);
   std::cerr << "Test inversion of positive defined matrix ....... ";
   if (ok) std::cerr << "OK \n";
   else std::cerr << "FAILED \n";
   return (ok) ? 0 : -1;
}

int main() {
   return testInversion();
}
<|endoftext|>


<commit_before>#include <cstdlib>
#include <iostream>
#include <iomanip>
#include <fstream>
#include "ObjModel.hpp"
#include "CommandLineParser.hpp"

struct CommandLine
{
    sys::CharSeqArg filename;
    sys::BoolArg verbose;
    sys::BoolArg help;

    CommandLine(int argc, const char **argv);
};

CommandLine::CommandLine(int argc, const char **argv)
{
    sys::CommandLineParser clp;
    clp.parameter(filename).placeholder("FILE").description("The filename to load and parse.");
    clp.option(help).name("help").shortName("h").description("Display this help message.");
    clp.option(verbose).name("verbose").shortName("v").description("Display information by objects.");
    clp.validator([this](){
        if(help) return sys::OperationResult::succeeded();
        return sys::OperationResult::test(filename, "Missing OBJ filename!");
    });

    sys::OperationResult result = clp.parse(argc, argv);
    if (!result)
    {
        std::cerr << result.message() << std::endl << std::endl;
    }

    if (!result || help)
    {
        std::cerr << "Usage: " << argv[0] << " [OPTIONS] FILE" << std::endl;
        std::cerr << clp;
        std::exit(1);
    }
}

int main (int argc, const char **argv)
{
    CommandLine cmdLine(argc, argv);

    std::ifstream ifs(cmdLine.filename.value());
    if (!ifs.is_open())
    {
        std::clog << "Cannot open file " << argv[1] << std::endl;
        return 1;
    }

    vfm::ObjModel model;
    ifs >> model;
    ifs.close();

    std::clog << std::setw(12) << "Vertices: " << model.positions.size() << std::endl;
    std::clog << std::setw(12) << "Normals: " << model.normals.size() << std::endl;
    std::clog << std::setw(12) << "Textures: " << model.textures.size() << std::endl;
    std::clog << std::setw(12) << "Objects: " << model.objects.size() << std::endl;

    if (cmdLine.verbose.value())
    {
        for (vfm::Object &o : model.objects)
        {
            std::clog << "Object '" << o.name << "' has " << o.vertexIndices.size() << " vertices" << " and " << o.triangles.size()/3 << " triangles" << std::endl;
        }
    }

    return 0;
}

<commit_msg>fix display filename correctly in error message for simpleloader<commit_after>#include <cstdlib>
#include <iostream>
#include <iomanip>
#include <fstream>
#include "ObjModel.hpp"
#include "CommandLineParser.hpp"

struct CommandLine
{
    sys::CharSeqArg filename;
    sys::BoolArg verbose;
    sys::BoolArg help;

    CommandLine(int argc, const char **argv);
};

CommandLine::CommandLine(int argc, const char **argv)
{
    sys::CommandLineParser clp;
    clp.parameter(filename).placeholder("FILE").description("The filename to load and parse.");
    clp.option(help).name("help").shortName("h").description("Display this help message.");
    clp.option(verbose).name("verbose").shortName("v").description("Display information by objects.");
    clp.validator([this](){
        if(help) return sys::OperationResult::succeeded();
        return sys::OperationResult::test(filename, "Missing OBJ filename!");
    });

    sys::OperationResult result = clp.parse(argc, argv);
    if (!result)
    {
        std::cerr << result.message() << std::endl << std::endl;
    }

    if (!result || help)
    {
        std::cerr << "Usage: " << argv[0] << " [OPTIONS] FILE" << std::endl;
        std::cerr << clp;
        std::exit(1);
    }
}

int main (int argc, const char **argv)
{
    CommandLine cmdLine(argc, argv);

    std::ifstream ifs(cmdLine.filename.value());
    if (!ifs.is_open())
    {
        std::clog << "Cannot open file " << cmdLine.filename.value() << std::endl;
        return 1;
    }

    vfm::ObjModel model;
    ifs >> model;
    ifs.close();

    std::clog << std::setw(12) << "Vertices: " << model.positions.size() << std::endl;
    std::clog << std::setw(12) << "Normals: " << model.normals.size() << std::endl;
    std::clog << std::setw(12) << "Textures: " << model.textures.size() << std::endl;
    std::clog << std::setw(12) << "Objects: " << model.objects.size() << std::endl;

    if (cmdLine.verbose.value())
    {
        for (vfm::Object &o : model.objects)
        {
            std::clog << "Object '" << o.name << "' has " << o.vertexIndices.size() << " vertices" << " and " << o.triangles.size()/3 << " triangles" << std::endl;
        }
    }

    return 0;
}

<|endoftext|>


<commit_before>#ifndef SLAP_TOOL_HPP
#define SLAP_TOOL_HPP

#include <string>

#include <utility>
#include <sstream>

namespace tool {

  std::string quote(const std::string& s, char q='"');
  std::string type_name(const std::type_info& self);

  template<class F, class ... Args, std::size_t ... I>
  static typename std::result_of< F(const Args&...) >::type
  apply(const F& f, const std::tuple<const Args&...>& args,
        std::index_sequence<I...>) {
    return f(std::get<I>(args)...);
  }

  // normalized/user friendly output of a type
  template<class T>
  static std::string show(const T& self, std::size_t max=64) {
    std::stringstream ss;
    ss << self;

    std::string str = ss.str();
    if(str.size() > max) {
      str = str.substr(0, max) + "...";
    }
    return quote(str);
  }

}

#endif
<commit_msg>timing<commit_after>#ifndef SLAP_TOOL_HPP
#define SLAP_TOOL_HPP

#include <string>

#include <utility>
#include <sstream>

#include <chrono>

namespace tool {

  std::string quote(const std::string& s, char q='"');
  std::string type_name(const std::type_info& self);

  template<class F, class ... Args, std::size_t ... I>
  static typename std::result_of< F(const Args&...) >::type
  apply(const F& f, const std::tuple<const Args&...>& args,
        std::index_sequence<I...>) {
    return f(std::get<I>(args)...);
  }

  // normalized/user friendly output of a type
  template<class T>
  static std::string show(const T& self, std::size_t max=64) {
    std::stringstream ss;
    ss << self;

    std::string str = ss.str();
    if(str.size() > max) {
      str = str.substr(0, max) + "...";
    }
    return quote(str);
  }

  template<class Func, class Resolution = std::chrono::milliseconds,
           class Clock = std::chrono::high_resolution_clock>
  static auto timer(double* duration, Func func) {
    typename Clock::time_point start = Clock::now();
    auto res = func();
    typename Clock::time_point stop = Clock::now();

    std::chrono::duration<double> diff = stop - start;
    *duration = diff.count();
    return res;
  }

}

#endif
<|endoftext|>


<commit_before>// Module:  Log4CPLUS
// File:    factory.cxx
// Created: 2/2002
// Author:  Tad E. Smith
//
//
// Copyright (C) Tad E. Smith  All rights reserved.
//
// This software is published under the terms of the Apache Software
// License version 1.1, a copy of which has been included with this
// distribution in the LICENSE.APL file.
//
// $Log: not supported by cvs2svn $
// Revision 1.6  2003/04/18 21:00:41  tcsmith
// Converted from std::string to log4cplus::tstring.
//
// Revision 1.5  2003/04/12 13:51:08  tcsmith
// No longer dynamically allocate the object in the "singleton" method.
//
// Revision 1.4  2003/04/03 00:41:11  tcsmith
// Standardized the formatting.
//

#include <log4cplus/spi/factory.h>
#include <log4cplus/consoleappender.h>
#include <log4cplus/fileappender.h>
#include <log4cplus/syslogappender.h>
#include <log4cplus/helpers/loglog.h>
#include <log4cplus/helpers/threads.h>

using namespace std;
using namespace log4cplus;
using namespace log4cplus::helpers;
using namespace log4cplus::spi;

///////////////////////////////////////////////////////////////////////////////
// LOCAL file class definitions
///////////////////////////////////////////////////////////////////////////////

namespace log4cplus {
    class ConsoleAppenderFactory : public AppenderFactory {
        SharedAppenderPtr createObject(const Properties& props)
        {
            return SharedAppenderPtr(new log4cplus::ConsoleAppender(props));
        }

        tstring getTypeName() {
	    return LOG4CPLUS_TEXT("log4cplus::ConsoleAppender");
	}
    };

    class FileAppenderFactory : public AppenderFactory {
        SharedAppenderPtr createObject(const Properties& props)
        {
            return SharedAppenderPtr(new log4cplus::FileAppender(props));
        }

        tstring getTypeName() {
	    return LOG4CPLUS_TEXT("log4cplus::FileAppender");
	}
    };

    class RollingFileAppenderFactory : public AppenderFactory {
        SharedAppenderPtr createObject(const Properties& props)
        {
            return SharedAppenderPtr(new log4cplus::RollingFileAppender(props));
        }

        tstring getTypeName() {
	    return LOG4CPLUS_TEXT("log4cplus::RollingFileAppender");
	}
    };

#if defined(HAVE_SYSLOG_H)
    class SysLogAppenderFactory : public AppenderFactory {
        SharedAppenderPtr createObject(const Properties& props)
        {
            return SharedAppenderPtr(new log4cplus::SysLogAppender(props));
        }

        tstring getTypeName() {
	    return LOG4CPLUS_TEXT("log4cplus::SysLogAppender");
	}
    };
#endif

    class SimpleLayoutFactory : public LayoutFactory {
        std::auto_ptr<Layout> createObject(const Properties& props)
        {
            return std::auto_ptr<Layout>(new log4cplus::SimpleLayout(props));
        }

        tstring getTypeName() {
	    return LOG4CPLUS_TEXT("log4cplus::SimpleLayout");
	}
    };

    class TTCCLayoutFactory : public LayoutFactory {
        std::auto_ptr<Layout> createObject(const Properties& props)
        {
            return std::auto_ptr<Layout>(new log4cplus::TTCCLayout(props));
        }

        tstring getTypeName() {
	    return LOG4CPLUS_TEXT("log4cplus::TTCCLayout");
	}
    };

    class PatternLayoutFactory : public LayoutFactory {
        std::auto_ptr<Layout> createObject(const Properties& props)
        {
            return std::auto_ptr<Layout>(new log4cplus::PatternLayout(props));
        }

        tstring getTypeName() {
	    return LOG4CPLUS_TEXT("log4cplus::PatternLayout");
	}
    };
}

///////////////////////////////////////////////////////////////////////////////
// LOCAL file initialization
///////////////////////////////////////////////////////////////////////////////

namespace {

    class _static_FactoryRegistry_initializer {
    public:
        _static_FactoryRegistry_initializer() {
            AppenderFactoryRegistry& reg = getAppenderFactoryRegistry();
            reg.put(auto_ptr<AppenderFactory>(new ConsoleAppenderFactory()));
            reg.put(auto_ptr<AppenderFactory>(new FileAppenderFactory()));
            reg.put(auto_ptr<AppenderFactory>(new RollingFileAppenderFactory()));
#if defined(HAVE_SYSLOG_H)
            reg.put(auto_ptr<AppenderFactory>(new SysLogAppenderFactory()));
#endif

            LayoutFactoryRegistry& reg2 = getLayoutFactoryRegistry();
            reg2.put(auto_ptr<LayoutFactory>(new SimpleLayoutFactory()));
            reg2.put(auto_ptr<LayoutFactory>(new TTCCLayoutFactory()));
            reg2.put(auto_ptr<LayoutFactory>(new PatternLayoutFactory()));
        }
    } initializer;
}

///////////////////////////////////////////////////////////////////////////////
// public methods
///////////////////////////////////////////////////////////////////////////////

AppenderFactoryRegistry&
log4cplus::spi::getAppenderFactoryRegistry()
{
    static AppenderFactoryRegistry singleton;
    return singleton;
}

LayoutFactoryRegistry&
log4cplus::spi::getLayoutFactoryRegistry()
{
    static LayoutFactoryRegistry singleton;
    return singleton;
}

<commit_msg>Added NTEventLogAppender support.<commit_after>// Module:  Log4CPLUS
// File:    factory.cxx
// Created: 2/2002
// Author:  Tad E. Smith
//
//
// Copyright (C) Tad E. Smith  All rights reserved.
//
// This software is published under the terms of the Apache Software
// License version 1.1, a copy of which has been included with this
// distribution in the LICENSE.APL file.
//
// $Log: not supported by cvs2svn $
// Revision 1.7  2003/04/19 07:23:06  tcsmith
// Added SysLogAppenderFactory.
//
// Revision 1.6  2003/04/18 21:00:41  tcsmith
// Converted from std::string to log4cplus::tstring.
//
// Revision 1.5  2003/04/12 13:51:08  tcsmith
// No longer dynamically allocate the object in the "singleton" method.
//
// Revision 1.4  2003/04/03 00:41:11  tcsmith
// Standardized the formatting.
//

#include <log4cplus/spi/factory.h>
#include <log4cplus/consoleappender.h>
#include <log4cplus/fileappender.h>
#include <log4cplus/nteventlogappender.h>
#include <log4cplus/syslogappender.h>
#include <log4cplus/helpers/loglog.h>
#include <log4cplus/helpers/threads.h>

using namespace std;
using namespace log4cplus;
using namespace log4cplus::helpers;
using namespace log4cplus::spi;

///////////////////////////////////////////////////////////////////////////////
// LOCAL file class definitions
///////////////////////////////////////////////////////////////////////////////

namespace log4cplus {
    class ConsoleAppenderFactory : public AppenderFactory {
        SharedAppenderPtr createObject(const Properties& props)
        {
            return SharedAppenderPtr(new log4cplus::ConsoleAppender(props));
        }

        tstring getTypeName() {
            return LOG4CPLUS_TEXT("log4cplus::ConsoleAppender");
        }
    };

    class FileAppenderFactory : public AppenderFactory {
        SharedAppenderPtr createObject(const Properties& props)
        {
            return SharedAppenderPtr(new log4cplus::FileAppender(props));
        }

        tstring getTypeName() {
            return LOG4CPLUS_TEXT("log4cplus::FileAppender");
        }
    };

    class RollingFileAppenderFactory : public AppenderFactory {
        SharedAppenderPtr createObject(const Properties& props)
        {
            return SharedAppenderPtr(new log4cplus::RollingFileAppender(props));
        }

        tstring getTypeName() {
            return LOG4CPLUS_TEXT("log4cplus::RollingFileAppender");
        }
    };

#if defined(WIN32)
    class NTEventLogAppenderFactory : public AppenderFactory {
        SharedAppenderPtr createObject(const Properties& props)
        {
            return SharedAppenderPtr(new log4cplus::NTEventLogAppender(props));
        }

        tstring getTypeName() {
            return LOG4CPLUS_TEXT("log4cplus::NTEventLogAppender");
        }
    };

#elif defined(HAVE_SYSLOG_H)
    class SysLogAppenderFactory : public AppenderFactory {
        SharedAppenderPtr createObject(const Properties& props)
        {
            return SharedAppenderPtr(new log4cplus::SysLogAppender(props));
        }

        tstring getTypeName() {
            return LOG4CPLUS_TEXT("log4cplus::SysLogAppender");
        }
    };
#endif

    class SimpleLayoutFactory : public LayoutFactory {
        std::auto_ptr<Layout> createObject(const Properties& props)
        {
            return std::auto_ptr<Layout>(new log4cplus::SimpleLayout(props));
        }

        tstring getTypeName() {
            return LOG4CPLUS_TEXT("log4cplus::SimpleLayout");
        }
    };

    class TTCCLayoutFactory : public LayoutFactory {
        std::auto_ptr<Layout> createObject(const Properties& props)
        {
            return std::auto_ptr<Layout>(new log4cplus::TTCCLayout(props));
        }

        tstring getTypeName() {
            return LOG4CPLUS_TEXT("log4cplus::TTCCLayout");
        }
    };

    class PatternLayoutFactory : public LayoutFactory {
        std::auto_ptr<Layout> createObject(const Properties& props)
        {
            return std::auto_ptr<Layout>(new log4cplus::PatternLayout(props));
        }

        tstring getTypeName() {
            return LOG4CPLUS_TEXT("log4cplus::PatternLayout");
        }
    };
}

///////////////////////////////////////////////////////////////////////////////
// LOCAL file initialization
///////////////////////////////////////////////////////////////////////////////

namespace {

    class _static_FactoryRegistry_initializer {
    public:
        _static_FactoryRegistry_initializer() {
            AppenderFactoryRegistry& reg = getAppenderFactoryRegistry();
            reg.put(auto_ptr<AppenderFactory>(new ConsoleAppenderFactory()));
            reg.put(auto_ptr<AppenderFactory>(new FileAppenderFactory()));
            reg.put(auto_ptr<AppenderFactory>(new RollingFileAppenderFactory()));
#if defined(WIN32)
            reg.put(auto_ptr<AppenderFactory>(new NTEventLogAppenderFactory()));
#elif defined(HAVE_SYSLOG_H)
            reg.put(auto_ptr<AppenderFactory>(new SysLogAppenderFactory()));
#endif

            LayoutFactoryRegistry& reg2 = getLayoutFactoryRegistry();
            reg2.put(auto_ptr<LayoutFactory>(new SimpleLayoutFactory()));
            reg2.put(auto_ptr<LayoutFactory>(new TTCCLayoutFactory()));
            reg2.put(auto_ptr<LayoutFactory>(new PatternLayoutFactory()));
        }
    } initializer;
}

///////////////////////////////////////////////////////////////////////////////
// public methods
///////////////////////////////////////////////////////////////////////////////

AppenderFactoryRegistry&
log4cplus::spi::getAppenderFactoryRegistry()
{
    static AppenderFactoryRegistry singleton;
    return singleton;
}

LayoutFactoryRegistry&
log4cplus::spi::getLayoutFactoryRegistry()
{
    static LayoutFactoryRegistry singleton;
    return singleton;
}

<|endoftext|>


<commit_before>// Module:  Log4CPLUS
// File:    factory.cxx
// Created: 2/2002
// Author:  Tad E. Smith
//
//
// Copyright (C) Tad E. Smith  All rights reserved.
//
// This software is published under the terms of the Apache Software
// License version 1.1, a copy of which has been included with this
// distribution in the LICENSE.APL file.
//
// $Log: not supported by cvs2svn $
// Revision 1.16  2003/09/28 04:02:14  tcsmith
// Made some fixes for the VisualAge 5 compiler on AIX.
//
// Revision 1.15  2003/08/27 14:55:16  tcsmith
// Modified initializeFactoryRegistry() to fix for the AIX compiler.
//
// Revision 1.14  2003/08/08 05:34:04  tcsmith
// Changed the #if checks to look for _WIN32 and not WIN32.
//
// Revision 1.13  2003/07/30 05:51:22  tcsmith
// Modified to remove "unused parameter" warning.
//
// Revision 1.12  2003/06/23 20:15:00  tcsmith
// Added NullAppenderFactory.
//
// Revision 1.11  2003/06/12 23:12:35  tcsmith
// Added DailyRollingFileAppenderFactory implementation.
//
// Revision 1.10  2003/05/28 17:39:12  tcsmith
// Added Filter factories.
//
// Revision 1.9  2003/05/04 07:08:23  tcsmith
// Replaced the static initialization class with the initializeFactoryRegistry()
// method.
//
// Revision 1.8  2003/04/19 20:59:01  tcsmith
// Added NTEventLogAppender support.
//
// Revision 1.7  2003/04/19 07:23:06  tcsmith
// Added SysLogAppenderFactory.
//
// Revision 1.6  2003/04/18 21:00:41  tcsmith
// Converted from std::string to log4cplus::tstring.
//
// Revision 1.5  2003/04/12 13:51:08  tcsmith
// No longer dynamically allocate the object in the "singleton" method.
//
// Revision 1.4  2003/04/03 00:41:11  tcsmith
// Standardized the formatting.
//

#include <log4cplus/spi/factory.h>
#include <log4cplus/consoleappender.h>
#include <log4cplus/fileappender.h>
#include <log4cplus/nteventlogappender.h>
#include <log4cplus/nullappender.h>
#include <log4cplus/socketappender.h>
#include <log4cplus/syslogappender.h>
#include <log4cplus/helpers/loglog.h>
#include <log4cplus/helpers/threads.h>

using namespace std;
using namespace log4cplus;
using namespace log4cplus::helpers;
using namespace log4cplus::spi;

///////////////////////////////////////////////////////////////////////////////
// LOCAL file class definitions
///////////////////////////////////////////////////////////////////////////////

namespace log4cplus {
    class ConsoleAppenderFactory : public AppenderFactory {
    public:
        SharedAppenderPtr createObject(const Properties& props)
        {
            return SharedAppenderPtr(new log4cplus::ConsoleAppender(props));
        }

        tstring getTypeName() {
            return LOG4CPLUS_TEXT("log4cplus::ConsoleAppender");
        }
    };

    class NullAppenderFactory : public AppenderFactory {
    public:
        SharedAppenderPtr createObject(const Properties& props)
        {
            return SharedAppenderPtr(new log4cplus::NullAppender(props));
        }

        tstring getTypeName() {
            return LOG4CPLUS_TEXT("log4cplus::NullAppender");
        }
    };

    class FileAppenderFactory : public AppenderFactory {
    public:
        SharedAppenderPtr createObject(const Properties& props)
        {
            return SharedAppenderPtr(new log4cplus::FileAppender(props));
        }

        tstring getTypeName() {
            return LOG4CPLUS_TEXT("log4cplus::FileAppender");
        }
    };

    class RollingFileAppenderFactory : public AppenderFactory {
    public:
        SharedAppenderPtr createObject(const Properties& props)
        {
            return SharedAppenderPtr(new log4cplus::RollingFileAppender(props));
        }

        tstring getTypeName() {
            return LOG4CPLUS_TEXT("log4cplus::RollingFileAppender");
        }
    };

    class DailyRollingFileAppenderFactory : public AppenderFactory {
    public:
        SharedAppenderPtr createObject(const Properties& props)
        {
            return SharedAppenderPtr(new log4cplus::DailyRollingFileAppender(props));
        }

        tstring getTypeName() {
            return LOG4CPLUS_TEXT("log4cplus::DailyRollingFileAppender");
        }
    };

    class SocketAppenderFactory : public AppenderFactory {
    public:
        SharedAppenderPtr createObject(const Properties& props)
        {
            return SharedAppenderPtr(new log4cplus::SocketAppender(props));
        }

        tstring getTypeName() {
            return LOG4CPLUS_TEXT("log4cplus::SocketAppender");
        }
    };

#if defined(_WIN32)
    class NTEventLogAppenderFactory : public AppenderFactory {
    public:
        SharedAppenderPtr createObject(const Properties& props)
        {
            return SharedAppenderPtr(new log4cplus::NTEventLogAppender(props));
        }

        tstring getTypeName() {
            return LOG4CPLUS_TEXT("log4cplus::NTEventLogAppender");
        }
    };

    class Win32DebugAppenderFactory : public AppenderFactory {
    public:
        SharedAppenderPtr createObject(const Properties& props)
        {
            return SharedAppenderPtr(new log4cplus::Win32DebugAppender(props));
        }

        tstring getTypeName() {
            return LOG4CPLUS_TEXT("log4cplus::Win32DebugAppender");
        }
    };

#elif defined(HAVE_SYSLOG_H)
    class SysLogAppenderFactory : public AppenderFactory {
    public:
        SharedAppenderPtr createObject(const Properties& props)
        {
            return SharedAppenderPtr(new log4cplus::SysLogAppender(props));
        }

        tstring getTypeName() {
            return LOG4CPLUS_TEXT("log4cplus::SysLogAppender");
        }
    };
#endif

    class SimpleLayoutFactory : public LayoutFactory {
    public:
        std::auto_ptr<Layout> createObject(const Properties& props)
        {
             std::auto_ptr<Layout> tmp(new log4cplus::SimpleLayout(props));
             return tmp;
        }

        tstring getTypeName() {
            return LOG4CPLUS_TEXT("log4cplus::SimpleLayout");
        }
    };

    class TTCCLayoutFactory : public LayoutFactory {
    public:
        std::auto_ptr<Layout> createObject(const Properties& props)
        {
            std::auto_ptr<Layout> tmp(new log4cplus::TTCCLayout(props));
            return tmp;
        }

        tstring getTypeName() {
            return LOG4CPLUS_TEXT("log4cplus::TTCCLayout");
        }
    };

    class PatternLayoutFactory : public LayoutFactory {
    public:
        std::auto_ptr<Layout> createObject(const Properties& props)
        {
            std::auto_ptr<Layout> tmp(new log4cplus::PatternLayout(props));
            return tmp;
        }

        tstring getTypeName() {
            return LOG4CPLUS_TEXT("log4cplus::PatternLayout");
        }
    };

    class DenyAllFilterFactory : public FilterFactory {
    public:
        FilterPtr createObject(const Properties&)
        {
            return FilterPtr(new log4cplus::spi::DenyAllFilter());
        }

        tstring getTypeName() {
            return LOG4CPLUS_TEXT("log4cplus::spi::DenyAllFilter");
        }
    };

    class LogLevelMatchFilterFactory : public FilterFactory {
    public:
        FilterPtr createObject(const Properties& props)
        {
            return FilterPtr(new log4cplus::spi::LogLevelMatchFilter(props));
        }

        tstring getTypeName() {
            return LOG4CPLUS_TEXT("log4cplus::spi::LogLevelMatchFilter");
        }
    };

    class LogLevelRangeFilterFactory : public FilterFactory {
    public:
        FilterPtr createObject(const Properties& props)
        {
            return FilterPtr(new log4cplus::spi::LogLevelRangeFilter(props));
        }

        tstring getTypeName() {
            return LOG4CPLUS_TEXT("log4cplus::spi::LogLevelRangeFilter");
        }
    };

    class StringMatchFilterFactory : public FilterFactory {
    public:
        FilterPtr createObject(const Properties& props)
        {
            return FilterPtr(new log4cplus::spi::StringMatchFilter(props));
        }

        tstring getTypeName() {
            return LOG4CPLUS_TEXT("log4cplus::spi::StringMatchFilter");
        }
    };
}

///////////////////////////////////////////////////////////////////////////////
// LOCAL file methods
///////////////////////////////////////////////////////////////////////////////

namespace log4cplus {
    void initializeFactoryRegistry() {
        AppenderFactoryRegistry& reg = getAppenderFactoryRegistry();
        auto_ptr<AppenderFactory> ptr1(new ConsoleAppenderFactory());
        reg.put(ptr1);
        auto_ptr<AppenderFactory> ptr2(new NullAppenderFactory());
        reg.put(ptr2);
        auto_ptr<AppenderFactory> ptr3(new FileAppenderFactory());
        reg.put(ptr3);
        auto_ptr<AppenderFactory> ptr4(new RollingFileAppenderFactory());
        reg.put(ptr4);
        auto_ptr<AppenderFactory> ptr5(new DailyRollingFileAppenderFactory());
        reg.put(ptr5);
        auto_ptr<AppenderFactory> ptr6(new SocketAppenderFactory());
        reg.put(ptr6);
#if defined(_WIN32)
        auto_ptr<AppenderFactory> ptr7(new NTEventLogAppenderFactory());
        reg.put(ptr7);
        auto_ptr<AppenderFactory> ptr8(new Win32DebugAppenderFactory());
        reg.put(ptr8);
#elif defined(HAVE_SYSLOG_H)
        auto_ptr<AppenderFactory> ptr9(new SysLogAppenderFactory());
        reg.put(ptr9);
#endif

        LayoutFactoryRegistry& reg2 = getLayoutFactoryRegistry();
        auto_ptr<LayoutFactory> ptr21(new SimpleLayoutFactory());
        reg2.put(ptr21);
        auto_ptr<LayoutFactory> ptr22(new TTCCLayoutFactory());
        reg2.put(ptr22);
        auto_ptr<LayoutFactory> ptr23(new PatternLayoutFactory());
        reg2.put(ptr23);

        FilterFactoryRegistry& reg3 = getFilterFactoryRegistry();
        auto_ptr<FilterFactory> ptr31(new DenyAllFilterFactory());
        reg3.put(ptr31);
        auto_ptr<FilterFactory> ptr32(new LogLevelMatchFilterFactory());
        reg3.put(ptr32);
        auto_ptr<FilterFactory> ptr33(new LogLevelRangeFilterFactory());
        reg3.put(ptr33);
        auto_ptr<FilterFactory> ptr34(new StringMatchFilterFactory());
        reg3.put(ptr34);
    }
}

///////////////////////////////////////////////////////////////////////////////
// public methods
///////////////////////////////////////////////////////////////////////////////

AppenderFactoryRegistry&
log4cplus::spi::getAppenderFactoryRegistry()
{
    static AppenderFactoryRegistry singleton;
    return singleton;
}

LayoutFactoryRegistry&
log4cplus::spi::getLayoutFactoryRegistry()
{
    static LayoutFactoryRegistry singleton;
    return singleton;
}

FilterFactoryRegistry&
log4cplus::spi::getFilterFactoryRegistry()
{
    static FilterFactoryRegistry singleton;
    return singleton;
}

<commit_msg>Added an include for the Win32Debugger class.<commit_after>// Module:  Log4CPLUS
// File:    factory.cxx
// Created: 2/2002
// Author:  Tad E. Smith
//
//
// Copyright (C) Tad E. Smith  All rights reserved.
//
// This software is published under the terms of the Apache Software
// License version 1.1, a copy of which has been included with this
// distribution in the LICENSE.APL file.
//
// $Log: not supported by cvs2svn $
// Revision 1.17  2004/02/14 20:13:05  tcsmith
// Added support for Win32DebugAppender.
//
// Revision 1.16  2003/09/28 04:02:14  tcsmith
// Made some fixes for the VisualAge 5 compiler on AIX.
//
// Revision 1.15  2003/08/27 14:55:16  tcsmith
// Modified initializeFactoryRegistry() to fix for the AIX compiler.
//
// Revision 1.14  2003/08/08 05:34:04  tcsmith
// Changed the #if checks to look for _WIN32 and not WIN32.
//
// Revision 1.13  2003/07/30 05:51:22  tcsmith
// Modified to remove "unused parameter" warning.
//
// Revision 1.12  2003/06/23 20:15:00  tcsmith
// Added NullAppenderFactory.
//
// Revision 1.11  2003/06/12 23:12:35  tcsmith
// Added DailyRollingFileAppenderFactory implementation.
//
// Revision 1.10  2003/05/28 17:39:12  tcsmith
// Added Filter factories.
//
// Revision 1.9  2003/05/04 07:08:23  tcsmith
// Replaced the static initialization class with the initializeFactoryRegistry()
// method.
//
// Revision 1.8  2003/04/19 20:59:01  tcsmith
// Added NTEventLogAppender support.
//
// Revision 1.7  2003/04/19 07:23:06  tcsmith
// Added SysLogAppenderFactory.
//
// Revision 1.6  2003/04/18 21:00:41  tcsmith
// Converted from std::string to log4cplus::tstring.
//
// Revision 1.5  2003/04/12 13:51:08  tcsmith
// No longer dynamically allocate the object in the "singleton" method.
//
// Revision 1.4  2003/04/03 00:41:11  tcsmith
// Standardized the formatting.
//

#include <log4cplus/spi/factory.h>
#include <log4cplus/consoleappender.h>
#include <log4cplus/fileappender.h>
#include <log4cplus/nteventlogappender.h>
#include <log4cplus/nullappender.h>
#include <log4cplus/socketappender.h>
#include <log4cplus/syslogappender.h>
#include <log4cplus/helpers/loglog.h>
#include <log4cplus/helpers/threads.h>

#if defined (_WIN32)
#include <log4cplus/Win32DebugAppender.h>
#endif

using namespace std;
using namespace log4cplus;
using namespace log4cplus::helpers;
using namespace log4cplus::spi;

///////////////////////////////////////////////////////////////////////////////
// LOCAL file class definitions
///////////////////////////////////////////////////////////////////////////////

namespace log4cplus {
    class ConsoleAppenderFactory : public AppenderFactory {
    public:
        SharedAppenderPtr createObject(const Properties& props)
        {
            return SharedAppenderPtr(new log4cplus::ConsoleAppender(props));
        }

        tstring getTypeName() {
            return LOG4CPLUS_TEXT("log4cplus::ConsoleAppender");
        }
    };

    class NullAppenderFactory : public AppenderFactory {
    public:
        SharedAppenderPtr createObject(const Properties& props)
        {
            return SharedAppenderPtr(new log4cplus::NullAppender(props));
        }

        tstring getTypeName() {
            return LOG4CPLUS_TEXT("log4cplus::NullAppender");
        }
    };

    class FileAppenderFactory : public AppenderFactory {
    public:
        SharedAppenderPtr createObject(const Properties& props)
        {
            return SharedAppenderPtr(new log4cplus::FileAppender(props));
        }

        tstring getTypeName() {
            return LOG4CPLUS_TEXT("log4cplus::FileAppender");
        }
    };

    class RollingFileAppenderFactory : public AppenderFactory {
    public:
        SharedAppenderPtr createObject(const Properties& props)
        {
            return SharedAppenderPtr(new log4cplus::RollingFileAppender(props));
        }

        tstring getTypeName() {
            return LOG4CPLUS_TEXT("log4cplus::RollingFileAppender");
        }
    };

    class DailyRollingFileAppenderFactory : public AppenderFactory {
    public:
        SharedAppenderPtr createObject(const Properties& props)
        {
            return SharedAppenderPtr(new log4cplus::DailyRollingFileAppender(props));
        }

        tstring getTypeName() {
            return LOG4CPLUS_TEXT("log4cplus::DailyRollingFileAppender");
        }
    };

    class SocketAppenderFactory : public AppenderFactory {
    public:
        SharedAppenderPtr createObject(const Properties& props)
        {
            return SharedAppenderPtr(new log4cplus::SocketAppender(props));
        }

        tstring getTypeName() {
            return LOG4CPLUS_TEXT("log4cplus::SocketAppender");
        }
    };

#if defined(_WIN32)
    class NTEventLogAppenderFactory : public AppenderFactory {
    public:
        SharedAppenderPtr createObject(const Properties& props)
        {
            return SharedAppenderPtr(new log4cplus::NTEventLogAppender(props));
        }

        tstring getTypeName() {
            return LOG4CPLUS_TEXT("log4cplus::NTEventLogAppender");
        }
    };

    class Win32DebugAppenderFactory : public AppenderFactory {
    public:
        SharedAppenderPtr createObject(const Properties& props)
        {
            return SharedAppenderPtr(new log4cplus::Win32DebugAppender(props));
        }

        tstring getTypeName() {
            return LOG4CPLUS_TEXT("log4cplus::Win32DebugAppender");
        }
    };

#elif defined(HAVE_SYSLOG_H)
    class SysLogAppenderFactory : public AppenderFactory {
    public:
        SharedAppenderPtr createObject(const Properties& props)
        {
            return SharedAppenderPtr(new log4cplus::SysLogAppender(props));
        }

        tstring getTypeName() {
            return LOG4CPLUS_TEXT("log4cplus::SysLogAppender");
        }
    };
#endif

    class SimpleLayoutFactory : public LayoutFactory {
    public:
        std::auto_ptr<Layout> createObject(const Properties& props)
        {
             std::auto_ptr<Layout> tmp(new log4cplus::SimpleLayout(props));
             return tmp;
        }

        tstring getTypeName() {
            return LOG4CPLUS_TEXT("log4cplus::SimpleLayout");
        }
    };

    class TTCCLayoutFactory : public LayoutFactory {
    public:
        std::auto_ptr<Layout> createObject(const Properties& props)
        {
            std::auto_ptr<Layout> tmp(new log4cplus::TTCCLayout(props));
            return tmp;
        }

        tstring getTypeName() {
            return LOG4CPLUS_TEXT("log4cplus::TTCCLayout");
        }
    };

    class PatternLayoutFactory : public LayoutFactory {
    public:
        std::auto_ptr<Layout> createObject(const Properties& props)
        {
            std::auto_ptr<Layout> tmp(new log4cplus::PatternLayout(props));
            return tmp;
        }

        tstring getTypeName() {
            return LOG4CPLUS_TEXT("log4cplus::PatternLayout");
        }
    };

    class DenyAllFilterFactory : public FilterFactory {
    public:
        FilterPtr createObject(const Properties&)
        {
            return FilterPtr(new log4cplus::spi::DenyAllFilter());
        }

        tstring getTypeName() {
            return LOG4CPLUS_TEXT("log4cplus::spi::DenyAllFilter");
        }
    };

    class LogLevelMatchFilterFactory : public FilterFactory {
    public:
        FilterPtr createObject(const Properties& props)
        {
            return FilterPtr(new log4cplus::spi::LogLevelMatchFilter(props));
        }

        tstring getTypeName() {
            return LOG4CPLUS_TEXT("log4cplus::spi::LogLevelMatchFilter");
        }
    };

    class LogLevelRangeFilterFactory : public FilterFactory {
    public:
        FilterPtr createObject(const Properties& props)
        {
            return FilterPtr(new log4cplus::spi::LogLevelRangeFilter(props));
        }

        tstring getTypeName() {
            return LOG4CPLUS_TEXT("log4cplus::spi::LogLevelRangeFilter");
        }
    };

    class StringMatchFilterFactory : public FilterFactory {
    public:
        FilterPtr createObject(const Properties& props)
        {
            return FilterPtr(new log4cplus::spi::StringMatchFilter(props));
        }

        tstring getTypeName() {
            return LOG4CPLUS_TEXT("log4cplus::spi::StringMatchFilter");
        }
    };
}

///////////////////////////////////////////////////////////////////////////////
// LOCAL file methods
///////////////////////////////////////////////////////////////////////////////

namespace log4cplus {
    void initializeFactoryRegistry() {
        AppenderFactoryRegistry& reg = getAppenderFactoryRegistry();
        auto_ptr<AppenderFactory> ptr1(new ConsoleAppenderFactory());
        reg.put(ptr1);
        auto_ptr<AppenderFactory> ptr2(new NullAppenderFactory());
        reg.put(ptr2);
        auto_ptr<AppenderFactory> ptr3(new FileAppenderFactory());
        reg.put(ptr3);
        auto_ptr<AppenderFactory> ptr4(new RollingFileAppenderFactory());
        reg.put(ptr4);
        auto_ptr<AppenderFactory> ptr5(new DailyRollingFileAppenderFactory());
        reg.put(ptr5);
        auto_ptr<AppenderFactory> ptr6(new SocketAppenderFactory());
        reg.put(ptr6);
#if defined(_WIN32)
        auto_ptr<AppenderFactory> ptr7(new NTEventLogAppenderFactory());
        reg.put(ptr7);
        auto_ptr<AppenderFactory> ptr8(new Win32DebugAppenderFactory());
        reg.put(ptr8);
#elif defined(HAVE_SYSLOG_H)
        auto_ptr<AppenderFactory> ptr9(new SysLogAppenderFactory());
        reg.put(ptr9);
#endif

        LayoutFactoryRegistry& reg2 = getLayoutFactoryRegistry();
        auto_ptr<LayoutFactory> ptr21(new SimpleLayoutFactory());
        reg2.put(ptr21);
        auto_ptr<LayoutFactory> ptr22(new TTCCLayoutFactory());
        reg2.put(ptr22);
        auto_ptr<LayoutFactory> ptr23(new PatternLayoutFactory());
        reg2.put(ptr23);

        FilterFactoryRegistry& reg3 = getFilterFactoryRegistry();
        auto_ptr<FilterFactory> ptr31(new DenyAllFilterFactory());
        reg3.put(ptr31);
        auto_ptr<FilterFactory> ptr32(new LogLevelMatchFilterFactory());
        reg3.put(ptr32);
        auto_ptr<FilterFactory> ptr33(new LogLevelRangeFilterFactory());
        reg3.put(ptr33);
        auto_ptr<FilterFactory> ptr34(new StringMatchFilterFactory());
        reg3.put(ptr34);
    }
}

///////////////////////////////////////////////////////////////////////////////
// public methods
///////////////////////////////////////////////////////////////////////////////

AppenderFactoryRegistry&
log4cplus::spi::getAppenderFactoryRegistry()
{
    static AppenderFactoryRegistry singleton;
    return singleton;
}

LayoutFactoryRegistry&
log4cplus::spi::getLayoutFactoryRegistry()
{
    static LayoutFactoryRegistry singleton;
    return singleton;
}

FilterFactoryRegistry&
log4cplus::spi::getFilterFactoryRegistry()
{
    static FilterFactoryRegistry singleton;
    return singleton;
}

<|endoftext|>