<commit_before>//===--- CaptureTracking.cpp - Determine whether a pointer is captured ----===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file contains routines that help determine which pointers are captured.
// A pointer value is captured if the function makes a copy of any part of the
// pointer that outlives the call.  Not being captured means, more or less, that
// the pointer is only dereferenced and not stored in a global.  Returning part
// of the pointer as the function return value may or may not count as capturing
// the pointer, depending on the context.
//
//===----------------------------------------------------------------------===//

#include "llvm/Analysis/CaptureTracking.h"
#include "llvm/Instructions.h"
#include "llvm/Value.h"
#include "llvm/Analysis/AliasAnalysis.h"
#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/CallSite.h"
using namespace llvm;

/// As its comment mentions, PointerMayBeCaptured can be expensive.
/// However, it's not easy for BasicAA to cache the result, because
/// it's an ImmutablePass. To work around this, bound queries at a
/// fixed number of uses.
///
/// TODO: Write a new FunctionPass AliasAnalysis so that it can keep
/// a cache. Then we can move the code from BasicAliasAnalysis into
/// that path, and remove this threshold.
static int const Threshold = 20;

/// PointerMayBeCaptured - Return true if this pointer value may be captured
/// by the enclosing function (which is required to exist).  This routine can
/// be expensive, so consider caching the results.  The boolean ReturnCaptures
/// specifies whether returning the value (or part of it) from the function
/// counts as capturing it or not.  The boolean StoreCaptures specified whether
/// storing the value (or part of it) into memory anywhere automatically
/// counts as capturing it or not.
bool llvm::PointerMayBeCaptured(const Value *V,
                                bool ReturnCaptures, bool StoreCaptures) {
  assert(isa<PointerType>(V->getType()) && "Capture is for pointers only!");
  SmallVector<Use*, 16> Worklist;
  SmallSet<Use*, 16> Visited;
  int Count = 0;

  for (Value::use_const_iterator UI = V->use_begin(), UE = V->use_end();
       UI != UE; ++UI) {
    Use *U = &UI.getUse();
    Visited.insert(U);
    Worklist.push_back(U);

    // If there are lots of uses, conservativelty say that the value
    // is captured to avoid taking too much compile time.
    if (Count++ >= Threshold)
      return true;
  }

  while (!Worklist.empty()) {
    Use *U = Worklist.pop_back_val();
    Instruction *I = cast<Instruction>(U->getUser());
    V = U->get();

    switch (I->getOpcode()) {
    case Instruction::Call:
    case Instruction::Invoke: {
      CallSite CS = CallSite::get(I);
      // Not captured if the callee is readonly, doesn't return a copy through
      // its return value and doesn't unwind (a readonly function can leak bits
      // by throwing an exception or not depending on the input value).
      if (CS.onlyReadsMemory() && CS.doesNotThrow() && I->getType()->isVoidTy())
        break;

      // Not captured if only passed via 'nocapture' arguments.  Note that
      // calling a function pointer does not in itself cause the pointer to
      // be captured.  This is a subtle point considering that (for example)
      // the callee might return its own address.  It is analogous to saying
      // that loading a value from a pointer does not cause the pointer to be
      // captured, even though the loaded value might be the pointer itself
      // (think of self-referential objects).
      CallSite::arg_iterator B = CS.arg_begin(), E = CS.arg_end();
      for (CallSite::arg_iterator A = B; A != E; ++A)
        if (A->get() == V && !CS.paramHasAttr(A - B + 1, Attribute::NoCapture))
          // The parameter is not marked 'nocapture' - captured.
          return true;
      // Only passed via 'nocapture' arguments, or is the called function - not
      // captured.
      break;
    }
    case Instruction::Load:
      // Loading from a pointer does not cause it to be captured.
      break;
    case Instruction::Ret:
      if (ReturnCaptures)
        return true;
      break;
    case Instruction::Store:
      if (V == I->getOperand(0))
        // Stored the pointer - conservatively assume it may be captured.
        // TODO: If StoreCaptures is not true, we could do Fancy analysis
        // to determine whether this store is not actually an escape point.
        // In that case, BasicAliasAnalysis should be updated as well to
        // take advantage of this.
        return true;
      // Storing to the pointee does not cause the pointer to be captured.
      break;
    case Instruction::BitCast:
    case Instruction::GetElementPtr:
    case Instruction::PHI:
    case Instruction::Select:
      // The original value is not captured via this if the new value isn't.
      for (Instruction::use_iterator UI = I->use_begin(), UE = I->use_end();
           UI != UE; ++UI) {
        Use *U = &UI.getUse();
        if (Visited.insert(U))
          Worklist.push_back(U);
      }
      break;
    case Instruction::ICmp:
      // Don't count comparisons of a no-alias return value against null as
      // captures. This allows us to ignore comparisons of malloc results
      // with null, for example.
      if (isNoAliasCall(V->stripPointerCasts()))
        if (ConstantPointerNull *CPN =
              dyn_cast<ConstantPointerNull>(I->getOperand(1)))
          if (CPN->getType()->getAddressSpace() == 0)
            break;
      // Otherwise, be conservative. There are crazy ways to capture pointers
      // using comparisons.
      return true;
    default:
      // Something else - be conservative and say it is captured.
      return true;
    }
  }

  // All uses examined - not captured.
  return false;
}
<commit_msg>Fix a typo in a comment, and adjust SmallSet and SmallVector sizes, that Chris noticed.<commit_after>//===--- CaptureTracking.cpp - Determine whether a pointer is captured ----===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file contains routines that help determine which pointers are captured.
// A pointer value is captured if the function makes a copy of any part of the
// pointer that outlives the call.  Not being captured means, more or less, that
// the pointer is only dereferenced and not stored in a global.  Returning part
// of the pointer as the function return value may or may not count as capturing
// the pointer, depending on the context.
//
//===----------------------------------------------------------------------===//

#include "llvm/Analysis/CaptureTracking.h"
#include "llvm/Instructions.h"
#include "llvm/Value.h"
#include "llvm/Analysis/AliasAnalysis.h"
#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/CallSite.h"
using namespace llvm;

/// As its comment mentions, PointerMayBeCaptured can be expensive.
/// However, it's not easy for BasicAA to cache the result, because
/// it's an ImmutablePass. To work around this, bound queries at a
/// fixed number of uses.
///
/// TODO: Write a new FunctionPass AliasAnalysis so that it can keep
/// a cache. Then we can move the code from BasicAliasAnalysis into
/// that path, and remove this threshold.
static int const Threshold = 20;

/// PointerMayBeCaptured - Return true if this pointer value may be captured
/// by the enclosing function (which is required to exist).  This routine can
/// be expensive, so consider caching the results.  The boolean ReturnCaptures
/// specifies whether returning the value (or part of it) from the function
/// counts as capturing it or not.  The boolean StoreCaptures specified whether
/// storing the value (or part of it) into memory anywhere automatically
/// counts as capturing it or not.
bool llvm::PointerMayBeCaptured(const Value *V,
                                bool ReturnCaptures, bool StoreCaptures) {
  assert(isa<PointerType>(V->getType()) && "Capture is for pointers only!");
  SmallVector<Use*, 20> Worklist;
  SmallSet<Use*, 20> Visited;
  int Count = 0;

  for (Value::use_const_iterator UI = V->use_begin(), UE = V->use_end();
       UI != UE; ++UI) {
    // If there are lots of uses, conservatively say that the value
    // is captured to avoid taking too much compile time.
    if (Count++ >= Threshold)
      return true;

    Use *U = &UI.getUse();
    Visited.insert(U);
    Worklist.push_back(U);
  }

  while (!Worklist.empty()) {
    Use *U = Worklist.pop_back_val();
    Instruction *I = cast<Instruction>(U->getUser());
    V = U->get();

    switch (I->getOpcode()) {
    case Instruction::Call:
    case Instruction::Invoke: {
      CallSite CS = CallSite::get(I);
      // Not captured if the callee is readonly, doesn't return a copy through
      // its return value and doesn't unwind (a readonly function can leak bits
      // by throwing an exception or not depending on the input value).
      if (CS.onlyReadsMemory() && CS.doesNotThrow() && I->getType()->isVoidTy())
        break;

      // Not captured if only passed via 'nocapture' arguments.  Note that
      // calling a function pointer does not in itself cause the pointer to
      // be captured.  This is a subtle point considering that (for example)
      // the callee might return its own address.  It is analogous to saying
      // that loading a value from a pointer does not cause the pointer to be
      // captured, even though the loaded value might be the pointer itself
      // (think of self-referential objects).
      CallSite::arg_iterator B = CS.arg_begin(), E = CS.arg_end();
      for (CallSite::arg_iterator A = B; A != E; ++A)
        if (A->get() == V && !CS.paramHasAttr(A - B + 1, Attribute::NoCapture))
          // The parameter is not marked 'nocapture' - captured.
          return true;
      // Only passed via 'nocapture' arguments, or is the called function - not
      // captured.
      break;
    }
    case Instruction::Load:
      // Loading from a pointer does not cause it to be captured.
      break;
    case Instruction::Ret:
      if (ReturnCaptures)
        return true;
      break;
    case Instruction::Store:
      if (V == I->getOperand(0))
        // Stored the pointer - conservatively assume it may be captured.
        // TODO: If StoreCaptures is not true, we could do Fancy analysis
        // to determine whether this store is not actually an escape point.
        // In that case, BasicAliasAnalysis should be updated as well to
        // take advantage of this.
        return true;
      // Storing to the pointee does not cause the pointer to be captured.
      break;
    case Instruction::BitCast:
    case Instruction::GetElementPtr:
    case Instruction::PHI:
    case Instruction::Select:
      // The original value is not captured via this if the new value isn't.
      for (Instruction::use_iterator UI = I->use_begin(), UE = I->use_end();
           UI != UE; ++UI) {
        Use *U = &UI.getUse();
        if (Visited.insert(U))
          Worklist.push_back(U);
      }
      break;
    case Instruction::ICmp:
      // Don't count comparisons of a no-alias return value against null as
      // captures. This allows us to ignore comparisons of malloc results
      // with null, for example.
      if (isNoAliasCall(V->stripPointerCasts()))
        if (ConstantPointerNull *CPN =
              dyn_cast<ConstantPointerNull>(I->getOperand(1)))
          if (CPN->getType()->getAddressSpace() == 0)
            break;
      // Otherwise, be conservative. There are crazy ways to capture pointers
      // using comparisons.
      return true;
    default:
      // Something else - be conservative and say it is captured.
      return true;
    }
  }

  // All uses examined - not captured.
  return false;
}
<|endoftext|>


<commit_before>
// STL includes
#include <csignal>
#include <iomanip>

// QT includes
#include <QImage>

// getoptPlusPLus includes
#include <getoptPlusPlus/getoptpp.h>

// Dispmanx grabber includes
#include <grabber/dispmanx/DispmanxFrameGrabber.h>

using namespace vlofgren;

static bool running = true;

void signal_handler(int signum)
{
	running = false;
}

int main(int argc, char** argv)
{
	signal(SIGTERM, signal_handler);
	signal(SIGINT,  signal_handler);

	int grabFlags = 0;
	int grabCount = -1;
	try
	{
		// create the option parser and initialize all parameters
		OptionsParser optionParser("Simple application to send a command to hyperion using the Json interface");
		ParameterSet & parameters = optionParser.getParameters();

		QString flagDescr = QString("Set the grab flags of the dispmanx frame grabber [default: 0x%1]").arg(grabFlags, 8, 16, QChar('0'));
		StringParameter   & argFlags = parameters.add<StringParameter>   ('f', "flags", flagDescr.toAscii().constData());
		IntParameter      & argCount = parameters.add<IntParameter>      ('n', "count", "Number of images to capture (default infinite)");
		argCount.setDefault(grabCount);
		SwitchParameter<> & argList  = parameters.add<SwitchParameter<> >('l', "list",  "List the possible flags");
		SwitchParameter<> & argHelp  = parameters.add<SwitchParameter<> >('h', "help",  "Show this help message and exit");

		// parse all options
		optionParser.parse(argc, const_cast<const char **>(argv));

		// check if we need to display the usage. exit if we do.
		if (argHelp.isSet())
		{
			optionParser.usage();
			return 0;
		}
		if (argList.isSet())
		{
			std::cout.width(15);
			std::cout.width(10);
			std::cout << "Possible DISPMANX flags: " << std::endl;
			std::cout << "Name                            | " << "Value" << std::endl;
			std::cout << "--------------------------------| " << "------" << std::endl;
			std::cout << "DISPMANX_NO_ROTATE              | 0x" << std::hex << std::setfill('0') << std::setw(8) << DISPMANX_NO_ROTATE << std::endl;
			std::cout << "DISPMANX_ROTATE_90              | 0x" << std::hex << std::setfill('0') << std::setw(8) << DISPMANX_ROTATE_90 << std::endl;
			std::cout << "DISPMANX_ROTATE_180             | 0x" << std::hex << std::setfill('0') << std::setw(8) << DISPMANX_ROTATE_180 << std::endl;
			std::cout << "DISPMANX_ROTATE_270             | 0x" << std::hex << std::setfill('0') << std::setw(8) << DISPMANX_ROTATE_270 << std::endl;

			std::cout << "DISPMANX_FLIP_HRIZ              | 0x" << std::hex << std::setfill('0') << std::setw(8) << DISPMANX_FLIP_HRIZ << std::endl;
			std::cout << "DISPMANX_FLIP_VERT              | 0x" << std::hex << std::setfill('0') << std::setw(8) << DISPMANX_FLIP_VERT << std::endl;

			std::cout << "DISPMANX_SNAPSHOT_NO_YUV        | 0x" << std::hex << std::setfill('0') << std::setw(8) << DISPMANX_SNAPSHOT_NO_YUV << std::endl;
			std::cout << "DISPMANX_SNAPSHOT_NO_RGB        | 0x" << std::hex << std::setfill('0') << std::setw(8) << DISPMANX_SNAPSHOT_NO_RGB << std::endl;
			std::cout << "DISPMANX_SNAPSHOT_FILL          | 0x" << std::hex << std::setfill('0') << std::setw(8) << DISPMANX_SNAPSHOT_FILL << std::endl;
			std::cout << "DISPMANX_SNAPSHOT_SWAP_RED_BLUE | 0x" << std::hex << std::setfill('0') << std::setw(8) << DISPMANX_SNAPSHOT_SWAP_RED_BLUE << std::endl;
			std::cout << "DISPMANX_SNAPSHOT_PACK          | 0x" << std::hex << std::setfill('0') << std::setw(8) << DISPMANX_SNAPSHOT_PACK << std::endl;
			return 0;
		}
		if (argFlags.isSet())
		{
			QString flagStr = QString::fromStdString(argFlags.getValue());

			bool ok = false;
//			grabFlags = flagStr.toInt(&ok);
			if (flagStr.startsWith("0x"))
			{
				grabFlags = flagStr.toInt(&ok, 16);
			}
			else
			{
				grabFlags = flagStr.toInt(&ok, 10);
			}
			std::cout << "Resulting flags: " << grabFlags << " (=0x" << std::hex << std::setfill('0') << std::setw(8) << grabFlags << ")" << std::dec << std::endl;
			if (!ok)
			{
				std::cerr << "Failed to parse flags (" << flagStr.toStdString().c_str() << ")" << std::endl;
				return -1;
			}
		}

		grabCount = argCount.getValue();
	}
	catch (const std::runtime_error & e)
	{
		// An error occured. Display error and quit
		std::cerr << e.what() << std::endl;
		return 1;
	}

	DispmanxFrameGrabber frameGrabber(64, 64);
	frameGrabber.setFlags(grabFlags);

	unsigned iFrame = 0;
	QImage qImage(64, 64, QImage::Format_ARGB32);
	Image<ColorRgba> imageRgba(64, 64);

	for (int i=0; i<grabCount || grabCount < 0; ++i)
	{
		frameGrabber.grabFrame(imageRgba);

		for (int iScanline=0; iScanline<qImage.height(); ++iScanline)
		{
			unsigned char* scanLinePtr = qImage.scanLine(iScanline);
			memcpy(scanLinePtr, imageRgba.memptr()+imageRgba.width()*iScanline, imageRgba.width()*sizeof(ColorRgba));
		}

		const QImage qImageSwp = qImage.rgbSwapped();
		qImageSwp.save(QString("HYPERION_f0x%1_%2.png").arg(grabFlags, 8, 16, QChar('0')).arg(iFrame));
		++iFrame;

		timespec sleepTime;
		sleepTime.tv_sec  = 1;
		sleepTime.tv_nsec = 0;
		nanosleep(&sleepTime, NULL);
	}

	return 0;
}

<commit_msg>fix compile on raspi<commit_after>
// STL includes
#include <csignal>
#include <iomanip>

// QT includes
#include <QImage>

// getoptPlusPLus includes
#include <getoptPlusPlus/getoptpp.h>

// Dispmanx grabber includes
#include <grabber/DispmanxFrameGrabber.h>

using namespace vlofgren;

static bool running = true;

void signal_handler(int signum)
{
	running = false;
}

int main(int argc, char** argv)
{
	signal(SIGTERM, signal_handler);
	signal(SIGINT,  signal_handler);

	int grabFlags = 0;
	int grabCount = -1;
	try
	{
		// create the option parser and initialize all parameters
		OptionsParser optionParser("Simple application to send a command to hyperion using the Json interface");
		ParameterSet & parameters = optionParser.getParameters();

		QString flagDescr = QString("Set the grab flags of the dispmanx frame grabber [default: 0x%1]").arg(grabFlags, 8, 16, QChar('0'));
		StringParameter   & argFlags = parameters.add<StringParameter>   ('f', "flags", flagDescr.toAscii().constData());
		IntParameter      & argCount = parameters.add<IntParameter>      ('n', "count", "Number of images to capture (default infinite)");
		argCount.setDefault(grabCount);
		SwitchParameter<> & argList  = parameters.add<SwitchParameter<> >('l', "list",  "List the possible flags");
		SwitchParameter<> & argHelp  = parameters.add<SwitchParameter<> >('h', "help",  "Show this help message and exit");

		// parse all options
		optionParser.parse(argc, const_cast<const char **>(argv));

		// check if we need to display the usage. exit if we do.
		if (argHelp.isSet())
		{
			optionParser.usage();
			return 0;
		}
		if (argList.isSet())
		{
			std::cout.width(15);
			std::cout.width(10);
			std::cout << "Possible DISPMANX flags: " << std::endl;
			std::cout << "Name                            | " << "Value" << std::endl;
			std::cout << "--------------------------------| " << "------" << std::endl;
			std::cout << "DISPMANX_NO_ROTATE              | 0x" << std::hex << std::setfill('0') << std::setw(8) << DISPMANX_NO_ROTATE << std::endl;
			std::cout << "DISPMANX_ROTATE_90              | 0x" << std::hex << std::setfill('0') << std::setw(8) << DISPMANX_ROTATE_90 << std::endl;
			std::cout << "DISPMANX_ROTATE_180             | 0x" << std::hex << std::setfill('0') << std::setw(8) << DISPMANX_ROTATE_180 << std::endl;
			std::cout << "DISPMANX_ROTATE_270             | 0x" << std::hex << std::setfill('0') << std::setw(8) << DISPMANX_ROTATE_270 << std::endl;

			std::cout << "DISPMANX_FLIP_HRIZ              | 0x" << std::hex << std::setfill('0') << std::setw(8) << DISPMANX_FLIP_HRIZ << std::endl;
			std::cout << "DISPMANX_FLIP_VERT              | 0x" << std::hex << std::setfill('0') << std::setw(8) << DISPMANX_FLIP_VERT << std::endl;

			std::cout << "DISPMANX_SNAPSHOT_NO_YUV        | 0x" << std::hex << std::setfill('0') << std::setw(8) << DISPMANX_SNAPSHOT_NO_YUV << std::endl;
			std::cout << "DISPMANX_SNAPSHOT_NO_RGB        | 0x" << std::hex << std::setfill('0') << std::setw(8) << DISPMANX_SNAPSHOT_NO_RGB << std::endl;
			std::cout << "DISPMANX_SNAPSHOT_FILL          | 0x" << std::hex << std::setfill('0') << std::setw(8) << DISPMANX_SNAPSHOT_FILL << std::endl;
			std::cout << "DISPMANX_SNAPSHOT_SWAP_RED_BLUE | 0x" << std::hex << std::setfill('0') << std::setw(8) << DISPMANX_SNAPSHOT_SWAP_RED_BLUE << std::endl;
			std::cout << "DISPMANX_SNAPSHOT_PACK          | 0x" << std::hex << std::setfill('0') << std::setw(8) << DISPMANX_SNAPSHOT_PACK << std::endl;
			return 0;
		}
		if (argFlags.isSet())
		{
			QString flagStr = QString::fromStdString(argFlags.getValue());

			bool ok = false;
//			grabFlags = flagStr.toInt(&ok);
			if (flagStr.startsWith("0x"))
			{
				grabFlags = flagStr.toInt(&ok, 16);
			}
			else
			{
				grabFlags = flagStr.toInt(&ok, 10);
			}
			std::cout << "Resulting flags: " << grabFlags << " (=0x" << std::hex << std::setfill('0') << std::setw(8) << grabFlags << ")" << std::dec << std::endl;
			if (!ok)
			{
				std::cerr << "Failed to parse flags (" << flagStr.toStdString().c_str() << ")" << std::endl;
				return -1;
			}
		}

		grabCount = argCount.getValue();
	}
	catch (const std::runtime_error & e)
	{
		// An error occured. Display error and quit
		std::cerr << e.what() << std::endl;
		return 1;
	}

	DispmanxFrameGrabber frameGrabber(64, 64);
	frameGrabber.setFlags(grabFlags);

	unsigned iFrame = 0;
	QImage qImage(64, 64, QImage::Format_ARGB32);
	Image<ColorRgba> imageRgba(64, 64);

	for (int i=0; i<grabCount || grabCount < 0; ++i)
	{
		frameGrabber.grabFrame(imageRgba);

		for (int iScanline=0; iScanline<qImage.height(); ++iScanline)
		{
			unsigned char* scanLinePtr = qImage.scanLine(iScanline);
			memcpy(scanLinePtr, imageRgba.memptr()+imageRgba.width()*iScanline, imageRgba.width()*sizeof(ColorRgba));
		}

		const QImage qImageSwp = qImage.rgbSwapped();
		qImageSwp.save(QString("HYPERION_f0x%1_%2.png").arg(grabFlags, 8, 16, QChar('0')).arg(iFrame));
		++iFrame;

		timespec sleepTime;
		sleepTime.tv_sec  = 1;
		sleepTime.tv_nsec = 0;
		nanosleep(&sleepTime, NULL);
	}

	return 0;
}

<|endoftext|>


<commit_before>/*=========================================================================

  Program:   Insight Segmentation & Registration Toolkit
  Module:    itkObjectFactoryBase.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) 2000 National Library of Medicine
  All rights reserved.

  See COPYRIGHT.txt for copyright details.

=========================================================================*/
// Disable warning for long symbol names in this file only
#ifdef _MSC_VER
#pragma warning ( disable : 4786 )
#endif

#include "itkObjectFactoryBase.h"
#include "itkDynamicLoader.h"
#include "itkDirectory.h"
#include "itkVersion.h"
#include <stdlib.h>
#include <ctype.h>
#include <algorithm>
#include <map>

// Create a sub class to shrink the size of the symbols
// Also, so a forward reference can be put in itkObjectFactoryBase.h
// and a pointer member can be used.  This avoids other
// classes including <map> and getting long symbol warnings.
typedef std::multimap<std::string, itkObjectFactoryBase::OverrideInformation> itkStringOverMap;

class itkOverRideMap : public itkStringOverMap
{
public:
};

// Initialize static list of factories.
//
std::list<itkObjectFactoryBase*>*
  itkObjectFactoryBase::m_RegisteredFactories = 0;

//----------------------------------------------------------------------------
// Create an instance of a named itk object using the loaded
// factories
itkObject*
itkObjectFactoryBase
::CreateInstance(const char* itkclassname)
{
  if ( !itkObjectFactoryBase::m_RegisteredFactories )
    {
    itkObjectFactoryBase::Initialize();
    }

  for ( std::list<itkObjectFactoryBase*>::iterator
      i = m_RegisteredFactories->begin();
      i != m_RegisteredFactories->end(); ++i )
    {
    itkObject* newobject = (*i)->CreateObject(itkclassname);
    if(newobject)
      {
      return newobject;
      }
    }
  return 0;
}

//----------------------------------------------------------------------------
// A one time initialization method.
void
itkObjectFactoryBase
::Initialize()
{
  // Don't do anything if we are already initialized
  if ( itkObjectFactoryBase::m_RegisteredFactories )
    {
    return;
    }

  itkObjectFactoryBase::m_RegisteredFactories =
    new std::list<itkObjectFactoryBase*>;
  itkObjectFactoryBase::RegisterDefaults();
  itkObjectFactoryBase::LoadDynamicFactories();
}

//----------------------------------------------------------------------------
// Register any factories that are always present in ITK like
// the OpenGL factory, currently this is not done.
void
itkObjectFactoryBase
::RegisterDefaults()
{
}

// Load all libraries in ITK_AUTOLOAD_PATH
void
itkObjectFactoryBase
::LoadDynamicFactories()
{
  // follow PATH conventions
#ifdef _WIN32
  char PathSeparator = ';';
#else
  char PathSeparator = ':';
#endif

  std::string LoadPath;
  if (getenv("ITK_AUTOLOAD_PATH"))
    {
    LoadPath = getenv("ITK_AUTOLOAD_PATH");
    }
  else
    {
    return;
    }

  if(LoadPath.size() == 0)
    {
    return;
    }
  std::string::size_type EndSeparatorPosition = 0;
  std::string::size_type StartSeparatorPosition = 0;
  while ( StartSeparatorPosition != std::string::npos )
    {
    StartSeparatorPosition = EndSeparatorPosition;
    // find PathSeparator in LoadPath
    EndSeparatorPosition = LoadPath.find(PathSeparator, EndSeparatorPosition);
    if(EndSeparatorPosition != std::string::npos)
      {
      EndSeparatorPosition = LoadPath.size();
      }
    std::string CurrentPath =
      LoadPath.substr(StartSeparatorPosition, EndSeparatorPosition);
    itkObjectFactoryBase::LoadLibrariesInPath(CurrentPath.c_str());
    // move past separator
    EndSeparatorPosition++;
  }
}

//----------------------------------------------------------------------------
// A file scope helper function to concat path and file into
// a full path
static std::string
CreateFullPath(const char* path, const char* file)
{
  std::string ret;
#ifdef _WIN32
  const char sep = '\\';
#else
  const char sep = '/';
#endif
  // make sure the end of path is a separator
  ret = path;
  if ( ret[ret.size()-1] != sep )
    {
    ret.append(1, sep);
    }
  ret.append(file);
  return ret;
}

// A file scope typedef to make the cast code to the load
// function cleaner to read.
typedef itkObjectFactoryBase* (* ITK_LOAD_FUNCTION)();

//----------------------------------------------------------------------------
// A file scoped function to determine if a file has
// the shared library extension in its name, this converts name to lower
// case before the compare, itkDynamicLoader always uses
// lower case for LibExtension values.
inline bool
itkNameIsSharedLibrary(const char* name)
{
  std::string sname = name;
  if ( sname.find(itkDynamicLoader::LibExtension()) != std::string::npos )
    {
    return true;
    }
  return false;
}

//----------------------------------------------------------------------------
void
itkObjectFactoryBase
::LoadLibrariesInPath(const char* path)
{
  itkDirectory* dir = itkDirectory::New();
  if ( !dir->Load(path) )
    {
    return;
    }

  // Attempt to load each file in the directory as a shared library
  for ( int i = 0; i < dir->GetNumberOfFiles(); i++ )
    {
    const char* file = dir->GetFile(i);
    // try to make sure the file has at least the extension
    // for a shared library in it.
    if ( itkNameIsSharedLibrary(file) )
      {
      std::string fullpath = CreateFullPath(path, file);
      itkLibHandle lib = itkDynamicLoader::OpenLibrary(fullpath.c_str());
      if ( lib )
        {
        // Look for the symbol itkLoad in the library
        ITK_LOAD_FUNCTION loadfunction
          = (ITK_LOAD_FUNCTION)itkDynamicLoader::GetSymbolAddress(lib, "itkLoad");
        // if the symbol is found call it to create the factory
        // from the library
        if ( loadfunction )
          {
          itkObjectFactoryBase* newfactory = (*loadfunction)();
          // initialize class members if load worked
          newfactory->m_LibraryHandle = (void*)lib;
          newfactory->m_LibraryPath = fullpath;
          newfactory->m_LibraryDate = 0; // unused for now...
          itkObjectFactoryBase::RegisterFactory(newfactory);
          }
        }
      }
    }
}

//----------------------------------------------------------------------------
// Recheck the ITK_AUTOLOAD_PATH for new libraries
void
itkObjectFactoryBase
::ReHash()
{
  itkObjectFactoryBase::UnRegisterAllFactories();
  itkObjectFactoryBase::Initialize();
}

// initialize class members
itkObjectFactoryBase::itkObjectFactoryBase()
{
  m_LibraryHandle = 0;
  m_LibraryDate = 0;
  m_OverrideMap = new itkOverRideMap;
}

//----------------------------------------------------------------------------
// Unload the library and free the path string
itkObjectFactoryBase
::~itkObjectFactoryBase()
{
  itkDynamicLoader::CloseLibrary((itkLibHandle)m_LibraryHandle);
}

//----------------------------------------------------------------------------
// Add a factory to the registered list
void
itkObjectFactoryBase
::RegisterFactory(itkObjectFactoryBase* factory)
{
  if ( factory->m_LibraryHandle == 0 )
    {
    const char* nonDynamicName = "Non-Dynamicly loaded factory";
    factory->m_LibraryPath = nonDynamicName;
    }
  if ( strcmp(factory->GetITKSourceVersion(),
            itkVersion::GetITKSourceVersion()) != 0 )
    {
    itkWarningMacro(<< "Possible incompatible factory load:"
    << "\nRunning itk version :\n" << itkVersion::GetITKSourceVersion()
    << "\nLoaded Factory version:\n" << factory->GetITKSourceVersion()
    << "\nLoading factory:\n" << factory->m_LibraryPath << "\n");
    }
  itkObjectFactoryBase::Initialize();
  itkObjectFactoryBase::m_RegisteredFactories->push_back(factory);
  factory->Register();
}

//----------------------------------------------------------------------------
void
itkObjectFactoryBase
::PrintSelf(std::ostream& os, itkIndent indent)
{
  itkObject::PrintSelf(os, indent);

  os << indent << "Factory DLL path: " << m_LibraryPath << "\n";
  os << indent << "Factory description: " << this->GetDescription() << std::endl;

  int num = m_OverrideMap->size();
  os << indent << "Factory overides " << num << " classes:" << std::endl;

  indent = indent.GetNextIndent();
  for(itkOverRideMap::iterator i = m_OverrideMap->begin();
      i != m_OverrideMap->end(); ++i)
    {
    os << indent << "Class : " <<  (*i).first
       << std::endl;
    os << indent << "Overriden with: " <<  (*i).second.m_OverrideWithName
       << std::endl;
    os << indent << "Enable flag: " << (*i).second.m_EnabledFlag
       << std::endl;
    os << std::endl;
  }
}

//----------------------------------------------------------------------------
void
itkObjectFactoryBase
::UnRegisterFactory(itkObjectFactoryBase* factory)
{
  for ( std::list<itkObjectFactoryBase*>::iterator i =
        m_RegisteredFactories->begin();
      i != m_RegisteredFactories->end(); ++i )
    {
    if ( factory == *i )
      {
      m_RegisteredFactories->remove(factory);
      factory->UnRegister();
      return;
      }
    }
}

//----------------------------------------------------------------------------
// unregister all factories and delete the RegisteredFactories list
void
itkObjectFactoryBase
::UnRegisterAllFactories()
{
  itkObjectFactoryBase* factory = 0;
  for ( std::list<itkObjectFactoryBase*>::iterator i
        = m_RegisteredFactories->begin();
      i != m_RegisteredFactories->end(); ++i )
    {
    (*i)->UnRegister();
    }
  delete itkObjectFactoryBase::m_RegisteredFactories;
  itkObjectFactoryBase::m_RegisteredFactories = 0;
}

//----------------------------------------------------------------------------
void
itkObjectFactoryBase
::RegisterOverride(const char* classOverride,
                   const char* subclass,
                   const char* description,
                   bool enableFlag,
                   itkCreateObjectFunctionBase*
                   createFunction)
{
  itkObjectFactoryBase::OverrideInformation info;
  info.m_Description = description;
  info.m_OverrideWithName = subclass;
  info.m_EnabledFlag = enableFlag;
  info.m_CreateObject = createFunction;
  m_OverrideMap->insert(itkOverRideMap::value_type(classOverride, info));
}

//----------------------------------------------------------------------------
itkObject*
itkObjectFactoryBase
::CreateObject(const char* itkclassname)
{
  m_OverrideMap->find(itkclassname);
  itkOverRideMap::iterator pos = m_OverrideMap->find(itkclassname);
  if ( pos != m_OverrideMap->end() )
    {
    return (*pos).second.m_CreateObject->CreateObject();
    }
  return 0;
}

//----------------------------------------------------------------------------
void
itkObjectFactoryBase
::SetEnableFlag(bool flag,
                const char* className,
                const char* subclassName)
{
  itkOverRideMap::iterator start = m_OverrideMap->lower_bound(className);
  itkOverRideMap::iterator end = m_OverrideMap->upper_bound(className);
  for ( itkOverRideMap::iterator i = start; i != end; ++i )
    {
    if ( (*i).second.m_OverrideWithName == subclassName )
      {
      (*i).second.m_EnabledFlag = flag;
      }
    }
}

//----------------------------------------------------------------------------
bool
itkObjectFactoryBase
::GetEnableFlag(const char* className, const char* subclassName)
{
  itkOverRideMap::iterator start = m_OverrideMap->lower_bound(className);
  itkOverRideMap::iterator end = m_OverrideMap->upper_bound(className);
  for ( itkOverRideMap::iterator i = start; i != end; ++i )
    {
    if ( (*i).second.m_OverrideWithName == subclassName )
      {
      return (*i).second.m_EnabledFlag;
      }
    }
  return 0;
}

//----------------------------------------------------------------------------
void
itkObjectFactoryBase
::Disable(const char* className)
{
  itkOverRideMap::iterator start = m_OverrideMap->lower_bound(className);
  itkOverRideMap::iterator end = m_OverrideMap->upper_bound(className);
  for ( itkOverRideMap::iterator i = start; i != end; ++i )
    {
    (*i).second.m_EnabledFlag = 0;
    }
}

//----------------------------------------------------------------------------
std::list<itkObjectFactoryBase*>
itkObjectFactoryBase
::GetRegisteredFactories()
{
  return *itkObjectFactoryBase::m_RegisteredFactories;
}

//----------------------------------------------------------------------------
// Return a list of classes that this factory overrides.
std::list<std::string>
itkObjectFactoryBase
::GetClassOverrideNames()
{
  std::list<std::string> ret;
  for ( itkOverRideMap::iterator i = m_OverrideMap->begin();
      i != m_OverrideMap->end(); ++i )
    {
    ret.push_back((*i).first);
    }
  return ret;
}

//----------------------------------------------------------------------------
// Return a list of the names of classes that override classes.
std::list<std::string>
itkObjectFactoryBase
::GetClassOverrideWithNames()
{
  std::list<std::string> ret;
  for ( itkOverRideMap::iterator i = m_OverrideMap->begin();
      i != m_OverrideMap->end(); ++i )
    {
    ret.push_back((*i).second.m_OverrideWithName);
    }
  return ret;
}

//----------------------------------------------------------------------------
// Retrun a list of descriptions for class overrides
std::list<std::string>
itkObjectFactoryBase
::GetClassOverrideDescriptions()
{
  std::list<std::string> ret;
  for ( itkOverRideMap::iterator i = m_OverrideMap->begin();
      i != m_OverrideMap->end(); ++i )
    {
    ret.push_back((*i).second.m_Description);
    }
  return ret;
}

//----------------------------------------------------------------------------
// Return a list of enable flags
std::list<bool>
itkObjectFactoryBase
::GetEnableFlags()
{
  std::list<bool> ret;
  for( itkOverRideMap::iterator i = m_OverrideMap->begin();
      i != m_OverrideMap->end(); ++i)
    {
    ret.push_back((*i).second.m_EnabledFlag);
    }
  return ret;
}

<commit_msg>ENH: unused variable 'factory' removed.<commit_after>/*=========================================================================

  Program:   Insight Segmentation & Registration Toolkit
  Module:    itkObjectFactoryBase.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) 2000 National Library of Medicine
  All rights reserved.

  See COPYRIGHT.txt for copyright details.

=========================================================================*/
// Disable warning for long symbol names in this file only
#ifdef _MSC_VER
#pragma warning ( disable : 4786 )
#endif

#include "itkObjectFactoryBase.h"
#include "itkDynamicLoader.h"
#include "itkDirectory.h"
#include "itkVersion.h"
#include <stdlib.h>
#include <ctype.h>
#include <algorithm>
#include <map>

// Create a sub class to shrink the size of the symbols
// Also, so a forward reference can be put in itkObjectFactoryBase.h
// and a pointer member can be used.  This avoids other
// classes including <map> and getting long symbol warnings.
typedef std::multimap<std::string, itkObjectFactoryBase::OverrideInformation> itkStringOverMap;

class itkOverRideMap : public itkStringOverMap
{
public:
};

// Initialize static list of factories.
//
std::list<itkObjectFactoryBase*>*
  itkObjectFactoryBase::m_RegisteredFactories = 0;

//----------------------------------------------------------------------------
// Create an instance of a named itk object using the loaded
// factories
itkObject*
itkObjectFactoryBase
::CreateInstance(const char* itkclassname)
{
  if ( !itkObjectFactoryBase::m_RegisteredFactories )
    {
    itkObjectFactoryBase::Initialize();
    }

  for ( std::list<itkObjectFactoryBase*>::iterator
      i = m_RegisteredFactories->begin();
      i != m_RegisteredFactories->end(); ++i )
    {
    itkObject* newobject = (*i)->CreateObject(itkclassname);
    if(newobject)
      {
      return newobject;
      }
    }
  return 0;
}

//----------------------------------------------------------------------------
// A one time initialization method.
void
itkObjectFactoryBase
::Initialize()
{
  // Don't do anything if we are already initialized
  if ( itkObjectFactoryBase::m_RegisteredFactories )
    {
    return;
    }

  itkObjectFactoryBase::m_RegisteredFactories =
    new std::list<itkObjectFactoryBase*>;
  itkObjectFactoryBase::RegisterDefaults();
  itkObjectFactoryBase::LoadDynamicFactories();
}

//----------------------------------------------------------------------------
// Register any factories that are always present in ITK like
// the OpenGL factory, currently this is not done.
void
itkObjectFactoryBase
::RegisterDefaults()
{
}

// Load all libraries in ITK_AUTOLOAD_PATH
void
itkObjectFactoryBase
::LoadDynamicFactories()
{
  // follow PATH conventions
#ifdef _WIN32
  char PathSeparator = ';';
#else
  char PathSeparator = ':';
#endif

  std::string LoadPath;
  if (getenv("ITK_AUTOLOAD_PATH"))
    {
    LoadPath = getenv("ITK_AUTOLOAD_PATH");
    }
  else
    {
    return;
    }

  if(LoadPath.size() == 0)
    {
    return;
    }
  std::string::size_type EndSeparatorPosition = 0;
  std::string::size_type StartSeparatorPosition = 0;
  while ( StartSeparatorPosition != std::string::npos )
    {
    StartSeparatorPosition = EndSeparatorPosition;
    // find PathSeparator in LoadPath
    EndSeparatorPosition = LoadPath.find(PathSeparator, EndSeparatorPosition);
    if(EndSeparatorPosition != std::string::npos)
      {
      EndSeparatorPosition = LoadPath.size();
      }
    std::string CurrentPath =
      LoadPath.substr(StartSeparatorPosition, EndSeparatorPosition);
    itkObjectFactoryBase::LoadLibrariesInPath(CurrentPath.c_str());
    // move past separator
    EndSeparatorPosition++;
  }
}

//----------------------------------------------------------------------------
// A file scope helper function to concat path and file into
// a full path
static std::string
CreateFullPath(const char* path, const char* file)
{
  std::string ret;
#ifdef _WIN32
  const char sep = '\\';
#else
  const char sep = '/';
#endif
  // make sure the end of path is a separator
  ret = path;
  if ( ret[ret.size()-1] != sep )
    {
    ret.append(1, sep);
    }
  ret.append(file);
  return ret;
}

// A file scope typedef to make the cast code to the load
// function cleaner to read.
typedef itkObjectFactoryBase* (* ITK_LOAD_FUNCTION)();

//----------------------------------------------------------------------------
// A file scoped function to determine if a file has
// the shared library extension in its name, this converts name to lower
// case before the compare, itkDynamicLoader always uses
// lower case for LibExtension values.
inline bool
itkNameIsSharedLibrary(const char* name)
{
  std::string sname = name;
  if ( sname.find(itkDynamicLoader::LibExtension()) != std::string::npos )
    {
    return true;
    }
  return false;
}

//----------------------------------------------------------------------------
void
itkObjectFactoryBase
::LoadLibrariesInPath(const char* path)
{
  itkDirectory* dir = itkDirectory::New();
  if ( !dir->Load(path) )
    {
    return;
    }

  // Attempt to load each file in the directory as a shared library
  for ( int i = 0; i < dir->GetNumberOfFiles(); i++ )
    {
    const char* file = dir->GetFile(i);
    // try to make sure the file has at least the extension
    // for a shared library in it.
    if ( itkNameIsSharedLibrary(file) )
      {
      std::string fullpath = CreateFullPath(path, file);
      itkLibHandle lib = itkDynamicLoader::OpenLibrary(fullpath.c_str());
      if ( lib )
        {
        // Look for the symbol itkLoad in the library
        ITK_LOAD_FUNCTION loadfunction
          = (ITK_LOAD_FUNCTION)itkDynamicLoader::GetSymbolAddress(lib, "itkLoad");
        // if the symbol is found call it to create the factory
        // from the library
        if ( loadfunction )
          {
          itkObjectFactoryBase* newfactory = (*loadfunction)();
          // initialize class members if load worked
          newfactory->m_LibraryHandle = (void*)lib;
          newfactory->m_LibraryPath = fullpath;
          newfactory->m_LibraryDate = 0; // unused for now...
          itkObjectFactoryBase::RegisterFactory(newfactory);
          }
        }
      }
    }
}

//----------------------------------------------------------------------------
// Recheck the ITK_AUTOLOAD_PATH for new libraries
void
itkObjectFactoryBase
::ReHash()
{
  itkObjectFactoryBase::UnRegisterAllFactories();
  itkObjectFactoryBase::Initialize();
}

// initialize class members
itkObjectFactoryBase::itkObjectFactoryBase()
{
  m_LibraryHandle = 0;
  m_LibraryDate = 0;
  m_OverrideMap = new itkOverRideMap;
}

//----------------------------------------------------------------------------
// Unload the library and free the path string
itkObjectFactoryBase
::~itkObjectFactoryBase()
{
  itkDynamicLoader::CloseLibrary((itkLibHandle)m_LibraryHandle);
}

//----------------------------------------------------------------------------
// Add a factory to the registered list
void
itkObjectFactoryBase
::RegisterFactory(itkObjectFactoryBase* factory)
{
  if ( factory->m_LibraryHandle == 0 )
    {
    const char* nonDynamicName = "Non-Dynamicly loaded factory";
    factory->m_LibraryPath = nonDynamicName;
    }
  if ( strcmp(factory->GetITKSourceVersion(),
            itkVersion::GetITKSourceVersion()) != 0 )
    {
    itkWarningMacro(<< "Possible incompatible factory load:"
    << "\nRunning itk version :\n" << itkVersion::GetITKSourceVersion()
    << "\nLoaded Factory version:\n" << factory->GetITKSourceVersion()
    << "\nLoading factory:\n" << factory->m_LibraryPath << "\n");
    }
  itkObjectFactoryBase::Initialize();
  itkObjectFactoryBase::m_RegisteredFactories->push_back(factory);
  factory->Register();
}

//----------------------------------------------------------------------------
void
itkObjectFactoryBase
::PrintSelf(std::ostream& os, itkIndent indent)
{
  itkObject::PrintSelf(os, indent);

  os << indent << "Factory DLL path: " << m_LibraryPath << "\n";
  os << indent << "Factory description: " << this->GetDescription() << std::endl;

  int num = m_OverrideMap->size();
  os << indent << "Factory overides " << num << " classes:" << std::endl;

  indent = indent.GetNextIndent();
  for(itkOverRideMap::iterator i = m_OverrideMap->begin();
      i != m_OverrideMap->end(); ++i)
    {
    os << indent << "Class : " <<  (*i).first
       << std::endl;
    os << indent << "Overriden with: " <<  (*i).second.m_OverrideWithName
       << std::endl;
    os << indent << "Enable flag: " << (*i).second.m_EnabledFlag
       << std::endl;
    os << std::endl;
  }
}

//----------------------------------------------------------------------------
void
itkObjectFactoryBase
::UnRegisterFactory(itkObjectFactoryBase* factory)
{
  for ( std::list<itkObjectFactoryBase*>::iterator i =
        m_RegisteredFactories->begin();
      i != m_RegisteredFactories->end(); ++i )
    {
    if ( factory == *i )
      {
      m_RegisteredFactories->remove(factory);
      factory->UnRegister();
      return;
      }
    }
}

//----------------------------------------------------------------------------
// unregister all factories and delete the RegisteredFactories list
void
itkObjectFactoryBase
::UnRegisterAllFactories()
{
  for ( std::list<itkObjectFactoryBase*>::iterator i
        = m_RegisteredFactories->begin();
      i != m_RegisteredFactories->end(); ++i )
    {
    (*i)->UnRegister();
    }
  delete itkObjectFactoryBase::m_RegisteredFactories;
  itkObjectFactoryBase::m_RegisteredFactories = 0;
}

//----------------------------------------------------------------------------
void
itkObjectFactoryBase
::RegisterOverride(const char* classOverride,
                   const char* subclass,
                   const char* description,
                   bool enableFlag,
                   itkCreateObjectFunctionBase*
                   createFunction)
{
  itkObjectFactoryBase::OverrideInformation info;
  info.m_Description = description;
  info.m_OverrideWithName = subclass;
  info.m_EnabledFlag = enableFlag;
  info.m_CreateObject = createFunction;
  m_OverrideMap->insert(itkOverRideMap::value_type(classOverride, info));
}

//----------------------------------------------------------------------------
itkObject*
itkObjectFactoryBase
::CreateObject(const char* itkclassname)
{
  m_OverrideMap->find(itkclassname);
  itkOverRideMap::iterator pos = m_OverrideMap->find(itkclassname);
  if ( pos != m_OverrideMap->end() )
    {
    return (*pos).second.m_CreateObject->CreateObject();
    }
  return 0;
}

//----------------------------------------------------------------------------
void
itkObjectFactoryBase
::SetEnableFlag(bool flag,
                const char* className,
                const char* subclassName)
{
  itkOverRideMap::iterator start = m_OverrideMap->lower_bound(className);
  itkOverRideMap::iterator end = m_OverrideMap->upper_bound(className);
  for ( itkOverRideMap::iterator i = start; i != end; ++i )
    {
    if ( (*i).second.m_OverrideWithName == subclassName )
      {
      (*i).second.m_EnabledFlag = flag;
      }
    }
}

//----------------------------------------------------------------------------
bool
itkObjectFactoryBase
::GetEnableFlag(const char* className, const char* subclassName)
{
  itkOverRideMap::iterator start = m_OverrideMap->lower_bound(className);
  itkOverRideMap::iterator end = m_OverrideMap->upper_bound(className);
  for ( itkOverRideMap::iterator i = start; i != end; ++i )
    {
    if ( (*i).second.m_OverrideWithName == subclassName )
      {
      return (*i).second.m_EnabledFlag;
      }
    }
  return 0;
}

//----------------------------------------------------------------------------
void
itkObjectFactoryBase
::Disable(const char* className)
{
  itkOverRideMap::iterator start = m_OverrideMap->lower_bound(className);
  itkOverRideMap::iterator end = m_OverrideMap->upper_bound(className);
  for ( itkOverRideMap::iterator i = start; i != end; ++i )
    {
    (*i).second.m_EnabledFlag = 0;
    }
}

//----------------------------------------------------------------------------
std::list<itkObjectFactoryBase*>
itkObjectFactoryBase
::GetRegisteredFactories()
{
  return *itkObjectFactoryBase::m_RegisteredFactories;
}

//----------------------------------------------------------------------------
// Return a list of classes that this factory overrides.
std::list<std::string>
itkObjectFactoryBase
::GetClassOverrideNames()
{
  std::list<std::string> ret;
  for ( itkOverRideMap::iterator i = m_OverrideMap->begin();
      i != m_OverrideMap->end(); ++i )
    {
    ret.push_back((*i).first);
    }
  return ret;
}

//----------------------------------------------------------------------------
// Return a list of the names of classes that override classes.
std::list<std::string>
itkObjectFactoryBase
::GetClassOverrideWithNames()
{
  std::list<std::string> ret;
  for ( itkOverRideMap::iterator i = m_OverrideMap->begin();
      i != m_OverrideMap->end(); ++i )
    {
    ret.push_back((*i).second.m_OverrideWithName);
    }
  return ret;
}

//----------------------------------------------------------------------------
// Retrun a list of descriptions for class overrides
std::list<std::string>
itkObjectFactoryBase
::GetClassOverrideDescriptions()
{
  std::list<std::string> ret;
  for ( itkOverRideMap::iterator i = m_OverrideMap->begin();
      i != m_OverrideMap->end(); ++i )
    {
    ret.push_back((*i).second.m_Description);
    }
  return ret;
}

//----------------------------------------------------------------------------
// Return a list of enable flags
std::list<bool>
itkObjectFactoryBase
::GetEnableFlags()
{
  std::list<bool> ret;
  for( itkOverRideMap::iterator i = m_OverrideMap->begin();
      i != m_OverrideMap->end(); ++i)
    {
    ret.push_back((*i).second.m_EnabledFlag);
    }
  return ret;
}

<|endoftext|>


<commit_before>
/*
 * Copyright 2010 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "GrBufferAllocPool.h"
#include "GrTypes.h"
#include "GrVertexBuffer.h"
#include "GrIndexBuffer.h"
#include "GrGpu.h"

#if GR_DEBUG
    #define VALIDATE validate
#else
    static void VALIDATE(bool x = false) {}
#endif

// page size
#define GrBufferAllocPool_MIN_BLOCK_SIZE ((size_t)1 << 12)

GrBufferAllocPool::GrBufferAllocPool(GrGpu* gpu,
                                     BufferType bufferType,
                                     bool frequentResetHint,
                                     size_t blockSize,
                                     int preallocBufferCnt) :
        fBlocks(GrMax(8, 2*preallocBufferCnt)) {

    GrAssert(NULL != gpu);
    fGpu = gpu;
    fGpu->ref();
    fGpuIsReffed = true;

    fBufferType = bufferType;
    fFrequentResetHint = frequentResetHint;
    fBufferPtr = NULL;
    fMinBlockSize = GrMax(GrBufferAllocPool_MIN_BLOCK_SIZE, blockSize);

    fBytesInUse = 0;

    fPreallocBuffersInUse = 0;
    fFirstPreallocBuffer = 0;
    for (int i = 0; i < preallocBufferCnt; ++i) {
        GrGeometryBuffer* buffer = this->createBuffer(fMinBlockSize);
        if (NULL != buffer) {
            *fPreallocBuffers.append() = buffer;
            buffer->ref();
        }
    }
}

GrBufferAllocPool::~GrBufferAllocPool() {
    VALIDATE();
    if (fBlocks.count()) {
        GrGeometryBuffer* buffer = fBlocks.back().fBuffer;
        if (buffer->isLocked()) {
            buffer->unlock();
        }
    }
    while (!fBlocks.empty()) {
        destroyBlock();
    }
    fPreallocBuffers.unrefAll();
    releaseGpuRef();
}

void GrBufferAllocPool::releaseGpuRef() {
    if (fGpuIsReffed) {
        fGpu->unref();
        fGpuIsReffed = false;
    }
}

void GrBufferAllocPool::reset() {
    VALIDATE();
    fBytesInUse = 0;
    if (fBlocks.count()) {
        GrGeometryBuffer* buffer = fBlocks.back().fBuffer;
        if (buffer->isLocked()) {
            buffer->unlock();
        }
    }
    while (!fBlocks.empty()) {
        destroyBlock();
    }
    if (fPreallocBuffers.count()) {
        // must set this after above loop.
        fFirstPreallocBuffer = (fFirstPreallocBuffer + fPreallocBuffersInUse) %
                               fPreallocBuffers.count();
    }
    fCpuData.reset(fGpu->getCaps().fBufferLockSupport ? 0 : fMinBlockSize);
    GrAssert(0 == fPreallocBuffersInUse);
    VALIDATE();
}

void GrBufferAllocPool::unlock() {
    VALIDATE();

    if (NULL != fBufferPtr) {
        BufferBlock& block = fBlocks.back();
        if (block.fBuffer->isLocked()) {
            block.fBuffer->unlock();
        } else {
            size_t flushSize = block.fBuffer->sizeInBytes() - block.fBytesFree;
            flushCpuData(fBlocks.back().fBuffer, flushSize);
        }
        fBufferPtr = NULL;
    }
    VALIDATE();
}

#if GR_DEBUG
void GrBufferAllocPool::validate(bool unusedBlockAllowed) const {
    if (NULL != fBufferPtr) {
        GrAssert(!fBlocks.empty());
        if (fBlocks.back().fBuffer->isLocked()) {
            GrGeometryBuffer* buf = fBlocks.back().fBuffer;
            GrAssert(buf->lockPtr() == fBufferPtr);
        } else {
            GrAssert(fCpuData.get() == fBufferPtr);
        }
    } else {
        GrAssert(fBlocks.empty() || !fBlocks.back().fBuffer->isLocked());
    }
    size_t bytesInUse = 0;
    for (int i = 0; i < fBlocks.count() - 1; ++i) {
        GrAssert(!fBlocks[i].fBuffer->isLocked());
    }
    for (int i = 0; i < fBlocks.count(); ++i) {
        size_t bytes = fBlocks[i].fBuffer->sizeInBytes() - fBlocks[i].fBytesFree;
        bytesInUse += bytes;
        GrAssert(bytes || unusedBlockAllowed);
    }

    GrAssert(bytesInUse == fBytesInUse);
    if (unusedBlockAllowed) {
        GrAssert((fBytesInUse && !fBlocks.empty()) ||
                 (!fBytesInUse && (fBlocks.count() < 2)));
    } else {
        GrAssert((0 == fBytesInUse) == fBlocks.empty());
    }
}
#endif

void* GrBufferAllocPool::makeSpace(size_t size,
                                   size_t alignment,
                                   const GrGeometryBuffer** buffer,
                                   size_t* offset) {
    VALIDATE();

    GrAssert(NULL != buffer);
    GrAssert(NULL != offset);

    if (NULL != fBufferPtr) {
        BufferBlock& back = fBlocks.back();
        size_t usedBytes = back.fBuffer->sizeInBytes() - back.fBytesFree;
        size_t pad = GrSizeAlignUpPad(usedBytes,
                                      alignment);
        if ((size + pad) <= back.fBytesFree) {
            usedBytes += pad;
            *offset = usedBytes;
            *buffer = back.fBuffer;
            back.fBytesFree -= size + pad;
            fBytesInUse += size;
            return (void*)(reinterpret_cast<intptr_t>(fBufferPtr) + usedBytes);
        }
    }

    // We could honor the space request using by a partial update of the current
    // VB (if there is room). But we don't currently use draw calls to GL that
    // allow the driver to know that previously issued draws won't read from
    // the part of the buffer we update. Also, the GL buffer implementation
    // may be cheating on the actual buffer size by shrinking the buffer on
    // updateData() if the amount of data passed is less than the full buffer
    // size.

    if (!createBlock(size)) {
        return NULL;
    }
    GrAssert(NULL != fBufferPtr);

    *offset = 0;
    BufferBlock& back = fBlocks.back();
    *buffer = back.fBuffer;
    back.fBytesFree -= size;
    fBytesInUse += size;
    VALIDATE();
    return fBufferPtr;
}

int GrBufferAllocPool::currentBufferItems(size_t itemSize) const {
    VALIDATE();
    if (NULL != fBufferPtr) {
        const BufferBlock& back = fBlocks.back();
        size_t usedBytes = back.fBuffer->sizeInBytes() - back.fBytesFree;
        size_t pad = GrSizeAlignUpPad(usedBytes, itemSize);
        return (back.fBytesFree - pad) / itemSize;
    } else if (fPreallocBuffersInUse < fPreallocBuffers.count()) {
        return fMinBlockSize / itemSize;
    }
    return 0;
}

int GrBufferAllocPool::preallocatedBuffersRemaining() const {
    return fPreallocBuffers.count() - fPreallocBuffersInUse;
}

int GrBufferAllocPool::preallocatedBufferCount() const {
    return fPreallocBuffers.count();
}

void GrBufferAllocPool::putBack(size_t bytes) {
    VALIDATE();

    while (bytes) {
        // caller shouldnt try to put back more than they've taken
        GrAssert(!fBlocks.empty());
        BufferBlock& block = fBlocks.back();
        size_t bytesUsed = block.fBuffer->sizeInBytes() - block.fBytesFree;
        if (bytes >= bytesUsed) {
            bytes -= bytesUsed;
            fBytesInUse -= bytesUsed;
            // if we locked a vb to satisfy the make space and we're releasing
            // beyond it, then unlock it.
            if (block.fBuffer->isLocked()) {
                block.fBuffer->unlock();
            }
            this->destroyBlock();
        } else {
            block.fBytesFree += bytes;
            fBytesInUse -= bytes;
            bytes = 0;
            break;
        }
    }
    VALIDATE();
}

bool GrBufferAllocPool::createBlock(size_t requestSize) {

    size_t size = GrMax(requestSize, fMinBlockSize);
    GrAssert(size >= GrBufferAllocPool_MIN_BLOCK_SIZE);

    VALIDATE();

    BufferBlock& block = fBlocks.push_back();

    if (size == fMinBlockSize &&
        fPreallocBuffersInUse < fPreallocBuffers.count()) {

        uint32_t nextBuffer = (fPreallocBuffersInUse + fFirstPreallocBuffer) %
                               fPreallocBuffers.count();
        block.fBuffer = fPreallocBuffers[nextBuffer];
        block.fBuffer->ref();
        ++fPreallocBuffersInUse;
    } else {
        block.fBuffer = this->createBuffer(size);
        if (NULL == block.fBuffer) {
            fBlocks.pop_back();
            return false;
        }
    }

    block.fBytesFree = size;
    if (NULL != fBufferPtr) {
        GrAssert(fBlocks.count() > 1);
        BufferBlock& prev = fBlocks.fromBack(1);
        if (prev.fBuffer->isLocked()) {
            prev.fBuffer->unlock();
        } else {
            flushCpuData(prev.fBuffer,
                         prev.fBuffer->sizeInBytes() - prev.fBytesFree);
        }
        fBufferPtr = NULL;
    }

    GrAssert(NULL == fBufferPtr);

    if (fGpu->getCaps().fBufferLockSupport &&
        size > GR_GEOM_BUFFER_LOCK_THRESHOLD &&
        (!fFrequentResetHint || requestSize > GR_GEOM_BUFFER_LOCK_THRESHOLD)) {
        fBufferPtr = block.fBuffer->lock();
    }

    if (NULL == fBufferPtr) {
        fBufferPtr = fCpuData.reset(size);
    }

    VALIDATE(true);

    return true;
}

void GrBufferAllocPool::destroyBlock() {
    GrAssert(!fBlocks.empty());

    BufferBlock& block = fBlocks.back();
    if (fPreallocBuffersInUse > 0) {
        uint32_t prevPreallocBuffer = (fPreallocBuffersInUse +
                                       fFirstPreallocBuffer +
                                       (fPreallocBuffers.count() - 1)) %
                                      fPreallocBuffers.count();
        if (block.fBuffer == fPreallocBuffers[prevPreallocBuffer]) {
            --fPreallocBuffersInUse;
        }
    }
    GrAssert(!block.fBuffer->isLocked());
    block.fBuffer->unref();
    fBlocks.pop_back();
    fBufferPtr = NULL;
}

void GrBufferAllocPool::flushCpuData(GrGeometryBuffer* buffer,
                                     size_t flushSize) {
    GrAssert(NULL != buffer);
    GrAssert(!buffer->isLocked());
    GrAssert(fCpuData.get() == fBufferPtr);
    GrAssert(flushSize <= buffer->sizeInBytes());

    bool updated = false;
    if (fGpu->getCaps().fBufferLockSupport &&
        flushSize > GR_GEOM_BUFFER_LOCK_THRESHOLD) {
        void* data = buffer->lock();
        if (NULL != data) {
            memcpy(data, fBufferPtr, flushSize);
            buffer->unlock();
            updated = true;
        }
    }
    buffer->updateData(fBufferPtr, flushSize);
}

GrGeometryBuffer* GrBufferAllocPool::createBuffer(size_t size) {
    if (kIndex_BufferType == fBufferType) {
        return fGpu->createIndexBuffer(size, true);
    } else {
        GrAssert(kVertex_BufferType == fBufferType);
        return fGpu->createVertexBuffer(size, true);
    }
}

////////////////////////////////////////////////////////////////////////////////

GrVertexBufferAllocPool::GrVertexBufferAllocPool(GrGpu* gpu,
                                                 bool frequentResetHint,
                                                 size_t bufferSize,
                                                 int preallocBufferCnt)
: GrBufferAllocPool(gpu,
                    kVertex_BufferType,
                    frequentResetHint,
                    bufferSize,
                    preallocBufferCnt) {
}

void* GrVertexBufferAllocPool::makeSpace(GrVertexLayout layout,
                                         int vertexCount,
                                         const GrVertexBuffer** buffer,
                                         int* startVertex) {

    GrAssert(vertexCount >= 0);
    GrAssert(NULL != buffer);
    GrAssert(NULL != startVertex);

    size_t vSize = GrDrawTarget::VertexSize(layout);
    size_t offset = 0; // assign to suppress warning
    const GrGeometryBuffer* geomBuffer = NULL; // assign to suppress warning
    void* ptr = INHERITED::makeSpace(vSize * vertexCount,
                                     vSize,
                                     &geomBuffer,
                                     &offset);

    *buffer = (const GrVertexBuffer*) geomBuffer;
    GrAssert(0 == offset % vSize);
    *startVertex = offset / vSize;
    return ptr;
}

bool GrVertexBufferAllocPool::appendVertices(GrVertexLayout layout,
                                             int vertexCount,
                                             const void* vertices,
                                             const GrVertexBuffer** buffer,
                                             int* startVertex) {
    void* space = makeSpace(layout, vertexCount, buffer, startVertex);
    if (NULL != space) {
        memcpy(space,
               vertices,
               GrDrawTarget::VertexSize(layout) * vertexCount);
        return true;
    } else {
        return false;
    }
}

int GrVertexBufferAllocPool::preallocatedBufferVertices(GrVertexLayout layout) const {
    return INHERITED::preallocatedBufferSize() /
            GrDrawTarget::VertexSize(layout);
}

int GrVertexBufferAllocPool::currentBufferVertices(GrVertexLayout layout) const {
    return currentBufferItems(GrDrawTarget::VertexSize(layout));
}

////////////////////////////////////////////////////////////////////////////////

GrIndexBufferAllocPool::GrIndexBufferAllocPool(GrGpu* gpu,
                                               bool frequentResetHint,
                                               size_t bufferSize,
                                               int preallocBufferCnt)
: GrBufferAllocPool(gpu,
                    kIndex_BufferType,
                    frequentResetHint,
                    bufferSize,
                    preallocBufferCnt) {
}

void* GrIndexBufferAllocPool::makeSpace(int indexCount,
                                        const GrIndexBuffer** buffer,
                                        int* startIndex) {

    GrAssert(indexCount >= 0);
    GrAssert(NULL != buffer);
    GrAssert(NULL != startIndex);

    size_t offset = 0; // assign to suppress warning
    const GrGeometryBuffer* geomBuffer = NULL; // assign to suppress warning
    void* ptr = INHERITED::makeSpace(indexCount * sizeof(uint16_t),
                                     sizeof(uint16_t),
                                     &geomBuffer,
                                     &offset);

    *buffer = (const GrIndexBuffer*) geomBuffer;
    GrAssert(0 == offset % sizeof(uint16_t));
    *startIndex = offset / sizeof(uint16_t);
    return ptr;
}

bool GrIndexBufferAllocPool::appendIndices(int indexCount,
                                           const void* indices,
                                           const GrIndexBuffer** buffer,
                                           int* startIndex) {
    void* space = makeSpace(indexCount, buffer, startIndex);
    if (NULL != space) {
        memcpy(space, indices, sizeof(uint16_t) * indexCount);
        return true;
    } else {
        return false;
    }
}

int GrIndexBufferAllocPool::preallocatedBufferIndices() const {
    return INHERITED::preallocatedBufferSize() / sizeof(uint16_t);
}

int GrIndexBufferAllocPool::currentBufferIndices() const {
    return currentBufferItems(sizeof(uint16_t));
}
<commit_msg>Don't update vertex/index buffer twice! <commit_after>
/*
 * Copyright 2010 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "GrBufferAllocPool.h"
#include "GrTypes.h"
#include "GrVertexBuffer.h"
#include "GrIndexBuffer.h"
#include "GrGpu.h"

#if GR_DEBUG
    #define VALIDATE validate
#else
    static void VALIDATE(bool x = false) {}
#endif

// page size
#define GrBufferAllocPool_MIN_BLOCK_SIZE ((size_t)1 << 12)

GrBufferAllocPool::GrBufferAllocPool(GrGpu* gpu,
                                     BufferType bufferType,
                                     bool frequentResetHint,
                                     size_t blockSize,
                                     int preallocBufferCnt) :
        fBlocks(GrMax(8, 2*preallocBufferCnt)) {

    GrAssert(NULL != gpu);
    fGpu = gpu;
    fGpu->ref();
    fGpuIsReffed = true;

    fBufferType = bufferType;
    fFrequentResetHint = frequentResetHint;
    fBufferPtr = NULL;
    fMinBlockSize = GrMax(GrBufferAllocPool_MIN_BLOCK_SIZE, blockSize);

    fBytesInUse = 0;

    fPreallocBuffersInUse = 0;
    fFirstPreallocBuffer = 0;
    for (int i = 0; i < preallocBufferCnt; ++i) {
        GrGeometryBuffer* buffer = this->createBuffer(fMinBlockSize);
        if (NULL != buffer) {
            *fPreallocBuffers.append() = buffer;
            buffer->ref();
        }
    }
}

GrBufferAllocPool::~GrBufferAllocPool() {
    VALIDATE();
    if (fBlocks.count()) {
        GrGeometryBuffer* buffer = fBlocks.back().fBuffer;
        if (buffer->isLocked()) {
            buffer->unlock();
        }
    }
    while (!fBlocks.empty()) {
        destroyBlock();
    }
    fPreallocBuffers.unrefAll();
    releaseGpuRef();
}

void GrBufferAllocPool::releaseGpuRef() {
    if (fGpuIsReffed) {
        fGpu->unref();
        fGpuIsReffed = false;
    }
}

void GrBufferAllocPool::reset() {
    VALIDATE();
    fBytesInUse = 0;
    if (fBlocks.count()) {
        GrGeometryBuffer* buffer = fBlocks.back().fBuffer;
        if (buffer->isLocked()) {
            buffer->unlock();
        }
    }
    while (!fBlocks.empty()) {
        destroyBlock();
    }
    if (fPreallocBuffers.count()) {
        // must set this after above loop.
        fFirstPreallocBuffer = (fFirstPreallocBuffer + fPreallocBuffersInUse) %
                               fPreallocBuffers.count();
    }
    fCpuData.reset(fGpu->getCaps().fBufferLockSupport ? 0 : fMinBlockSize);
    GrAssert(0 == fPreallocBuffersInUse);
    VALIDATE();
}

void GrBufferAllocPool::unlock() {
    VALIDATE();

    if (NULL != fBufferPtr) {
        BufferBlock& block = fBlocks.back();
        if (block.fBuffer->isLocked()) {
            block.fBuffer->unlock();
        } else {
            size_t flushSize = block.fBuffer->sizeInBytes() - block.fBytesFree;
            flushCpuData(fBlocks.back().fBuffer, flushSize);
        }
        fBufferPtr = NULL;
    }
    VALIDATE();
}

#if GR_DEBUG
void GrBufferAllocPool::validate(bool unusedBlockAllowed) const {
    if (NULL != fBufferPtr) {
        GrAssert(!fBlocks.empty());
        if (fBlocks.back().fBuffer->isLocked()) {
            GrGeometryBuffer* buf = fBlocks.back().fBuffer;
            GrAssert(buf->lockPtr() == fBufferPtr);
        } else {
            GrAssert(fCpuData.get() == fBufferPtr);
        }
    } else {
        GrAssert(fBlocks.empty() || !fBlocks.back().fBuffer->isLocked());
    }
    size_t bytesInUse = 0;
    for (int i = 0; i < fBlocks.count() - 1; ++i) {
        GrAssert(!fBlocks[i].fBuffer->isLocked());
    }
    for (int i = 0; i < fBlocks.count(); ++i) {
        size_t bytes = fBlocks[i].fBuffer->sizeInBytes() - fBlocks[i].fBytesFree;
        bytesInUse += bytes;
        GrAssert(bytes || unusedBlockAllowed);
    }

    GrAssert(bytesInUse == fBytesInUse);
    if (unusedBlockAllowed) {
        GrAssert((fBytesInUse && !fBlocks.empty()) ||
                 (!fBytesInUse && (fBlocks.count() < 2)));
    } else {
        GrAssert((0 == fBytesInUse) == fBlocks.empty());
    }
}
#endif

void* GrBufferAllocPool::makeSpace(size_t size,
                                   size_t alignment,
                                   const GrGeometryBuffer** buffer,
                                   size_t* offset) {
    VALIDATE();

    GrAssert(NULL != buffer);
    GrAssert(NULL != offset);

    if (NULL != fBufferPtr) {
        BufferBlock& back = fBlocks.back();
        size_t usedBytes = back.fBuffer->sizeInBytes() - back.fBytesFree;
        size_t pad = GrSizeAlignUpPad(usedBytes,
                                      alignment);
        if ((size + pad) <= back.fBytesFree) {
            usedBytes += pad;
            *offset = usedBytes;
            *buffer = back.fBuffer;
            back.fBytesFree -= size + pad;
            fBytesInUse += size;
            return (void*)(reinterpret_cast<intptr_t>(fBufferPtr) + usedBytes);
        }
    }

    // We could honor the space request using by a partial update of the current
    // VB (if there is room). But we don't currently use draw calls to GL that
    // allow the driver to know that previously issued draws won't read from
    // the part of the buffer we update. Also, the GL buffer implementation
    // may be cheating on the actual buffer size by shrinking the buffer on
    // updateData() if the amount of data passed is less than the full buffer
    // size.

    if (!createBlock(size)) {
        return NULL;
    }
    GrAssert(NULL != fBufferPtr);

    *offset = 0;
    BufferBlock& back = fBlocks.back();
    *buffer = back.fBuffer;
    back.fBytesFree -= size;
    fBytesInUse += size;
    VALIDATE();
    return fBufferPtr;
}

int GrBufferAllocPool::currentBufferItems(size_t itemSize) const {
    VALIDATE();
    if (NULL != fBufferPtr) {
        const BufferBlock& back = fBlocks.back();
        size_t usedBytes = back.fBuffer->sizeInBytes() - back.fBytesFree;
        size_t pad = GrSizeAlignUpPad(usedBytes, itemSize);
        return (back.fBytesFree - pad) / itemSize;
    } else if (fPreallocBuffersInUse < fPreallocBuffers.count()) {
        return fMinBlockSize / itemSize;
    }
    return 0;
}

int GrBufferAllocPool::preallocatedBuffersRemaining() const {
    return fPreallocBuffers.count() - fPreallocBuffersInUse;
}

int GrBufferAllocPool::preallocatedBufferCount() const {
    return fPreallocBuffers.count();
}

void GrBufferAllocPool::putBack(size_t bytes) {
    VALIDATE();

    while (bytes) {
        // caller shouldnt try to put back more than they've taken
        GrAssert(!fBlocks.empty());
        BufferBlock& block = fBlocks.back();
        size_t bytesUsed = block.fBuffer->sizeInBytes() - block.fBytesFree;
        if (bytes >= bytesUsed) {
            bytes -= bytesUsed;
            fBytesInUse -= bytesUsed;
            // if we locked a vb to satisfy the make space and we're releasing
            // beyond it, then unlock it.
            if (block.fBuffer->isLocked()) {
                block.fBuffer->unlock();
            }
            this->destroyBlock();
        } else {
            block.fBytesFree += bytes;
            fBytesInUse -= bytes;
            bytes = 0;
            break;
        }
    }
    VALIDATE();
}

bool GrBufferAllocPool::createBlock(size_t requestSize) {

    size_t size = GrMax(requestSize, fMinBlockSize);
    GrAssert(size >= GrBufferAllocPool_MIN_BLOCK_SIZE);

    VALIDATE();

    BufferBlock& block = fBlocks.push_back();

    if (size == fMinBlockSize &&
        fPreallocBuffersInUse < fPreallocBuffers.count()) {

        uint32_t nextBuffer = (fPreallocBuffersInUse + fFirstPreallocBuffer) %
                               fPreallocBuffers.count();
        block.fBuffer = fPreallocBuffers[nextBuffer];
        block.fBuffer->ref();
        ++fPreallocBuffersInUse;
    } else {
        block.fBuffer = this->createBuffer(size);
        if (NULL == block.fBuffer) {
            fBlocks.pop_back();
            return false;
        }
    }

    block.fBytesFree = size;
    if (NULL != fBufferPtr) {
        GrAssert(fBlocks.count() > 1);
        BufferBlock& prev = fBlocks.fromBack(1);
        if (prev.fBuffer->isLocked()) {
            prev.fBuffer->unlock();
        } else {
            flushCpuData(prev.fBuffer,
                         prev.fBuffer->sizeInBytes() - prev.fBytesFree);
        }
        fBufferPtr = NULL;
    }

    GrAssert(NULL == fBufferPtr);

    if (fGpu->getCaps().fBufferLockSupport &&
        size > GR_GEOM_BUFFER_LOCK_THRESHOLD &&
        (!fFrequentResetHint || requestSize > GR_GEOM_BUFFER_LOCK_THRESHOLD)) {
        fBufferPtr = block.fBuffer->lock();
    }

    if (NULL == fBufferPtr) {
        fBufferPtr = fCpuData.reset(size);
    }

    VALIDATE(true);

    return true;
}

void GrBufferAllocPool::destroyBlock() {
    GrAssert(!fBlocks.empty());

    BufferBlock& block = fBlocks.back();
    if (fPreallocBuffersInUse > 0) {
        uint32_t prevPreallocBuffer = (fPreallocBuffersInUse +
                                       fFirstPreallocBuffer +
                                       (fPreallocBuffers.count() - 1)) %
                                      fPreallocBuffers.count();
        if (block.fBuffer == fPreallocBuffers[prevPreallocBuffer]) {
            --fPreallocBuffersInUse;
        }
    }
    GrAssert(!block.fBuffer->isLocked());
    block.fBuffer->unref();
    fBlocks.pop_back();
    fBufferPtr = NULL;
}

void GrBufferAllocPool::flushCpuData(GrGeometryBuffer* buffer,
                                     size_t flushSize) {
    GrAssert(NULL != buffer);
    GrAssert(!buffer->isLocked());
    GrAssert(fCpuData.get() == fBufferPtr);
    GrAssert(flushSize <= buffer->sizeInBytes());

    if (fGpu->getCaps().fBufferLockSupport &&
        flushSize > GR_GEOM_BUFFER_LOCK_THRESHOLD) {
        void* data = buffer->lock();
        if (NULL != data) {
            memcpy(data, fBufferPtr, flushSize);
            buffer->unlock();
            return;
        }
    }
    buffer->updateData(fBufferPtr, flushSize);
}

GrGeometryBuffer* GrBufferAllocPool::createBuffer(size_t size) {
    if (kIndex_BufferType == fBufferType) {
        return fGpu->createIndexBuffer(size, true);
    } else {
        GrAssert(kVertex_BufferType == fBufferType);
        return fGpu->createVertexBuffer(size, true);
    }
}

////////////////////////////////////////////////////////////////////////////////

GrVertexBufferAllocPool::GrVertexBufferAllocPool(GrGpu* gpu,
                                                 bool frequentResetHint,
                                                 size_t bufferSize,
                                                 int preallocBufferCnt)
: GrBufferAllocPool(gpu,
                    kVertex_BufferType,
                    frequentResetHint,
                    bufferSize,
                    preallocBufferCnt) {
}

void* GrVertexBufferAllocPool::makeSpace(GrVertexLayout layout,
                                         int vertexCount,
                                         const GrVertexBuffer** buffer,
                                         int* startVertex) {

    GrAssert(vertexCount >= 0);
    GrAssert(NULL != buffer);
    GrAssert(NULL != startVertex);

    size_t vSize = GrDrawTarget::VertexSize(layout);
    size_t offset = 0; // assign to suppress warning
    const GrGeometryBuffer* geomBuffer = NULL; // assign to suppress warning
    void* ptr = INHERITED::makeSpace(vSize * vertexCount,
                                     vSize,
                                     &geomBuffer,
                                     &offset);

    *buffer = (const GrVertexBuffer*) geomBuffer;
    GrAssert(0 == offset % vSize);
    *startVertex = offset / vSize;
    return ptr;
}

bool GrVertexBufferAllocPool::appendVertices(GrVertexLayout layout,
                                             int vertexCount,
                                             const void* vertices,
                                             const GrVertexBuffer** buffer,
                                             int* startVertex) {
    void* space = makeSpace(layout, vertexCount, buffer, startVertex);
    if (NULL != space) {
        memcpy(space,
               vertices,
               GrDrawTarget::VertexSize(layout) * vertexCount);
        return true;
    } else {
        return false;
    }
}

int GrVertexBufferAllocPool::preallocatedBufferVertices(GrVertexLayout layout) const {
    return INHERITED::preallocatedBufferSize() /
            GrDrawTarget::VertexSize(layout);
}

int GrVertexBufferAllocPool::currentBufferVertices(GrVertexLayout layout) const {
    return currentBufferItems(GrDrawTarget::VertexSize(layout));
}

////////////////////////////////////////////////////////////////////////////////

GrIndexBufferAllocPool::GrIndexBufferAllocPool(GrGpu* gpu,
                                               bool frequentResetHint,
                                               size_t bufferSize,
                                               int preallocBufferCnt)
: GrBufferAllocPool(gpu,
                    kIndex_BufferType,
                    frequentResetHint,
                    bufferSize,
                    preallocBufferCnt) {
}

void* GrIndexBufferAllocPool::makeSpace(int indexCount,
                                        const GrIndexBuffer** buffer,
                                        int* startIndex) {

    GrAssert(indexCount >= 0);
    GrAssert(NULL != buffer);
    GrAssert(NULL != startIndex);

    size_t offset = 0; // assign to suppress warning
    const GrGeometryBuffer* geomBuffer = NULL; // assign to suppress warning
    void* ptr = INHERITED::makeSpace(indexCount * sizeof(uint16_t),
                                     sizeof(uint16_t),
                                     &geomBuffer,
                                     &offset);

    *buffer = (const GrIndexBuffer*) geomBuffer;
    GrAssert(0 == offset % sizeof(uint16_t));
    *startIndex = offset / sizeof(uint16_t);
    return ptr;
}

bool GrIndexBufferAllocPool::appendIndices(int indexCount,
                                           const void* indices,
                                           const GrIndexBuffer** buffer,
                                           int* startIndex) {
    void* space = makeSpace(indexCount, buffer, startIndex);
    if (NULL != space) {
        memcpy(space, indices, sizeof(uint16_t) * indexCount);
        return true;
    } else {
        return false;
    }
}

int GrIndexBufferAllocPool::preallocatedBufferIndices() const {
    return INHERITED::preallocatedBufferSize() / sizeof(uint16_t);
}

int GrIndexBufferAllocPool::currentBufferIndices() const {
    return currentBufferItems(sizeof(uint16_t));
}
<|endoftext|>


<commit_before>/*!
 * \file painter_dashed_stroke_shader_set.hpp
 * \brief file painter_dashed_stroke_shader_set.hpp
 *
 * Copyright 2016 by Intel.
 *
 * Contact: kevin.rogovin@intel.com
 *
 * This Source Code Form is subject to the
 * terms of the Mozilla Public License, v. 2.0.
 * If a copy of the MPL was not distributed with
 * this file, You can obtain one at
 * http://mozilla.org/MPL/2.0/.
 *
 * \author Kevin Rogovin <kevin.rogovin@intel.com>
 *
 */

#pragma once

#include <fastuidraw/util/reference_counted.hpp>
#include <fastuidraw/painter/painter_stroke_shader.hpp>
#include <fastuidraw/painter/painter_enums.hpp>

namespace fastuidraw
{
  class PainterItemShaderData;

/*!\addtogroup Painter
  @{
 */

  /*!
    A DashEvaluator is used by Painter to realize the
    data to send to a PainterPacker for the purpose
    of dashed stroking.
   */
  class DashEvaluator:
    public reference_counted<DashEvaluator>::default_base
  {
  public:
    /*!
      To be implemented by a derived class to give the distance
      to the next dash boundary. Giving a negative value indicates
      that the location passed is not drawn when dashed and giving
      a positive indicates it is.
      \param data PainterItemShaderData object holding the data to
                  be sent to the shader
      \param distance the distance to use to use to compute the
                      return value
     */
    virtual
    float
    signed_distance_to_next_dash_boundary(const PainterItemShaderData &data,
                                          float distance) const;
  };

  /*!
    A PainterDashedStrokeShaderSet holds a collection of
    PainterStrokeShaderSet objects for the purpose of
    dashed stroking. The shaders within a
    PainterDashedStrokeShaderSet are expected to draw
    any caps of dashed stroking from using just the edge
    data. In particular, attributes/indices for caps are
    NEVER given to a shader within a PainterDashedStrokeShaderSet.
   */
  class PainterDashedStrokeShaderSet
  {
  public:
    /*!
      Ctor
     */
    PainterDashedStrokeShaderSet(void);

    /*!
      Copy ctor.
     */
    PainterDashedStrokeShaderSet(const PainterDashedStrokeShaderSet &obj);

    ~PainterDashedStrokeShaderSet();

    /*!
      Assignment operator.
     */
    PainterDashedStrokeShaderSet&
    operator=(const PainterDashedStrokeShaderSet &rhs);

    /*!
      Returns the DashEvaluator object to be used with
      the expected PainterItemShaderData passed to the
      PainterStrokeShader objects of this
      PainterDashedStrokeShaderSet.
     */
    const reference_counted_ptr<const DashEvaluator>&
    dash_evaluator(void) const;

    /*!
      Set the value returned by dash_evaluator(void) const.
      Initial value is NULL.
     */
    PainterDashedStrokeShaderSet&
    dash_evaluator(const reference_counted_ptr<const DashEvaluator>&);

    /*!
      Shader set for dashed stroking of paths where the stroking
      width is given in same units as the original path.
      The stroking parameters are given by PainterDashedStrokeParams.
      \param st cap style
     */
    const PainterStrokeShader&
    shader(enum PainterEnums::dashed_cap_style st) const;

    /*!
      Set the value returned by dashed_stroke_shader(enum PainterEnums::dashed_cap_style) const.
      \param st cap style
      \param sh value to use
     */
    PainterDashedStrokeShaderSet&
    shader(enum PainterEnums::dashed_cap_style st, const PainterStrokeShader &sh);

  private:
    void *m_d;
  };

/*! @} */
}
<commit_msg>fastuidraw/painter: use DataBase object directly in DashEvaluator<commit_after>/*!
 * \file painter_dashed_stroke_shader_set.hpp
 * \brief file painter_dashed_stroke_shader_set.hpp
 *
 * Copyright 2016 by Intel.
 *
 * Contact: kevin.rogovin@intel.com
 *
 * This Source Code Form is subject to the
 * terms of the Mozilla Public License, v. 2.0.
 * If a copy of the MPL was not distributed with
 * this file, You can obtain one at
 * http://mozilla.org/MPL/2.0/.
 *
 * \author Kevin Rogovin <kevin.rogovin@intel.com>
 *
 */

#pragma once

#include <fastuidraw/util/reference_counted.hpp>
#include <fastuidraw/painter/painter_value.hpp>
#include <fastuidraw/painter/painter_stroke_shader.hpp>
#include <fastuidraw/painter/painter_enums.hpp>

namespace fastuidraw
{
/*!\addtogroup Painter
  @{
 */

  /*!
    A DashEvaluator is used by Painter to realize the
    data to send to a PainterPacker for the purpose
    of dashed stroking.
   */
  class DashEvaluator:
    public reference_counted<DashEvaluator>::default_base
  {
  public:
    /*!
      To be implemented by a derived class to return the distance
      to the next dash boundary. A negative return value indicates
      that the location passed is not drawn when dashed and a
      positive indicates it is.
      \param data PainterItemShaderData::DataBase object holding the data to
                  be sent to the shader
      \param distance the distance to use to compute the return value
     */
    virtual
    float
    signed_distance_to_next_dash_boundary(const PainterShaderData::DataBase *data,
                                          float distance) const;
  };

  /*!
    A PainterDashedStrokeShaderSet holds a collection of
    PainterStrokeShaderSet objects for the purpose of
    dashed stroking. The shaders within a
    PainterDashedStrokeShaderSet are expected to draw
    any caps of dashed stroking from using just the edge
    data. In particular, attributes/indices for caps are
    NEVER given to a shader within a PainterDashedStrokeShaderSet.
   */
  class PainterDashedStrokeShaderSet
  {
  public:
    /*!
      Ctor
     */
    PainterDashedStrokeShaderSet(void);

    /*!
      Copy ctor.
     */
    PainterDashedStrokeShaderSet(const PainterDashedStrokeShaderSet &obj);

    ~PainterDashedStrokeShaderSet();

    /*!
      Assignment operator.
     */
    PainterDashedStrokeShaderSet&
    operator=(const PainterDashedStrokeShaderSet &rhs);

    /*!
      Returns the DashEvaluator object to be used with
      the expected PainterItemShaderData passed to the
      PainterStrokeShader objects of this
      PainterDashedStrokeShaderSet.
     */
    const reference_counted_ptr<const DashEvaluator>&
    dash_evaluator(void) const;

    /*!
      Set the value returned by dash_evaluator(void) const.
      Initial value is NULL.
     */
    PainterDashedStrokeShaderSet&
    dash_evaluator(const reference_counted_ptr<const DashEvaluator>&);

    /*!
      Shader set for dashed stroking of paths where the stroking
      width is given in same units as the original path.
      The stroking parameters are given by PainterDashedStrokeParams.
      \param st cap style
     */
    const PainterStrokeShader&
    shader(enum PainterEnums::dashed_cap_style st) const;

    /*!
      Set the value returned by dashed_stroke_shader(enum PainterEnums::dashed_cap_style) const.
      \param st cap style
      \param sh value to use
     */
    PainterDashedStrokeShaderSet&
    shader(enum PainterEnums::dashed_cap_style st, const PainterStrokeShader &sh);

  private:
    void *m_d;
  };

/*! @} */
}
<|endoftext|>


<commit_before>/*	opendatacon
 *
 *	Copyright (c) 2020:
 *
 *		DCrip3fJguWgVCLrZFfA7sIGgvx1Ou3fHfCxnrz4svAi
 *		yxeOtDhDCXf1Z4ApgXvX5ahqQmzRfJ2DoX8S05SqHA==
 *
 *	Licensed under the Apache License, Version 2.0 (the "License");
 *	you may not use this file except in compliance with the License.
 *	You may obtain a copy of the License at
 *
 *		http://www.apache.org/licenses/LICENSE-2.0
 *
 *	Unless required by applicable law or agreed to in writing, software
 *	distributed under the License is distributed on an "AS IS" BASIS,
 *	WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *	See the License for the specific language governing permissions and
 *	limitations under the License.
 */
/*
 * BinaryControl.cpp
 *
 *  Created on: 2021-02-08
 *  A year of hope that pandemic will end soon
 *      Author: Rakesh Kumar <cpp.rakesh@gmail.com>
 */

#include "BinaryControl.h"

void BinaryControl::CreateBinaryControl(std::size_t index,
	const std::shared_ptr<odc::EventInfo>& on,
	const std::shared_ptr<odc::EventInfo>& off,
	FeedbackMode mode,
	std::size_t update_interval)
{
	{ // for the scope of lock
		std::unique_lock<std::shared_timed_mutex> lck(feedback_mutex);
		m_binary_feedbacks[index].emplace_back(std::make_shared<BinaryFeedback>(on, off, mode, update_interval));
	}
	if (!IsIndex(index))
	{
		odc::EventTypePayload<odc::EventType::ControlRelayOutputBlock>::type payload;
		payload.functionCode = odc::ControlCode::NUL;
		std::shared_ptr<odc::EventInfo> control_event = std::make_shared<odc::EventInfo>(odc::EventType::ControlRelayOutputBlock, index, on->GetSourcePort(), odc::QualityFlags::COMM_LOST);
		control_event->SetPayload<odc::EventType::ControlRelayOutputBlock>(std::move(payload));
		control_event->SetTimestamp(0);
		{ // for the scope of the lock
			std::unique_lock<std::shared_timed_mutex> lck(current_mutex);
			m_current_binary_events[index] = control_event;
		}
	}
}

std::vector<std::shared_ptr<BinaryFeedback>> BinaryControl::BinaryFeedbacks(std::size_t index)
{
	std::shared_lock<std::shared_timed_mutex> lck(feedback_mutex);
	std::vector<std::shared_ptr<BinaryFeedback>> feedback;
	if (m_binary_feedbacks.find(index) != m_binary_feedbacks.end())
		feedback = m_binary_feedbacks[index];
	return feedback;
}

void BinaryControl::CreateBinaryControl(std::size_t index,
	const std::string& port_source,
	odc::FeedbackType type,
	const std::vector<std::size_t>& indexes,
	const std::vector<odc::PositionAction>& action,
	std::size_t lower_limit, std::size_t raise_limit)
{
	odc::EventTypePayload<odc::EventType::ControlRelayOutputBlock>::type payload;
	payload.functionCode = odc::ControlCode::NUL;
	std::shared_ptr<odc::EventInfo> control_event = std::make_shared<odc::EventInfo>(odc::EventType::ControlRelayOutputBlock, index, port_source, odc::QualityFlags::COMM_LOST);
	control_event->SetPayload<odc::EventType::ControlRelayOutputBlock>(std::move(payload));
	control_event->SetTimestamp(0);
	{ // scope of the lock
		std::unique_lock<std::shared_timed_mutex> lck(position_mutex);
		m_binary_positions[index] = std::make_shared<BinaryPosition>(type, action, indexes, lower_limit, raise_limit);
	}
	{ // scope of the lock
		std::unique_lock<std::shared_timed_mutex> lck(current_mutex);
		m_current_binary_events[index] = control_event;
	}
}

std::shared_ptr<BinaryPosition> BinaryControl::GetBinaryPosition(std::size_t index)
{
	std::shared_lock<std::shared_timed_mutex> lck(position_mutex);
	return m_binary_positions[index];
}

void BinaryControl::CreateBinaryControl(std::size_t index)
{
	std::unique_lock<std::shared_timed_mutex> lck(current_mutex);
	m_current_binary_events[index] = nullptr;
}

bool BinaryControl::IsIndex(std::size_t index)
{
	std::shared_lock<std::shared_timed_mutex> lck(current_mutex);
	return m_current_binary_events.find(index) != m_current_binary_events.end();
}

void BinaryControl::SetCurrentBinaryEvent(const std::shared_ptr<odc::EventInfo>& event, std::size_t index)
{
	std::unique_lock<std::shared_timed_mutex> lck(current_mutex);
	m_current_binary_events[index] = event;
}

std::shared_ptr<odc::EventInfo> BinaryControl::GetCurrentBinaryEvent(std::size_t index)
{
	std::shared_lock<std::shared_timed_mutex> lck(current_mutex);
	return m_current_binary_events[index];
}

<commit_msg>initialise SimPort control status values not null<commit_after>/*	opendatacon
 *
 *	Copyright (c) 2020:
 *
 *		DCrip3fJguWgVCLrZFfA7sIGgvx1Ou3fHfCxnrz4svAi
 *		yxeOtDhDCXf1Z4ApgXvX5ahqQmzRfJ2DoX8S05SqHA==
 *
 *	Licensed under the Apache License, Version 2.0 (the "License");
 *	you may not use this file except in compliance with the License.
 *	You may obtain a copy of the License at
 *
 *		http://www.apache.org/licenses/LICENSE-2.0
 *
 *	Unless required by applicable law or agreed to in writing, software
 *	distributed under the License is distributed on an "AS IS" BASIS,
 *	WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *	See the License for the specific language governing permissions and
 *	limitations under the License.
 */
/*
 * BinaryControl.cpp
 *
 *  Created on: 2021-02-08
 *  A year of hope that pandemic will end soon
 *      Author: Rakesh Kumar <cpp.rakesh@gmail.com>
 */

#include "BinaryControl.h"

void BinaryControl::CreateBinaryControl(std::size_t index,
	const std::shared_ptr<odc::EventInfo>& on,
	const std::shared_ptr<odc::EventInfo>& off,
	FeedbackMode mode,
	std::size_t update_interval)
{
	{ // for the scope of lock
		std::unique_lock<std::shared_timed_mutex> lck(feedback_mutex);
		m_binary_feedbacks[index].emplace_back(std::make_shared<BinaryFeedback>(on, off, mode, update_interval));
	}
	if (!IsIndex(index))
	{
		odc::EventTypePayload<odc::EventType::ControlRelayOutputBlock>::type payload;
		payload.functionCode = odc::ControlCode::NUL;
		std::shared_ptr<odc::EventInfo> control_event = std::make_shared<odc::EventInfo>(odc::EventType::ControlRelayOutputBlock, index, on->GetSourcePort(), odc::QualityFlags::COMM_LOST);
		control_event->SetPayload<odc::EventType::ControlRelayOutputBlock>(std::move(payload));
		control_event->SetTimestamp(0);
		{ // for the scope of the lock
			std::unique_lock<std::shared_timed_mutex> lck(current_mutex);
			m_current_binary_events[index] = control_event;
		}
	}
}

std::vector<std::shared_ptr<BinaryFeedback>> BinaryControl::BinaryFeedbacks(std::size_t index)
{
	std::shared_lock<std::shared_timed_mutex> lck(feedback_mutex);
	std::vector<std::shared_ptr<BinaryFeedback>> feedback;
	if (m_binary_feedbacks.find(index) != m_binary_feedbacks.end())
		feedback = m_binary_feedbacks[index];
	return feedback;
}

void BinaryControl::CreateBinaryControl(std::size_t index,
	const std::string& port_source,
	odc::FeedbackType type,
	const std::vector<std::size_t>& indexes,
	const std::vector<odc::PositionAction>& action,
	std::size_t lower_limit, std::size_t raise_limit)
{
	odc::EventTypePayload<odc::EventType::ControlRelayOutputBlock>::type payload;
	payload.functionCode = odc::ControlCode::NUL;
	std::shared_ptr<odc::EventInfo> control_event = std::make_shared<odc::EventInfo>(odc::EventType::ControlRelayOutputBlock, index, port_source, odc::QualityFlags::COMM_LOST);
	control_event->SetPayload<odc::EventType::ControlRelayOutputBlock>(std::move(payload));
	control_event->SetTimestamp(0);
	{ // scope of the lock
		std::unique_lock<std::shared_timed_mutex> lck(position_mutex);
		m_binary_positions[index] = std::make_shared<BinaryPosition>(type, action, indexes, lower_limit, raise_limit);
	}
	{ // scope of the lock
		std::unique_lock<std::shared_timed_mutex> lck(current_mutex);
		m_current_binary_events[index] = control_event;
	}
}

std::shared_ptr<BinaryPosition> BinaryControl::GetBinaryPosition(std::size_t index)
{
	std::shared_lock<std::shared_timed_mutex> lck(position_mutex);
	return m_binary_positions[index];
}

void BinaryControl::CreateBinaryControl(std::size_t index)
{
	odc::EventTypePayload<odc::EventType::ControlRelayOutputBlock>::type payload;
	payload.functionCode = odc::ControlCode::NUL;
	std::shared_ptr<odc::EventInfo> control_event = std::make_shared<odc::EventInfo>(odc::EventType::ControlRelayOutputBlock, index, "NULL", odc::QualityFlags::COMM_LOST);
	control_event->SetPayload<odc::EventType::ControlRelayOutputBlock>(std::move(payload));
	control_event->SetTimestamp(0);
	{ // scope of the lock
		std::unique_lock<std::shared_timed_mutex> lck(current_mutex);
		m_current_binary_events[index] = control_event;
	}
}

bool BinaryControl::IsIndex(std::size_t index)
{
	std::shared_lock<std::shared_timed_mutex> lck(current_mutex);
	return m_current_binary_events.find(index) != m_current_binary_events.end();
}

void BinaryControl::SetCurrentBinaryEvent(const std::shared_ptr<odc::EventInfo>& event, std::size_t index)
{
	std::unique_lock<std::shared_timed_mutex> lck(current_mutex);
	m_current_binary_events[index] = event;
}

std::shared_ptr<odc::EventInfo> BinaryControl::GetCurrentBinaryEvent(std::size_t index)
{
	std::shared_lock<std::shared_timed_mutex> lck(current_mutex);
	return m_current_binary_events[index];
}

<|endoftext|>