<commit_before>/**************************************************************************
 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
 *                                                                        *
 * Author: The ALICE Off-line Project.                                    *
 * Contributors are mentioned in the code where appropriate.              *
 *                                                                        *
 * Permission to use, copy, modify and distribute this software and its   *
 * documentation strictly for non-commercial purposes is hereby granted   *
 * without fee, provided that the above copyright notice appears in all   *
 * copies and that both the copyright notice and this permission notice   *
 * appear in the supporting documentation. The authors make no claims     *
 * about the suitability of this software for any purpose. It is          *
 * provided "as is" without express or implied warranty.                  *
 **************************************************************************/

/* $Id$ */

///////////////////////////////////////////////////////////////////////////////
// PHOS Preprocessor class. It runs by Shuttle at the end of the run,
// calculates calibration coefficients and dead/bad channels
// to be posted in OCDB
//
// Author: Boris Polichtchouk, 4 October 2006
///////////////////////////////////////////////////////////////////////////////

#include "AliPHOSPreprocessor.h"
#include "AliLog.h"
#include "AliCDBMetaData.h"
#include "AliPHOSEmcCalibData.h"
#include "TFile.h"
#include "TH1.h"
#include "TMap.h"
#include "TRandom.h"

ClassImp(AliPHOSPreprocessor)

//_______________________________________________________________________________________
AliPHOSPreprocessor::AliPHOSPreprocessor() :
AliPreprocessor("PHS",0)
{
  //default constructor
}

//_______________________________________________________________________________________
AliPHOSPreprocessor::AliPHOSPreprocessor(AliShuttleInterface* shuttle):
AliPreprocessor("PHS",shuttle)
{
  // Constructor
}

//_______________________________________________________________________________________
UInt_t AliPHOSPreprocessor::Process(TMap* /*valueSet*/)
{
  // process data retrieved by the Shuttle

  // The fileName with the histograms which have been produced by
  // AliPHOSCalibHistoProducer.
  // It is a responsibility of the SHUTTLE framework to form the fileName

  const char* fileName = GetFile(kDAQ, "AMPLITUDES", "GDC");
  AliInfo(Form("Got filename: %s",fileName));

  TFile f(fileName);

  if(!f.IsOpen()) {
    AliInfo(Form("File %s is not opened, something goes wrong!",fileName));
    return 0;
  }

  const Int_t nMod=5; // 1:5 modules
  const Int_t nCol=56; //1:56 columns in each module
  const Int_t nRow=64; //1:64 rows in each module

  Double_t coeff;
  char hnam[80];
  TH1F* histo=0;

  // Generate name of the reference histogram
  TString refHistoName = "mod";
  refHistoName += gRandom->Integer(nMod)+1;
  refHistoName += "col";
  refHistoName += gRandom->Integer(nCol)+1;
  refHistoName += "row";
  refHistoName += gRandom->Integer(nRow)+1;
  TH1F* hRef = (TH1F*)f.Get(refHistoName);

  // If the reference histogram does not exist or has too little statistics,
  // it is better to give up preprocessing
  if(!hRef || hRef->GetEntries()<2) {
    AliInfo(Form("Cannot get reference histogram %s",refHistoName.Data()));
    return 0;
  }

  AliPHOSEmcCalibData calibData;
  Double_t refMean=hRef->GetMean();

  // Calculates relative calibration coefficients for all non-zero channels

  for(Int_t mod=0; mod<nMod; mod++) {
    for(Int_t col=0; col<nCol; col++) {
      for(Int_t row=0; row<nRow; row++) {
        sprintf(hnam,"mod%dcol%drow%d",mod,col,row);
        histo = (TH1F*)f.Get(hnam);
	//TODO: dead channels exclusion!
        if(histo) {
          coeff = histo->GetMean()/refMean;
	  calibData.SetADCchannelEmc(mod+1,col+1,row+1,0.001/coeff);
	  AliInfo(Form("mod %d col %d row %d  coeff %f\n",mod,col,row,coeff));
	}
        else
          calibData.SetADCchannelEmc(mod+1,col+1,row+1,-111);
      }
    }
  }

  AliCDBMetaData metaData;
  Int_t result = Store("Calib", "EmcData", &calibData, &metaData);

  f.Close();
  return result;

}
<commit_msg>New algorithm for selecting a random reference histogram (G.Conesa)<commit_after>/**************************************************************************
 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
 *                                                                        *
 * Author: The ALICE Off-line Project.                                    *
 * Contributors are mentioned in the code where appropriate.              *
 *                                                                        *
 * Permission to use, copy, modify and distribute this software and its   *
 * documentation strictly for non-commercial purposes is hereby granted   *
 * without fee, provided that the above copyright notice appears in all   *
 * copies and that both the copyright notice and this permission notice   *
 * appear in the supporting documentation. The authors make no claims     *
 * about the suitability of this software for any purpose. It is          *
 * provided "as is" without express or implied warranty.                  *
 **************************************************************************/

/* $Id$ */

///////////////////////////////////////////////////////////////////////////////
// PHOS Preprocessor class. It runs by Shuttle at the end of the run,
// calculates calibration coefficients and dead/bad channels
// to be posted in OCDB
//
// Author: Boris Polichtchouk, 4 October 2006
///////////////////////////////////////////////////////////////////////////////

#include "AliPHOSPreprocessor.h"
#include "AliLog.h"
#include "AliCDBMetaData.h"
#include "AliPHOSEmcCalibData.h"
#include "TFile.h"
#include "TH1.h"
#include "TMap.h"
#include "TRandom.h"
#include "TKey.h"

ClassImp(AliPHOSPreprocessor)

//_______________________________________________________________________________________
AliPHOSPreprocessor::AliPHOSPreprocessor() :
AliPreprocessor("PHS",0)
{
  //default constructor
}

//_______________________________________________________________________________________
AliPHOSPreprocessor::AliPHOSPreprocessor(AliShuttleInterface* shuttle):
AliPreprocessor("PHS",shuttle)
{
  // Constructor
}

//_______________________________________________________________________________________
UInt_t AliPHOSPreprocessor::Process(TMap* /*valueSet*/)
{
  // process data retrieved by the Shuttle

  // The fileName with the histograms which have been produced by
  // AliPHOSCalibHistoProducer.
  // It is a responsibility of the SHUTTLE framework to form the fileName

  const char* fileName = GetFile(kDAQ, "AMPLITUDES", "GDC");
  AliInfo(Form("Got filename: %s",fileName));

  TFile f(fileName);

  if(!f.IsOpen()) {
    AliInfo(Form("File %s is not opened, something goes wrong!",fileName));
    return 0;
  }

  const Int_t nMod=5; // 1:5 modules
  const Int_t nCol=56; //1:56 columns in each module
  const Int_t nRow=64; //1:64 rows in each module

  Double_t coeff;
  char hnam[80];
  TH1F* histo=0;

  //Get the reference histogram
  //(author: Gustavo Conesa Balbastre)

  TList * keylist = f.GetListOfKeys();
  Int_t nkeys   = f.GetNkeys();
  Bool_t ok = kFALSE;
  TKey  *key;
  TString refHistoName= "";
  Int_t ikey = 0;
  Int_t counter = 0;
  TH1F* hRef = 0;

  //Check if the file contains any histogram

  if(nkeys< 2){
    AliInfo(Form("Not enough histograms (%d) for calibration.",nkeys));
    return 0;
  }

  while(!ok){
    ikey = gRandom->Integer(nkeys);
    key = (TKey*)keylist->At(ikey);
    refHistoName = key->GetName();
    hRef = (TH1F*)f.Get(refHistoName);
    counter++;
    // Check if the reference histogram has too little statistics
    if(hRef->GetEntries()>2) ok=kTRUE;
    if(!ok && counter >= nMod*nCol*nRow){
      AliInfo("No histogram with enough statistics for reference.");
      return 0;
    }
  }

  AliInfo(Form("reference histogram %s, %.1f entries, mean=%.3f, rms=%.3f.",
	 hRef->GetName(),hRef->GetEntries(),
	 hRef->GetMean(),hRef->GetRMS()));

  AliPHOSEmcCalibData calibData;
  Double_t refMean=hRef->GetMean();

  // Calculates relative calibration coefficients for all non-zero channels

  for(Int_t mod=0; mod<nMod; mod++) {
    for(Int_t col=0; col<nCol; col++) {
      for(Int_t row=0; row<nRow; row++) {
        sprintf(hnam,"mod%dcol%drow%d",mod,col,row);
        histo = (TH1F*)f.Get(hnam);
	//TODO: dead channels exclusion!
        if(histo) {
          coeff = histo->GetMean()/refMean;
	  calibData.SetADCchannelEmc(mod+1,col+1,row+1,0.001/coeff);
	  AliInfo(Form("mod %d col %d row %d  coeff %f\n",mod,col,row,coeff));
	}
        else
          calibData.SetADCchannelEmc(mod+1,col+1,row+1,0.001);
      }
    }
  }

  AliCDBMetaData metaData;
  Int_t result = Store("Calib", "EmcData", &calibData, &metaData);

  f.Close();
  return result;

}
<|endoftext|>


<commit_before>#include "PrecompiledHeader.h"
#include "Etw\Etw.h"
#include "PlugNPlayObjectRegistry.h"
#include "Utilities\EventHandler.h"
#include "Utilities\Fence.h"
#include "Utilities\HandleHolder.h"
#include "Utilities\Vector.h"

using namespace ABI::Windows::Devices::Enumeration::Pnp;
using namespace ABI::Windows::Foundation;
using namespace ABI::Windows::Foundation::Collections;
using namespace PlugNPlay;

PlugNPlayObjectRegistry* PlugNPlayObjectRegistry::s_Instance;

const wchar_t kDEVPKEY_Device_InstanceId[] = L"{78c34fc8-104a-4aca-9ea4-524d52996e57} 256";
const wchar_t kDEVPKEY_Device_DeviceDesc[] = L"{A45C254E-DF1C-4EFD-8020-67D146A850E0} 2";
const wchar_t kDEVPKEY_Device_FriendlyName[] = L"{A45C254E-DF1C-4EFD-8020-67D146A850E0} 14";

HRESULT PlugNPlayObjectRegistry::Create()
{
	Etw::EtwScopedEvent creationEvent("PlugNPlayObjectRegistry", "Create registry");

	auto instance = WRL::Make<PlugNPlayObjectRegistry>();

	auto hr = instance->Initialize();
	if (FAILED(hr))
	{
		instance->Cleanup();
		ReturnIfFailed(hr);
	}

	s_Instance = instance.Detach();
	return S_OK;
}

void PlugNPlayObjectRegistry::Destroy()
{
	auto instance = static_cast<PlugNPlayObjectRegistry*>(InterlockedExchangePointer(reinterpret_cast<void**>(&s_Instance), nullptr));

	if (instance != nullptr)
	{
		instance->Cleanup();
		instance->Release();
	}
}

PlugNPlayObjectRegistry::PlugNPlayObjectRegistry() :
	m_IsPnpObjectWatcherRunning(false),
	m_IsInitialEnumerationCompleted(false),
	m_DirtyStatus(DirtyStatus::kNotDirty)
{
	m_AddedEventToken.value = 0;
	m_UpdatedEventToken.value = 0;
	m_RemovedEventToken.value = 0;
}

HRESULT PlugNPlayObjectRegistry::Initialize()
{
	m_InitialEnumerationCompletedEvent = CreateEventExW(nullptr, nullptr, CREATE_EVENT_MANUAL_RESET, EVENT_ALL_ACCESS);

	auto hr = Windows::Foundation::GetActivationFactory(Utilities::HStringReference(L"Windows.Devices.Enumeration.Pnp.PnpObject"), &m_PnpObjectStatics);
	ReturnIfFailed(hr);

	auto interfaceInstanceIdProperties = WRL::Make<Utilities::Vector<HSTRING>>();
	interfaceInstanceIdProperties->Append(Utilities::HStringReference(kDEVPKEY_Device_InstanceId));

	hr = m_PnpObjectStatics->CreateWatcher(PnpObjectType_DeviceInterface, interfaceInstanceIdProperties.Get(), &m_PnpObjectWatcher);
	ReturnIfFailed(hr);

	WRL::ComPtr<PlugNPlayObjectRegistry> _this = this;

	hr = m_PnpObjectWatcher->add_Added(Utilities::EventHandlerFactory<ITypedEventHandler<PnpObjectWatcher*, PnpObject*>>::Make([_this](IPnpObjectWatcher*, IPnpObject* pnpObject)
	{
		_this->OnObjectAdded(pnpObject);
		return S_OK;
	}).Get(), &m_AddedEventToken);
	ReturnIfFailed(hr);

	hr = m_PnpObjectWatcher->add_Updated(Utilities::EventHandlerFactory<ITypedEventHandler<PnpObjectWatcher*, PnpObjectUpdate*>>::Make([_this](IPnpObjectWatcher*, IPnpObjectUpdate* pnpObject)
	{
		_this->OnObjectUpdated(pnpObject);
		return S_OK;
	}).Get(), &m_UpdatedEventToken);
	ReturnIfFailed(hr);

	hr = m_PnpObjectWatcher->add_Removed(Utilities::EventHandlerFactory<ITypedEventHandler<PnpObjectWatcher*, PnpObjectUpdate*>>::Make([_this](IPnpObjectWatcher*, IPnpObjectUpdate* pnpObject)
	{
		_this->OnObjectRemoved(pnpObject);
		return S_OK;
	}).Get(), &m_RemovedEventToken);
	ReturnIfFailed(hr);

	hr = m_PnpObjectWatcher->add_EnumerationCompleted(Utilities::EventHandlerFactory<ITypedEventHandler<PnpObjectWatcher*, IInspectable*>>::Make([_this](IPnpObjectWatcher*, IInspectable*)
	{
		_this->OnInitialEnumerationCompleted();
		return S_OK;
	}).Get(), &m_InitialEnumerationCompletedToken);
	ReturnIfFailed(hr);

	hr = m_PnpObjectWatcher->Start();
	ReturnIfFailed(hr);

	m_IsPnpObjectWatcherRunning = true;
	return S_OK;
}

void PlugNPlayObjectRegistry::Cleanup()
{
	Etw::EtwScopedEvent cleanupEvent("PlugNPlayObjectRegistry", "Cleanup registry");

	HRESULT hr;

	if (m_PnpObjectWatcher != nullptr)
	{
		if (m_RemovedEventToken.value != 0)
		{
			hr = m_PnpObjectWatcher->remove_Removed(m_RemovedEventToken);
			Assert(SUCCEEDED(hr));

			m_RemovedEventToken.value = 0;
		}

		if (m_UpdatedEventToken.value != 0)
		{
			hr = m_PnpObjectWatcher->remove_Updated(m_UpdatedEventToken);
			Assert(SUCCEEDED(hr));

			m_UpdatedEventToken.value = 0;
		}

		if (m_AddedEventToken.value != 0)
		{
			hr = m_PnpObjectWatcher->remove_Added(m_AddedEventToken);
			Assert(SUCCEEDED(hr));

			m_AddedEventToken.value = 0;
		}

		Utilities::ReaderWriterLock::WriterLock lock(m_RegistryLock);

		if (m_IsPnpObjectWatcherRunning)
		{
			hr = m_PnpObjectWatcher->Stop();
			Assert(SUCCEEDED(hr));

			m_IsPnpObjectWatcherRunning = false;
		}

		m_PnpObjectWatcher = nullptr;
	}
}

HRESULT PlugNPlayObjectRegistry::Lookup(const wchar_t* interfaceInstanceIdSubstring, HSTRING* outName)
{
	Etw::EtwScopedEvent lookupEvent("PlugNPlayObjectRegistry", "Lookup interface instance id substring");

	Assert(s_Instance != nullptr);
	return s_Instance->LookupImpl(interfaceInstanceIdSubstring, outName);
}

static inline HRESULT UnboxString(IInspectable* boxed, HSTRING* outUnboxed)
{
	if (boxed == nullptr)
	{
		*outUnboxed = nullptr;
		return S_OK;
	}

	WRL::ComPtr<IPropertyValue> propertyValue;
	auto hr = boxed->QueryInterface(__uuidof(IPropertyValue), &propertyValue);
	ReturnIfFailed(hr);

	return propertyValue->GetString(outUnboxed);
}

void PlugNPlayObjectRegistry::RebuildRegistry()
{
	Utilities::ReaderWriterLock::WriterLock registryLock(m_RegistryLock);
	Utilities::CriticalSection::Lock objectLock(m_ObjectCriticalSection);

	Etw::EtwScopedEvent rebuildEVent("PlugNPlayObjectRegistry", "Rebuild registry");

	m_DirtyStatus = DirtyStatus::kNotDirty;

	m_InterfaceInstanceIds.clear();
	m_InstanceIdIndices.clear();
	m_DeviceNames.clear();

	Utilities::Fence allDevicesCreatedFence(static_cast<uint32_t>(m_PnpObjects.size()));

	m_InstanceIdIndices.reserve(m_PnpObjects.size());
	m_DeviceNames.resize(m_PnpObjects.size());

	auto deviceNameProperties = WRL::Make<Utilities::Vector<HSTRING>>();
	deviceNameProperties->Append(Utilities::HStringReference(kDEVPKEY_Device_FriendlyName));
	deviceNameProperties->Append(Utilities::HStringReference(kDEVPKEY_Device_DeviceDesc)); // Fallback in case friendly name is not available

	for (auto& pnpObject : m_PnpObjects)
	{
		WRL::ComPtr<IMapView<HSTRING, IInspectable*>> objectProperties;
		auto hr = pnpObject.second->get_Properties(&objectProperties);
		AdvanceFenceAndContinueIfFailed(hr, allDevicesCreatedFence);

		WRL::ComPtr<IInspectable> instanceIdInspectable;
		hr = objectProperties->Lookup(Utilities::HStringReference(L"System.Devices.DeviceInstanceId"), &instanceIdInspectable);
		AdvanceFenceAndContinueIfFailed(hr, allDevicesCreatedFence);

		Utilities::HString deviceId;
		hr = UnboxString(instanceIdInspectable.Get(), &deviceId);
		if (FAILED(hr) || deviceId == nullptr)
		{
			allDevicesCreatedFence.Advance();
			continue;
		}

		WRL::ComPtr<IAsyncOperation<PnpObject*>> createDeviceAsyncOperation;
		hr = m_PnpObjectStatics->CreateFromIdAsync(PnpObjectType_Device, deviceId, deviceNameProperties.Get(), &createDeviceAsyncOperation);
		AdvanceFenceAndContinueIfFailed(hr, allDevicesCreatedFence);

		uint32_t deviceIndex = static_cast<uint32_t>(m_InstanceIdIndices.size());
		hr = createDeviceAsyncOperation->put_Completed(Utilities::EventHandlerFactory<IAsyncOperationCompletedHandler<PnpObject*>>::Make([this, &allDevicesCreatedFence, deviceIndex](IAsyncOperation<PnpObject*>* operation, AsyncStatus asyncStatus)
		{
			Assert(asyncStatus == Completed);

			if (asyncStatus == Completed)
			{
				WRL::ComPtr<IPnpObject> device;
				auto hr = operation->GetResults(&device);
				AdvanceFenceAndReturnSuccessIfFailed(hr, allDevicesCreatedFence);

				WRL::ComPtr<IMapView<HSTRING, IInspectable*>> deviceProperties;
				hr = device->get_Properties(&deviceProperties);
				AdvanceFenceAndReturnSuccessIfFailed(hr, allDevicesCreatedFence);

				WRL::ComPtr<IInspectable> nameInspectable;
				hr = deviceProperties->Lookup(Utilities::HStringReference(kDEVPKEY_Device_FriendlyName), &nameInspectable);

				if (FAILED(hr) || nameInspectable == nullptr)
					hr = deviceProperties->Lookup(Utilities::HStringReference(kDEVPKEY_Device_DeviceDesc), &nameInspectable);

				AdvanceFenceAndReturnSuccessIfFailed(hr, allDevicesCreatedFence);

				Utilities::HString name;
				hr = UnboxString(nameInspectable.Get(), &name);
				AdvanceFenceAndReturnSuccessIfFailed(hr, allDevicesCreatedFence);

				m_DeviceNames[deviceIndex] = std::move(name);
			}

			allDevicesCreatedFence.Advance();
			return S_OK;
		}).Get());
		ContinueIfFailed(hr);

		uint32_t idLength;
		const wchar_t* deviceIdCharacters = pnpObject.first.GetRawBuffer(&idLength);

		m_InstanceIdIndices.push_back(m_InterfaceInstanceIds.size());
		m_InterfaceInstanceIds.insert(m_InterfaceInstanceIds.end(), deviceIdCharacters, deviceIdCharacters + idLength);
		m_InterfaceInstanceIds.push_back(0);
	}

	{
		Etw::EtwScopedEvent waitForFenceEvent("PlugNPlayObjectRegistry", "Synchronize allDevicesCreatedFence");
		allDevicesCreatedFence.Synchronize();
	}
}

void PlugNPlayObjectRegistry::RebuildRegistryIfNeeded()
{
	do
	{
		auto dirty = DirtyStatus::kDirty;
		if (m_DirtyStatus.compare_exchange_strong(dirty, DirtyStatus::kRebuilding, std::memory_order_seq_cst))
			RebuildRegistry();
	}
	while (m_DirtyStatus == DirtyStatus::kRebuilding);
}

void PlugNPlayObjectRegistry::OnObjectAdded(IPnpObject* pnpObject)
{
	Utilities::HString objectId;
	auto hr = pnpObject->get_Id(&objectId);
	Assert(SUCCEEDED(hr));
	if (FAILED(hr)) return;

	Utilities::CriticalSection::Lock lock(m_ObjectCriticalSection);
	m_PnpObjects.emplace(std::move(objectId), pnpObject);

	if (m_IsInitialEnumerationCompleted)
		m_DirtyStatus = DirtyStatus::kDirty;
}

void PlugNPlayObjectRegistry::OnObjectUpdated(IPnpObjectUpdate* pnpObjectUpdate)
{
	Utilities::CriticalSection::Lock lock(m_ObjectCriticalSection);

	if (m_IsInitialEnumerationCompleted)
		m_DirtyStatus = DirtyStatus::kDirty;
}

void PlugNPlayObjectRegistry::OnObjectRemoved(IPnpObjectUpdate* pnpObjectUpdate)
{
	Utilities::HString objectId;
	auto hr = pnpObjectUpdate->get_Id(&objectId);
	Assert(SUCCEEDED(hr));
	if (FAILED(hr)) return;

	Utilities::CriticalSection::Lock lock(m_ObjectCriticalSection);
	m_PnpObjects.erase(objectId);

	if (m_IsInitialEnumerationCompleted)
		m_DirtyStatus = DirtyStatus::kDirty;
}

void PlugNPlayObjectRegistry::OnInitialEnumerationCompleted()
{
	m_IsInitialEnumerationCompleted = true;
	RebuildRegistry();
	SetEvent(m_InitialEnumerationCompletedEvent);
}

HRESULT PlugNPlayObjectRegistry::LookupImpl(const wchar_t* interfaceInstanceIdSubstring, HSTRING* outName)
{
	Assert(s_Instance != nullptr);

	auto waitResult = WaitForSingleObjectEx(s_Instance->m_InitialEnumerationCompletedEvent, INFINITE, FALSE);
	Assert(waitResult == WAIT_OBJECT_0);

	RebuildRegistryIfNeeded();
	Utilities::ReaderWriterLock::ReaderLock lock(m_RegistryLock);

	bool found;
	size_t foundIndex;

	for (size_t i = 0; i < m_InterfaceInstanceIds.size(); i++)
	{
		size_t index = i;
		size_t j = 0;

		while (interfaceInstanceIdSubstring[j] != L'\0' && interfaceInstanceIdSubstring[j] == m_InterfaceInstanceIds[index])
		{
			index++;
			j++;
		}

		if (interfaceInstanceIdSubstring[j] == '\0')
		{
			found = true;
			foundIndex = i;
			break;
		}
	}

	if (!found)
		return E_FAIL;

	auto it = std::upper_bound(m_InstanceIdIndices.begin(), m_InstanceIdIndices.end(), foundIndex);
	if (it == m_InstanceIdIndices.begin())
		return E_FAIL;

	auto deviceName = m_DeviceNames[it - m_InstanceIdIndices.begin() - 1];
	*outName = deviceName.Detach();
	return S_OK;
}<commit_msg>Fix a leak and some misc stuff in PlugNPlayObjectRegistry.<commit_after>#include "PrecompiledHeader.h"
#include "Etw\Etw.h"
#include "PlugNPlayObjectRegistry.h"
#include "Utilities\EventHandler.h"
#include "Utilities\Fence.h"
#include "Utilities\HandleHolder.h"
#include "Utilities\Vector.h"

using namespace ABI::Windows::Devices::Enumeration::Pnp;
using namespace ABI::Windows::Foundation;
using namespace ABI::Windows::Foundation::Collections;
using namespace PlugNPlay;

PlugNPlayObjectRegistry* PlugNPlayObjectRegistry::s_Instance;

const wchar_t kDEVPKEY_Device_InstanceId[] = L"{78c34fc8-104a-4aca-9ea4-524d52996e57} 256";
const wchar_t kDEVPKEY_Device_DeviceDesc[] = L"{A45C254E-DF1C-4EFD-8020-67D146A850E0} 2";
const wchar_t kDEVPKEY_Device_FriendlyName[] = L"{A45C254E-DF1C-4EFD-8020-67D146A850E0} 14";

HRESULT PlugNPlayObjectRegistry::Create()
{
	Etw::EtwScopedEvent creationEvent("PlugNPlayObjectRegistry", "Create registry");

	auto instance = WRL::Make<PlugNPlayObjectRegistry>();

	auto hr = instance->Initialize();
	if (FAILED(hr))
	{
		instance->Cleanup();
		ReturnIfFailed(hr);
	}

	s_Instance = instance.Detach();
	return S_OK;
}

void PlugNPlayObjectRegistry::Destroy()
{
	auto instance = static_cast<PlugNPlayObjectRegistry*>(InterlockedExchangePointer(reinterpret_cast<void**>(&s_Instance), nullptr));

	if (instance != nullptr)
	{
		instance->Cleanup();
		instance->Release();
	}
}

PlugNPlayObjectRegistry::PlugNPlayObjectRegistry() :
	m_IsPnpObjectWatcherRunning(false),
	m_IsInitialEnumerationCompleted(false),
	m_DirtyStatus(DirtyStatus::kNotDirty)
{
	m_AddedEventToken.value = 0;
	m_UpdatedEventToken.value = 0;
	m_RemovedEventToken.value = 0;
	m_InitialEnumerationCompletedToken.value = 0;
}

HRESULT PlugNPlayObjectRegistry::Initialize()
{
	m_InitialEnumerationCompletedEvent = CreateEventExW(nullptr, nullptr, CREATE_EVENT_MANUAL_RESET, EVENT_ALL_ACCESS);

	auto hr = Windows::Foundation::GetActivationFactory(Utilities::HStringReference(L"Windows.Devices.Enumeration.Pnp.PnpObject"), &m_PnpObjectStatics);
	ReturnIfFailed(hr);

	auto interfaceInstanceIdProperties = WRL::Make<Utilities::Vector<HSTRING>>();
	interfaceInstanceIdProperties->Append(Utilities::HStringReference(kDEVPKEY_Device_InstanceId));

	hr = m_PnpObjectStatics->CreateWatcher(PnpObjectType_DeviceInterface, interfaceInstanceIdProperties.Get(), &m_PnpObjectWatcher);
	ReturnIfFailed(hr);

	WRL::ComPtr<PlugNPlayObjectRegistry> _this = this;

	hr = m_PnpObjectWatcher->add_Added(Utilities::EventHandlerFactory<ITypedEventHandler<PnpObjectWatcher*, PnpObject*>>::Make([_this](IPnpObjectWatcher*, IPnpObject* pnpObject)
	{
		_this->OnObjectAdded(pnpObject);
		return S_OK;
	}).Get(), &m_AddedEventToken);
	ReturnIfFailed(hr);

	hr = m_PnpObjectWatcher->add_Updated(Utilities::EventHandlerFactory<ITypedEventHandler<PnpObjectWatcher*, PnpObjectUpdate*>>::Make([_this](IPnpObjectWatcher*, IPnpObjectUpdate* pnpObject)
	{
		_this->OnObjectUpdated(pnpObject);
		return S_OK;
	}).Get(), &m_UpdatedEventToken);
	ReturnIfFailed(hr);

	hr = m_PnpObjectWatcher->add_Removed(Utilities::EventHandlerFactory<ITypedEventHandler<PnpObjectWatcher*, PnpObjectUpdate*>>::Make([_this](IPnpObjectWatcher*, IPnpObjectUpdate* pnpObject)
	{
		_this->OnObjectRemoved(pnpObject);
		return S_OK;
	}).Get(), &m_RemovedEventToken);
	ReturnIfFailed(hr);

	hr = m_PnpObjectWatcher->add_EnumerationCompleted(Utilities::EventHandlerFactory<ITypedEventHandler<PnpObjectWatcher*, IInspectable*>>::Make([_this](IPnpObjectWatcher*, IInspectable*)
	{
		_this->OnInitialEnumerationCompleted();
		return S_OK;
	}).Get(), &m_InitialEnumerationCompletedToken);
	ReturnIfFailed(hr);

	hr = m_PnpObjectWatcher->Start();
	ReturnIfFailed(hr);

	m_IsPnpObjectWatcherRunning = true;
	return S_OK;
}

void PlugNPlayObjectRegistry::Cleanup()
{
	Etw::EtwScopedEvent cleanupEvent("PlugNPlayObjectRegistry", "Cleanup registry");

	HRESULT hr;

	if (m_PnpObjectWatcher != nullptr)
	{
		if (m_RemovedEventToken.value != 0)
		{
			hr = m_PnpObjectWatcher->remove_Removed(m_RemovedEventToken);
			Assert(SUCCEEDED(hr));

			m_RemovedEventToken.value = 0;
		}

		if (m_UpdatedEventToken.value != 0)
		{
			hr = m_PnpObjectWatcher->remove_Updated(m_UpdatedEventToken);
			Assert(SUCCEEDED(hr));

			m_UpdatedEventToken.value = 0;
		}

		if (m_AddedEventToken.value != 0)
		{
			hr = m_PnpObjectWatcher->remove_Added(m_AddedEventToken);
			Assert(SUCCEEDED(hr));

			m_AddedEventToken.value = 0;
		}

		if (m_InitialEnumerationCompletedToken.value != 0)
		{
			hr = m_PnpObjectWatcher->remove_EnumerationCompleted(m_InitialEnumerationCompletedToken);
			Assert(SUCCEEDED(hr));

			m_InitialEnumerationCompletedToken.value = 0;
		}

		Utilities::ReaderWriterLock::WriterLock lock(m_RegistryLock);

		if (m_IsPnpObjectWatcherRunning)
		{
			hr = m_PnpObjectWatcher->Stop();
			Assert(SUCCEEDED(hr));

			m_IsPnpObjectWatcherRunning = false;
		}

		m_PnpObjectWatcher = nullptr;
	}
}

HRESULT PlugNPlayObjectRegistry::Lookup(const wchar_t* interfaceInstanceIdSubstring, HSTRING* outName)
{
	Etw::EtwScopedEvent lookupEvent("PlugNPlayObjectRegistry", "Lookup interface instance id substring");

	Assert(s_Instance != nullptr);
	return s_Instance->LookupImpl(interfaceInstanceIdSubstring, outName);
}

static inline HRESULT UnboxString(IInspectable* boxed, HSTRING* outUnboxed)
{
	if (boxed == nullptr)
	{
		*outUnboxed = nullptr;
		return S_OK;
	}

	WRL::ComPtr<IPropertyValue> propertyValue;
	auto hr = boxed->QueryInterface(__uuidof(IPropertyValue), &propertyValue);
	ReturnIfFailed(hr);

	return propertyValue->GetString(outUnboxed);
}

void PlugNPlayObjectRegistry::RebuildRegistry()
{
	Utilities::ReaderWriterLock::WriterLock registryLock(m_RegistryLock);
	Utilities::CriticalSection::Lock objectLock(m_ObjectCriticalSection);

	Etw::EtwScopedEvent rebuildEvent("PlugNPlayObjectRegistry", "Rebuild registry");

	m_DirtyStatus = DirtyStatus::kNotDirty;

	m_InterfaceInstanceIds.clear();
	m_InstanceIdIndices.clear();
	m_DeviceNames.clear();

	Utilities::Fence allDevicesCreatedFence(static_cast<uint32_t>(m_PnpObjects.size()));

	m_InstanceIdIndices.reserve(m_PnpObjects.size());
	m_DeviceNames.resize(m_PnpObjects.size());

	auto deviceNameProperties = WRL::Make<Utilities::Vector<HSTRING>>();
	deviceNameProperties->Append(Utilities::HStringReference(kDEVPKEY_Device_FriendlyName));
	deviceNameProperties->Append(Utilities::HStringReference(kDEVPKEY_Device_DeviceDesc)); // Fallback in case friendly name is not available

	for (auto& pnpObject : m_PnpObjects)
	{
		WRL::ComPtr<IMapView<HSTRING, IInspectable*>> objectProperties;
		auto hr = pnpObject.second->get_Properties(&objectProperties);
		AdvanceFenceAndContinueIfFailed(hr, allDevicesCreatedFence);

		WRL::ComPtr<IInspectable> instanceIdInspectable;
		hr = objectProperties->Lookup(Utilities::HStringReference(L"System.Devices.DeviceInstanceId"), &instanceIdInspectable);
		AdvanceFenceAndContinueIfFailed(hr, allDevicesCreatedFence);

		Utilities::HString deviceId;
		hr = UnboxString(instanceIdInspectable.Get(), &deviceId);
		if (FAILED(hr) || deviceId == nullptr)
		{
			allDevicesCreatedFence.Advance();
			continue;
		}

		WRL::ComPtr<IAsyncOperation<PnpObject*>> createDeviceAsyncOperation;
		hr = m_PnpObjectStatics->CreateFromIdAsync(PnpObjectType_Device, deviceId, deviceNameProperties.Get(), &createDeviceAsyncOperation);
		AdvanceFenceAndContinueIfFailed(hr, allDevicesCreatedFence);

		uint32_t deviceIndex = static_cast<uint32_t>(m_InstanceIdIndices.size());
		hr = createDeviceAsyncOperation->put_Completed(Utilities::EventHandlerFactory<IAsyncOperationCompletedHandler<PnpObject*>>::Make([this, &allDevicesCreatedFence, deviceIndex](IAsyncOperation<PnpObject*>* operation, AsyncStatus asyncStatus)
		{
			Assert(asyncStatus == Completed);

			if (asyncStatus == Completed)
			{
				WRL::ComPtr<IPnpObject> device;
				auto hr = operation->GetResults(&device);
				AdvanceFenceAndReturnSuccessIfFailed(hr, allDevicesCreatedFence);

				WRL::ComPtr<IMapView<HSTRING, IInspectable*>> deviceProperties;
				hr = device->get_Properties(&deviceProperties);
				AdvanceFenceAndReturnSuccessIfFailed(hr, allDevicesCreatedFence);

				WRL::ComPtr<IInspectable> nameInspectable;
				hr = deviceProperties->Lookup(Utilities::HStringReference(kDEVPKEY_Device_FriendlyName), &nameInspectable);

				if (FAILED(hr) || nameInspectable == nullptr)
					hr = deviceProperties->Lookup(Utilities::HStringReference(kDEVPKEY_Device_DeviceDesc), &nameInspectable);

				AdvanceFenceAndReturnSuccessIfFailed(hr, allDevicesCreatedFence);

				Utilities::HString name;
				hr = UnboxString(nameInspectable.Get(), &name);
				AdvanceFenceAndReturnSuccessIfFailed(hr, allDevicesCreatedFence);

				m_DeviceNames[deviceIndex] = std::move(name);
			}

			allDevicesCreatedFence.Advance();
			return S_OK;
		}).Get());
		ContinueIfFailed(hr);

		uint32_t idLength;
		const wchar_t* deviceIdCharacters = pnpObject.first.GetRawBuffer(&idLength);

		m_InstanceIdIndices.push_back(m_InterfaceInstanceIds.size());
		m_InterfaceInstanceIds.insert(m_InterfaceInstanceIds.end(), deviceIdCharacters, deviceIdCharacters + idLength);
		m_InterfaceInstanceIds.push_back(0);
	}

	{
		Etw::EtwScopedEvent waitForFenceEvent("PlugNPlayObjectRegistry", "Synchronize allDevicesCreatedFence");
		allDevicesCreatedFence.Synchronize();
	}
}

void PlugNPlayObjectRegistry::RebuildRegistryIfNeeded()
{
	do
	{
		auto dirty = DirtyStatus::kDirty;
		if (m_DirtyStatus.compare_exchange_strong(dirty, DirtyStatus::kRebuilding, std::memory_order_seq_cst))
			RebuildRegistry();
	}
	while (m_DirtyStatus == DirtyStatus::kRebuilding);
}

void PlugNPlayObjectRegistry::OnObjectAdded(IPnpObject* pnpObject)
{
	Utilities::HString objectId;
	auto hr = pnpObject->get_Id(&objectId);
	Assert(SUCCEEDED(hr));
	if (FAILED(hr)) return;

	Utilities::CriticalSection::Lock lock(m_ObjectCriticalSection);
	m_PnpObjects.emplace(std::move(objectId), pnpObject);

	if (m_IsInitialEnumerationCompleted)
		m_DirtyStatus = DirtyStatus::kDirty;
}

void PlugNPlayObjectRegistry::OnObjectUpdated(IPnpObjectUpdate* pnpObjectUpdate)
{
	Utilities::CriticalSection::Lock lock(m_ObjectCriticalSection);

	if (m_IsInitialEnumerationCompleted)
		m_DirtyStatus = DirtyStatus::kDirty;
}

void PlugNPlayObjectRegistry::OnObjectRemoved(IPnpObjectUpdate* pnpObjectUpdate)
{
	Utilities::HString objectId;
	auto hr = pnpObjectUpdate->get_Id(&objectId);
	Assert(SUCCEEDED(hr));
	if (FAILED(hr)) return;

	Utilities::CriticalSection::Lock lock(m_ObjectCriticalSection);
	m_PnpObjects.erase(objectId);

	if (m_IsInitialEnumerationCompleted)
		m_DirtyStatus = DirtyStatus::kDirty;
}

void PlugNPlayObjectRegistry::OnInitialEnumerationCompleted()
{
	m_IsInitialEnumerationCompleted = true;
	RebuildRegistry();
	SetEvent(m_InitialEnumerationCompletedEvent);
}

HRESULT PlugNPlayObjectRegistry::LookupImpl(const wchar_t* interfaceInstanceIdSubstring, HSTRING* outName)
{
	auto waitResult = WaitForSingleObjectEx(m_InitialEnumerationCompletedEvent, INFINITE, FALSE);
	Assert(waitResult == WAIT_OBJECT_0);

	RebuildRegistryIfNeeded();
	Utilities::ReaderWriterLock::ReaderLock lock(m_RegistryLock);

	bool found = false;
	size_t foundIndex;

	for (size_t i = 0; i < m_InterfaceInstanceIds.size(); i++)
	{
		size_t index = i;
		size_t j = 0;

		while (interfaceInstanceIdSubstring[j] != L'\0' && interfaceInstanceIdSubstring[j] == m_InterfaceInstanceIds[index])
		{
			index++;
			j++;
		}

		if (interfaceInstanceIdSubstring[j] == '\0')
		{
			found = true;
			foundIndex = i;
			break;
		}
	}

	if (!found)
		return E_FAIL;

	auto it = std::upper_bound(m_InstanceIdIndices.begin(), m_InstanceIdIndices.end(), foundIndex);
	if (it == m_InstanceIdIndices.begin())
		return E_FAIL;

	auto deviceName = m_DeviceNames[it - m_InstanceIdIndices.begin() - 1];
	*outName = deviceName.Detach();
	return S_OK;
}<|endoftext|>


<commit_before>/*
 * Copyright (c) Meta Platforms, Inc. and affiliates.
 *
 * 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.
 */

#include <folly/python/executor.h>

#include <stdexcept>

#include <folly/CppAttributes.h>
#include <folly/python/executor_api.h> // @manual

namespace folly {
namespace python {

namespace {

void ensure_imported() {
  static bool imported = false;
  if (!imported) {
    if (0 != import_folly__executor()) {
      throw std::runtime_error("import_folly__executor failed");
    }
    imported = true;
  }
}

} // namespace

folly::Executor* getExecutor() {
  ensure_imported();
  return get_running_executor(false); // TODO: fried set this to true
}

int setExecutorForLoop(PyObject* loop, AsyncioExecutor* executor) {
  ensure_imported();
  return set_executor_for_loop(loop, executor);
}

} // namespace python
} // namespace folly
<commit_msg>Remove dead includes in folly/python<commit_after>/*
 * Copyright (c) Meta Platforms, Inc. and affiliates.
 *
 * 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.
 */

#include <folly/python/executor.h>

#include <stdexcept>

#include <folly/python/executor_api.h> // @manual

namespace folly {
namespace python {

namespace {

void ensure_imported() {
  static bool imported = false;
  if (!imported) {
    if (0 != import_folly__executor()) {
      throw std::runtime_error("import_folly__executor failed");
    }
    imported = true;
  }
}

} // namespace

folly::Executor* getExecutor() {
  ensure_imported();
  return get_running_executor(false); // TODO: fried set this to true
}

int setExecutorForLoop(PyObject* loop, AsyncioExecutor* executor) {
  ensure_imported();
  return set_executor_for_loop(loop, executor);
}

} // namespace python
} // namespace folly
<|endoftext|>


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

The Medical Imaging Interaction Toolkit (MITK)

Copyright (c) German Cancer Research Center,
Division of Medical and Biological Informatics.
All rights reserved.

This software is distributed WITHOUT ANY WARRANTY; without
even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE.

See LICENSE.txt or http://www.mitk.org for details.

===================================================================*/

#include <usConfig.h>

#include <usTestingMacros.h>
#include <usTestingConfig.h>

#include <usModule.h>
#include <usModuleContext.h>
#include <usGetModuleContext.h>
#include <usServiceInterface.h>
#include <usServiceTracker.h>
#include <usSharedLibrary.h>

#include "usServiceControlInterface.h"

#include <memory>

US_USE_NAMESPACE

bool CheckConvertibility(const std::vector<ServiceReferenceU>& refs,
                         std::vector<std::string>::const_iterator idBegin,
                         std::vector<std::string>::const_iterator idEnd)
{
  std::vector<std::string> ids;
  ids.assign(idBegin, idEnd);

  for (std::vector<ServiceReferenceU>::const_iterator sri = refs.begin();
       sri != refs.end(); ++sri)
  {
    for (std::vector<std::string>::iterator idIter = ids.begin();
         idIter != ids.end(); ++idIter)
    {
      if (sri->IsConvertibleTo(*idIter))
      {
        ids.erase(idIter);
        break;
      }
    }
  }

  return ids.empty();
}

struct MyInterfaceOne {
  virtual ~MyInterfaceOne() {}
};
US_DECLARE_SERVICE_INTERFACE(MyInterfaceOne, "org.cppmicroservices.servicetrackertest.MyInterfaceOne")

struct MyInterfaceTwo {
  virtual ~MyInterfaceTwo() {}
};
US_DECLARE_SERVICE_INTERFACE(MyInterfaceTwo, "org.cppmicroservices.servicetrackertest.MyInterfaceTwo")

class MyCustomizer : public us::ServiceTrackerCustomizer<MyInterfaceOne>
{

public:

  MyCustomizer(us::ModuleContext* context)
    : m_context(context)
  {}

  virtual MyInterfaceOne* AddingService(const ServiceReferenceType& reference)
  {
    US_TEST_CONDITION_REQUIRED(reference, "AddingService() valid reference")
    return m_context->GetService(reference);
  }

  virtual void ModifiedService(const ServiceReferenceType& reference, MyInterfaceOne* service)
  {
    US_TEST_CONDITION(reference, "ModifiedService() valid reference")
    US_TEST_CONDITION(service, "ModifiedService() valid service")
  }

  virtual void RemovedService(const ServiceReferenceType& reference, MyInterfaceOne* service)
  {
    US_TEST_CONDITION(reference, "RemovedService() valid reference")
    US_TEST_CONDITION(service, "RemovedService() valid service")
  }

private:

  us::ModuleContext* m_context;
};

void TestFilterString()
{
  us::ModuleContext* context = us::GetModuleContext();
  MyCustomizer customizer(context);

  us::LDAPFilter filter("(" + us::ServiceConstants::SERVICE_ID() + ">=0)");
  us::ServiceTracker<MyInterfaceOne> tracker(context, filter, &customizer);
  tracker.Open();

  struct MyServiceOne : public MyInterfaceOne {};
  struct MyServiceTwo : public MyInterfaceTwo {};

  MyServiceOne serviceOne;
  MyServiceTwo serviceTwo;

  context->RegisterService<MyInterfaceOne>(&serviceOne);
  context->RegisterService<MyInterfaceTwo>(&serviceTwo);

  US_TEST_CONDITION(tracker.GetServiceReferences().size() == 1, "tracking count")
}

void TestServiceTracker()
{

#ifdef US_PLATFORM_WINDOWS
  const std::string LIB_PATH = US_RUNTIME_OUTPUT_DIRECTORY;
#else
  const std::string LIB_PATH = US_LIBRARY_OUTPUT_DIRECTORY;
#endif

  ModuleContext* mc = GetModuleContext();
  SharedLibrary libS(LIB_PATH, "TestModuleS");

#ifdef US_BUILD_SHARED_LIBS
  // Start the test target to get a service published.
  try
  {
    libS.Load();
  }
  catch (const std::exception& e)
  {
    US_TEST_FAILED_MSG( << "Failed to load module, got exception: " << e.what() );
  }
#endif

  // 1. Create a ServiceTracker with ServiceTrackerCustomizer == null

  std::string s1("org.cppmicroservices.TestModuleSService");
  ServiceReferenceU servref = mc->GetServiceReference(s1 + "0");

  US_TEST_CONDITION_REQUIRED(servref != 0, "Test if registered service of id org.cppmicroservices.TestModuleSService0");

  ServiceReference<ServiceControlInterface> servCtrlRef = mc->GetServiceReference<ServiceControlInterface>();
  US_TEST_CONDITION_REQUIRED(servCtrlRef != 0, "Test if constrol service was registered");

  ServiceControlInterface* serviceController = mc->GetService(servCtrlRef);
  US_TEST_CONDITION_REQUIRED(serviceController != 0, "Test valid service controller");

  std::auto_ptr<ServiceTracker<void> > st1(new ServiceTracker<void>(mc, servref));

  // 2. Check the size method with an unopened service tracker

  US_TEST_CONDITION_REQUIRED(st1->Size() == 0, "Test if size == 0");

  // 3. Open the service tracker and see what it finds,
  // expect to find one instance of the implementation,
  // "org.cppmicroservices.TestModuleSService0"

  st1->Open();
  std::vector<ServiceReferenceU> sa2 = st1->GetServiceReferences();

  US_TEST_CONDITION_REQUIRED(sa2.size() == 1, "Checking ServiceTracker size");
  US_TEST_CONDITION_REQUIRED(s1 + "0" == sa2[0].GetInterfaceId(), "Checking service implementation name");

  // 5. Close this service tracker
  st1->Close();

  // 6. Check the size method, now when the servicetracker is closed
  US_TEST_CONDITION_REQUIRED(st1->Size() == 0, "Checking ServiceTracker size");

  // 7. Check if we still track anything , we should get null
  sa2 = st1->GetServiceReferences();
  US_TEST_CONDITION_REQUIRED(sa2.empty(), "Checking ServiceTracker size");

  // 8. A new Servicetracker, this time with a filter for the object
  std::string fs = std::string("(") + ServiceConstants::OBJECTCLASS() + "=" + s1 + "*" + ")";
  LDAPFilter f1(fs);
  st1.reset(new ServiceTracker<void>(mc, f1));
  // add a service
  serviceController->ServiceControl(1, "register", 7);

  // 9. Open the service tracker and see what it finds,
  // expect to find two instances of references to
  // "org.cppmicroservices.TestModuleSService*"
  // i.e. they refer to the same piece of code

  std::vector<std::string> ids;
  ids.push_back((s1 + "0"));
  ids.push_back((s1 + "1"));
  ids.push_back((s1 + "2"));
  ids.push_back((s1 + "3"));

  st1->Open();
  sa2 = st1->GetServiceReferences();
  US_TEST_CONDITION_REQUIRED(sa2.size() == 2, "Checking service reference count");
  US_TEST_CONDITION_REQUIRED(CheckConvertibility(sa2, ids.begin(), ids.begin()+2), "Check for expected interface id [0]");
  US_TEST_CONDITION_REQUIRED(sa2[1].IsConvertibleTo(s1 + "1"), "Check for expected interface id [1]");

  // 10. Get libTestModuleS to register one more service and see if it appears
  serviceController->ServiceControl(2, "register", 1);
  sa2 = st1->GetServiceReferences();

  US_TEST_CONDITION_REQUIRED(sa2.size() == 3, "Checking service reference count");

  US_TEST_CONDITION_REQUIRED(CheckConvertibility(sa2, ids.begin(), ids.begin()+3), "Check for expected interface id [2]");

  // 11. Get libTestModuleS to register one more service and see if it appears
  serviceController->ServiceControl(3, "register", 2);
  sa2 = st1->GetServiceReferences();
  US_TEST_CONDITION_REQUIRED(sa2.size() == 4, "Checking service reference count");
  US_TEST_CONDITION_REQUIRED(CheckConvertibility(sa2, ids.begin(), ids.end()), "Check for expected interface id [3]");

  // 12. Get libTestModuleS to unregister one service and see if it disappears
  serviceController->ServiceControl(3, "unregister", 0);
  sa2 = st1->GetServiceReferences();
  US_TEST_CONDITION_REQUIRED(sa2.size() == 3, "Checking service reference count");

  // 13. Get the highest ranking service reference, it should have ranking 7
  ServiceReferenceU h1 = st1->GetServiceReference();
  int rank = any_cast<int>(h1.GetProperty(ServiceConstants::SERVICE_RANKING()));
  US_TEST_CONDITION_REQUIRED(rank == 7, "Check service rank");

  // 14. Get the service of the highest ranked service reference

  InterfaceMap o1 = st1->GetService(h1);
  US_TEST_CONDITION_REQUIRED(!o1.empty(), "Check for non-null service");

  // 14a Get the highest ranked service, directly this time
  InterfaceMap o3 = st1->GetService();
  US_TEST_CONDITION_REQUIRED(!o3.empty(), "Check for non-null service");
  US_TEST_CONDITION_REQUIRED(o1 == o3, "Check for equal service instances");

  // 15. Now release the tracking of that service and then try to get it
  //     from the servicetracker, which should yield a null object
  serviceController->ServiceControl(1, "unregister", 7);
  InterfaceMap o2 = st1->GetService(h1);
  US_TEST_CONDITION_REQUIRED(o2.empty(), "Checkt that service is null");

  // 16. Get all service objects this tracker tracks, it should be 2
  std::vector<InterfaceMap> ts1 = st1->GetServices();
  US_TEST_CONDITION_REQUIRED(ts1.size() == 2, "Check service count");

  // 17. Test the remove method.
  //     First register another service, then remove it being tracked
  serviceController->ServiceControl(1, "register", 7);
  h1 = st1->GetServiceReference();
  std::vector<ServiceReferenceU> sa3 = st1->GetServiceReferences();
  US_TEST_CONDITION_REQUIRED(sa3.size() == 3, "Check service reference count");
  US_TEST_CONDITION_REQUIRED(CheckConvertibility(sa3, ids.begin(), ids.begin()+3), "Check for expected interface id [0]");

  st1->Remove(h1);           // remove tracking on one servref
  sa2 = st1->GetServiceReferences();
  US_TEST_CONDITION_REQUIRED(sa2.size() == 2, "Check service reference count");

  // 18. Test the addingService method,add a service reference

  // 19. Test the removedService method, remove a service reference

  // 20. Test the waitForService method
  InterfaceMap o9 = st1->WaitForService(50);
  US_TEST_CONDITION_REQUIRED(!o9.empty(), "Checking WaitForService method");
}

int usServiceTrackerTest(int /*argc*/, char* /*argv*/[])
{
  US_TEST_BEGIN("ServiceTrackerTest")

  TestFilterString();
  TestServiceTracker();

  US_TEST_END()
}
<commit_msg>Unregister services after test method ends.<commit_after>/*===================================================================

The Medical Imaging Interaction Toolkit (MITK)

Copyright (c) German Cancer Research Center,
Division of Medical and Biological Informatics.
All rights reserved.

This software is distributed WITHOUT ANY WARRANTY; without
even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE.

See LICENSE.txt or http://www.mitk.org for details.

===================================================================*/

#include <usConfig.h>

#include <usTestingMacros.h>
#include <usTestingConfig.h>

#include <usModule.h>
#include <usModuleContext.h>
#include <usGetModuleContext.h>
#include <usServiceInterface.h>
#include <usServiceTracker.h>
#include <usSharedLibrary.h>

#include "usServiceControlInterface.h"

#include <memory>

US_USE_NAMESPACE

bool CheckConvertibility(const std::vector<ServiceReferenceU>& refs,
                         std::vector<std::string>::const_iterator idBegin,
                         std::vector<std::string>::const_iterator idEnd)
{
  std::vector<std::string> ids;
  ids.assign(idBegin, idEnd);

  for (std::vector<ServiceReferenceU>::const_iterator sri = refs.begin();
       sri != refs.end(); ++sri)
  {
    for (std::vector<std::string>::iterator idIter = ids.begin();
         idIter != ids.end(); ++idIter)
    {
      if (sri->IsConvertibleTo(*idIter))
      {
        ids.erase(idIter);
        break;
      }
    }
  }

  return ids.empty();
}

struct MyInterfaceOne {
  virtual ~MyInterfaceOne() {}
};
US_DECLARE_SERVICE_INTERFACE(MyInterfaceOne, "org.cppmicroservices.servicetrackertest.MyInterfaceOne")

struct MyInterfaceTwo {
  virtual ~MyInterfaceTwo() {}
};
US_DECLARE_SERVICE_INTERFACE(MyInterfaceTwo, "org.cppmicroservices.servicetrackertest.MyInterfaceTwo")

class MyCustomizer : public us::ServiceTrackerCustomizer<MyInterfaceOne>
{

public:

  MyCustomizer(us::ModuleContext* context)
    : m_context(context)
  {}

  virtual MyInterfaceOne* AddingService(const ServiceReferenceType& reference)
  {
    US_TEST_CONDITION_REQUIRED(reference, "AddingService() valid reference")
    return m_context->GetService(reference);
  }

  virtual void ModifiedService(const ServiceReferenceType& reference, MyInterfaceOne* service)
  {
    US_TEST_CONDITION(reference, "ModifiedService() valid reference")
    US_TEST_CONDITION(service, "ModifiedService() valid service")
  }

  virtual void RemovedService(const ServiceReferenceType& reference, MyInterfaceOne* service)
  {
    US_TEST_CONDITION(reference, "RemovedService() valid reference")
    US_TEST_CONDITION(service, "RemovedService() valid service")
  }

private:

  us::ModuleContext* m_context;
};

void TestFilterString()
{
  us::ModuleContext* context = us::GetModuleContext();
  MyCustomizer customizer(context);

  us::LDAPFilter filter("(" + us::ServiceConstants::SERVICE_ID() + ">=0)");
  us::ServiceTracker<MyInterfaceOne> tracker(context, filter, &customizer);
  tracker.Open();

  struct MyServiceOne : public MyInterfaceOne {};
  struct MyServiceTwo : public MyInterfaceTwo {};

  MyServiceOne serviceOne;
  MyServiceTwo serviceTwo;

  ServiceRegistration<MyInterfaceOne> reg1 = context->RegisterService<MyInterfaceOne>(&serviceOne);
  ServiceRegistration<MyInterfaceTwo> reg2 = context->RegisterService<MyInterfaceTwo>(&serviceTwo);

  US_TEST_CONDITION(tracker.GetServiceReferences().size() == 1, "tracking count")

  reg1.Unregister();
  reg2.Unregister();
}

void TestServiceTracker()
{

#ifdef US_PLATFORM_WINDOWS
  const std::string LIB_PATH = US_RUNTIME_OUTPUT_DIRECTORY;
#else
  const std::string LIB_PATH = US_LIBRARY_OUTPUT_DIRECTORY;
#endif

  ModuleContext* mc = GetModuleContext();
  SharedLibrary libS(LIB_PATH, "TestModuleS");

#ifdef US_BUILD_SHARED_LIBS
  // Start the test target to get a service published.
  try
  {
    libS.Load();
  }
  catch (const std::exception& e)
  {
    US_TEST_FAILED_MSG( << "Failed to load module, got exception: " << e.what() );
  }
#endif

  // 1. Create a ServiceTracker with ServiceTrackerCustomizer == null

  std::string s1("org.cppmicroservices.TestModuleSService");
  ServiceReferenceU servref = mc->GetServiceReference(s1 + "0");

  US_TEST_CONDITION_REQUIRED(servref != 0, "Test if registered service of id org.cppmicroservices.TestModuleSService0");

  ServiceReference<ServiceControlInterface> servCtrlRef = mc->GetServiceReference<ServiceControlInterface>();
  US_TEST_CONDITION_REQUIRED(servCtrlRef != 0, "Test if constrol service was registered");

  ServiceControlInterface* serviceController = mc->GetService(servCtrlRef);
  US_TEST_CONDITION_REQUIRED(serviceController != 0, "Test valid service controller");

  std::auto_ptr<ServiceTracker<void> > st1(new ServiceTracker<void>(mc, servref));

  // 2. Check the size method with an unopened service tracker

  US_TEST_CONDITION_REQUIRED(st1->Size() == 0, "Test if size == 0");

  // 3. Open the service tracker and see what it finds,
  // expect to find one instance of the implementation,
  // "org.cppmicroservices.TestModuleSService0"

  st1->Open();
  std::vector<ServiceReferenceU> sa2 = st1->GetServiceReferences();

  US_TEST_CONDITION_REQUIRED(sa2.size() == 1, "Checking ServiceTracker size");
  US_TEST_CONDITION_REQUIRED(s1 + "0" == sa2[0].GetInterfaceId(), "Checking service implementation name");

  // 5. Close this service tracker
  st1->Close();

  // 6. Check the size method, now when the servicetracker is closed
  US_TEST_CONDITION_REQUIRED(st1->Size() == 0, "Checking ServiceTracker size");

  // 7. Check if we still track anything , we should get null
  sa2 = st1->GetServiceReferences();
  US_TEST_CONDITION_REQUIRED(sa2.empty(), "Checking ServiceTracker size");

  // 8. A new Servicetracker, this time with a filter for the object
  std::string fs = std::string("(") + ServiceConstants::OBJECTCLASS() + "=" + s1 + "*" + ")";
  LDAPFilter f1(fs);
  st1.reset(new ServiceTracker<void>(mc, f1));
  // add a service
  serviceController->ServiceControl(1, "register", 7);

  // 9. Open the service tracker and see what it finds,
  // expect to find two instances of references to
  // "org.cppmicroservices.TestModuleSService*"
  // i.e. they refer to the same piece of code

  std::vector<std::string> ids;
  ids.push_back((s1 + "0"));
  ids.push_back((s1 + "1"));
  ids.push_back((s1 + "2"));
  ids.push_back((s1 + "3"));

  st1->Open();
  sa2 = st1->GetServiceReferences();
  US_TEST_CONDITION_REQUIRED(sa2.size() == 2, "Checking service reference count");
  US_TEST_CONDITION_REQUIRED(CheckConvertibility(sa2, ids.begin(), ids.begin()+2), "Check for expected interface id [0]");
  US_TEST_CONDITION_REQUIRED(sa2[1].IsConvertibleTo(s1 + "1"), "Check for expected interface id [1]");

  // 10. Get libTestModuleS to register one more service and see if it appears
  serviceController->ServiceControl(2, "register", 1);
  sa2 = st1->GetServiceReferences();

  US_TEST_CONDITION_REQUIRED(sa2.size() == 3, "Checking service reference count");

  US_TEST_CONDITION_REQUIRED(CheckConvertibility(sa2, ids.begin(), ids.begin()+3), "Check for expected interface id [2]");

  // 11. Get libTestModuleS to register one more service and see if it appears
  serviceController->ServiceControl(3, "register", 2);
  sa2 = st1->GetServiceReferences();
  US_TEST_CONDITION_REQUIRED(sa2.size() == 4, "Checking service reference count");
  US_TEST_CONDITION_REQUIRED(CheckConvertibility(sa2, ids.begin(), ids.end()), "Check for expected interface id [3]");

  // 12. Get libTestModuleS to unregister one service and see if it disappears
  serviceController->ServiceControl(3, "unregister", 0);
  sa2 = st1->GetServiceReferences();
  US_TEST_CONDITION_REQUIRED(sa2.size() == 3, "Checking service reference count");

  // 13. Get the highest ranking service reference, it should have ranking 7
  ServiceReferenceU h1 = st1->GetServiceReference();
  int rank = any_cast<int>(h1.GetProperty(ServiceConstants::SERVICE_RANKING()));
  US_TEST_CONDITION_REQUIRED(rank == 7, "Check service rank");

  // 14. Get the service of the highest ranked service reference

  InterfaceMap o1 = st1->GetService(h1);
  US_TEST_CONDITION_REQUIRED(!o1.empty(), "Check for non-null service");

  // 14a Get the highest ranked service, directly this time
  InterfaceMap o3 = st1->GetService();
  US_TEST_CONDITION_REQUIRED(!o3.empty(), "Check for non-null service");
  US_TEST_CONDITION_REQUIRED(o1 == o3, "Check for equal service instances");

  // 15. Now release the tracking of that service and then try to get it
  //     from the servicetracker, which should yield a null object
  serviceController->ServiceControl(1, "unregister", 7);
  InterfaceMap o2 = st1->GetService(h1);
  US_TEST_CONDITION_REQUIRED(o2.empty(), "Checkt that service is null");

  // 16. Get all service objects this tracker tracks, it should be 2
  std::vector<InterfaceMap> ts1 = st1->GetServices();
  US_TEST_CONDITION_REQUIRED(ts1.size() == 2, "Check service count");

  // 17. Test the remove method.
  //     First register another service, then remove it being tracked
  serviceController->ServiceControl(1, "register", 7);
  h1 = st1->GetServiceReference();
  std::vector<ServiceReferenceU> sa3 = st1->GetServiceReferences();
  US_TEST_CONDITION_REQUIRED(sa3.size() == 3, "Check service reference count");
  US_TEST_CONDITION_REQUIRED(CheckConvertibility(sa3, ids.begin(), ids.begin()+3), "Check for expected interface id [0]");

  st1->Remove(h1);           // remove tracking on one servref
  sa2 = st1->GetServiceReferences();
  US_TEST_CONDITION_REQUIRED(sa2.size() == 2, "Check service reference count");

  // 18. Test the addingService method,add a service reference

  // 19. Test the removedService method, remove a service reference

  // 20. Test the waitForService method
  InterfaceMap o9 = st1->WaitForService(50);
  US_TEST_CONDITION_REQUIRED(!o9.empty(), "Checking WaitForService method");
}

int usServiceTrackerTest(int /*argc*/, char* /*argv*/[])
{
  US_TEST_BEGIN("ServiceTrackerTest")

  TestFilterString();
  TestServiceTracker();

  US_TEST_END()
}
<|endoftext|>


<commit_before>/*
 * opencog/attentionbank/AttentionBank.cc
 *
 * Copyright (C) 2013,2017 Linas Vepstas <linasvepstas@gmail.com>
 * All Rights Reserved
 *
 * Written by Joel Pitt
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License v3 as
 * published by the Free Software Foundation and including the exceptions
 * at http://opencog.org/wiki/Licenses
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program; if not, write to:
 * Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

#include <functional>
#include <opencog/util/Config.h>
#include <opencog/util/mt19937ar.h>

#include <opencog/atoms/base/Handle.h>
#include <opencog/atomspace/AtomSpace.h>
#include "AttentionBank.h"
#include "AVUtils.h"

using namespace opencog;

AttentionBank::AttentionBank(AtomSpace* asp)
{
    startingFundsSTI = fundsSTI = config().get_double("STARTING_STI_FUNDS", 100000);
    startingFundsLTI = fundsLTI = config().get_double("STARTING_LTI_FUNDS", 100000);
    stiFundsBuffer = config().get_double("STI_FUNDS_BUFFER", 10000);
    ltiFundsBuffer = config().get_double("LTI_FUNDS_BUFFER", 10000);
    targetLTI = config().get_double("TARGET_LTI_FUNDS", 10000);
    targetSTI = config().get_double("TARGET_STI_FUNDS", 10000);
    STIAtomWage = config().get_double("ECAN_STARTING_ATOM_STI_WAGE", 10);
    LTIAtomWage = config().get_double("ECAN_STARTING_ATOM_LTI_WAGE", 10);
    maxAFSize = config().get_int("ECAN_MAX_AF_SIZE", 100);

    _remove_signal = &asp->atomRemovedSignal();
    _remove_connection = _remove_signal->connect(
            std::bind(&AttentionBank::remove_atom_from_bank, this,
                std::placeholders::_1));
}

AttentionBank::~AttentionBank()
{
    //_remove_signal->disconnect(_remove_connection);
}

void AttentionBank::remove_atom_from_bank(const AtomPtr& atom)
{
    AFMutex.lock();
    auto it = std::find_if(attentionalFocus.begin(), attentionalFocus.end(),
                [atom](std::pair<Handle, AttentionValuePtr> p)
                { return p.first == Handle(atom);});

    if (it != attentionalFocus.end())
        attentionalFocus.erase(it);
    AFMutex.unlock();

   _importanceIndex.removeAtom(Handle(atom));
}

void AttentionBank::set_sti(const Handle& h, AttentionValue::sti_t stiValue)
{
    AttentionValuePtr oldav = get_av(h);
    AttentionValuePtr newav = AttentionValue::createAV(
        stiValue, oldav->getLTI(), oldav->getVLTI());

    _importanceIndex.updateImportance(h, oldav, newav);
    AVChanged(h, oldav, newav);
}

void AttentionBank::set_lti(const Handle& h, AttentionValue::lti_t ltiValue)
{
    AttentionValuePtr old_av = get_av(h);
    AttentionValuePtr new_av = AttentionValue::createAV(
        old_av->getSTI(), ltiValue, old_av->getVLTI());

    AVChanged(h, old_av, new_av);
}

void AttentionBank::change_vlti(const Handle& h, int unit)
{
    AttentionValuePtr old_av = get_av(h);
    AttentionValuePtr new_av = AttentionValue::createAV(
        old_av->getSTI(),
        old_av->getLTI(),
        old_av->getVLTI() + unit);

    AVChanged(h, old_av, new_av);
}

void AttentionBank::change_av(const Handle& h, const AttentionValuePtr& new_av)
{
    AttentionValuePtr old_av = get_av(h);
    _importanceIndex.updateImportance(h, old_av, new_av);
    AVChanged(h, old_av, new_av);
}

void AttentionBank::AVChanged(const Handle& h,
                              const AttentionValuePtr& old_av,
                              const AttentionValuePtr& new_av)
{
    _mtx.lock();
    // First, update the atom's actual AV.
    set_av(h, new_av);

    AttentionValue::sti_t oldSti = old_av->getSTI();
    AttentionValue::sti_t newSti = new_av->getSTI();

    // Add the old attention values to the AttentionBank funds and
    // subtract the new attention values from the AttentionBank funds
    fundsSTI += (oldSti - newSti);
    fundsLTI += (old_av->getLTI() - new_av->getLTI());

    _importanceIndex.update();

    _mtx.unlock();

    logger().fine("AVChanged: fundsSTI = %d, old_av: %d, new_av: %d",
                   fundsSTI, oldSti, newSti);

    // Notify any interested parties that the AV changed.
    _AVChangedSignal.emit(h, old_av, new_av);

    // update AF
    updateAttentionalFocus(h, old_av, new_av);
}

void AttentionBank::stimulate(const Handle& h, double stimulus)
{
    // XXX This is not protected or made atomic in any way ...
    // If two different threads stimulate the same atom at the same
    // time, then the calculations will be bad. Does it matter?
    AttentionValuePtr oldav(get_av(h));
    AttentionValue::sti_t sti   = oldav->getSTI();
    AttentionValue::lti_t lti   = oldav->getLTI();
    AttentionValue::vlti_t vlti = oldav->getVLTI();

    AttentionValue::sti_t stiWage = calculateSTIWage() * stimulus;
    AttentionValue::lti_t ltiWage = calculateLTIWage() * stimulus;
    AttentionValuePtr newav = AttentionValue::createAV(
           sti + stiWage, lti + ltiWage, vlti);
    _importanceIndex.updateImportance(h, oldav, newav);
    AVChanged(h, oldav, newav);

#ifdef ECAN_EXPERIMENT
    if(stimulusRec.find(h) != stimulusRec.end()){
        stimulusRec[h] += stimulus;
    } else{
        stimulusRec[h] = stimulus;
    }
#endif
}

AttentionValue::sti_t AttentionBank::calculateSTIWage()
{
    AttentionValue::sti_t funds = getSTIFunds();
    AttentionValue::sti_t diff  = funds - targetSTI;
    AttentionValue::sti_t ndiff = diff / stiFundsBuffer;
    ndiff = std::min(ndiff, 1.0);
    ndiff = std::max(ndiff, -1.0);

    return STIAtomWage + (STIAtomWage * ndiff);
}

AttentionValue::lti_t AttentionBank::calculateLTIWage()
{
    AttentionValue::lti_t funds = getLTIFunds();
    AttentionValue::lti_t diff  = funds - targetLTI;
    AttentionValue::lti_t ndiff = diff / ltiFundsBuffer;
    ndiff = std::min(ndiff, 1.0);
    ndiff = std::max(ndiff, -1.0);

    return LTIAtomWage + (LTIAtomWage * ndiff);
}

double AttentionBank::getNormalisedSTI(AttentionValuePtr av,
                                   bool average, bool clip) const
{
    double val;
    // get normalizer (maxSTI - attention boundary)
    AttentionValue::sti_t s = av->getSTI();
    if (s > get_af_max_sti()) {
        int normaliser = (int) getMaxSTI(average) - get_af_max_sti();
        if (normaliser == 0) return 0.0;
        val = (s - get_af_max_sti()) / (double) normaliser;
    } else {
        int normaliser = -((int) getMinSTI(average) + get_af_max_sti());
        if (normaliser == 0) return 0.0;
        val = (s + get_af_max_sti()) / (double) normaliser;

    }

    if (clip) return std::max(-1.0, std::min(val, 1.0));
    return val;
}

double AttentionBank::getNormalisedSTI(AttentionValuePtr av) const
{
    AttentionValue::sti_t s = av->getSTI();
    auto normaliser =
            s > get_af_max_sti() ? getMaxSTI() : getMinSTI();

    return (s / normaliser);
}

double AttentionBank::getNormalisedZeroToOneSTI(AttentionValuePtr av,
                                    bool average, bool clip) const
{
    AttentionValue::sti_t s = av->getSTI();
    int normaliser = getMaxSTI(average) - getMinSTI(average);

    if (normaliser == 0) return 0.0;

    double val = (s - getMinSTI(average)) / (double) normaliser;
    if (clip) return std::max(0.0, std::min(val, 1.0));
    return val;
}

/** Unique singleton instance (for now) */
// This implementation is pretty hokey, and is a stop-gap until some
// sort of more elegant way of managing the attentionbank is found.
// One of the issues is that access via this function can be CPU-wasteful.
AttentionBank& opencog::attentionbank(AtomSpace* asp)
{
    static AttentionBank* _instance = nullptr;
    static AtomSpace* _as = nullptr;

    // Protect setting and getting against thread races.
    // This is probably not needed.
    static std::map<AtomSpace*, AttentionBank*> banksy;
    static std::mutex art;
    std::unique_lock<std::mutex> graffiti(art);

    if (_as != asp and _instance) {
        delete _instance;
        _instance = nullptr;
        _as = nullptr;
    }
    if (asp and nullptr == _instance) {
        _instance = new AttentionBank(asp);
        _as = asp;
    }
    return *_instance;
}

bool AttentionBank::atom_is_in_AF(const Handle& h)
{
    auto it = std::find_if(attentionalFocus.begin(), attentionalFocus.end(),
            [h](std::pair<Handle, AttentionValuePtr> p)
            {
               if (p.first == h) return true;
               return false;
            });
    return  (it != attentionalFocus.end());
}

/**
 *  Updates list of top K important atoms based on STI value.
 */
void AttentionBank::updateAttentionalFocus(const Handle& h,
                    const AttentionValuePtr& old_av,
                    const AttentionValuePtr& new_av)
{
    std::lock_guard<std::mutex> lock(AFMutex);
    AttentionValue::sti_t sti = new_av->getSTI();
    auto least = attentionalFocus.begin(); // Atom to be removed from the AF
    bool insertable = false;
    auto it = std::find_if(attentionalFocus.begin(), attentionalFocus.end(),
            [h](std::pair<Handle, AttentionValuePtr> p)
            { return p.first == h;});

    // Update the STI value if atoms was already in AF
    if (it != attentionalFocus.end())
    {
        attentionalFocus.erase(it);
        attentionalFocus.insert(std::make_pair(h, new_av));
        return;
    }

    // Simply insert the new Atom if AF is not full yet.
    else if (attentionalFocus.size() < maxAFSize)
    {
        insertable = true;
    }

    // Remove the least sti valued atom in the AF and replace
    // it with the new atom holding a higher STI value.
    else if (sti > (least->second)->getSTI())
    {
        Handle hrm = least->first;
        AttentionValuePtr hrm_new_av = get_av(hrm);
        // Value recorded when this atom entered into AF
        AttentionValuePtr hrm_old_av = least->second;

        attentionalFocus.erase(least);
        AFCHSigl& afch = RemoveAFSignal();
        afch.emit(hrm, hrm_old_av, hrm_new_av);
        insertable = true;
    }

    // Insert the new atom in to AF and emit the AddAFSignal.
    if (insertable)
    {
        attentionalFocus.insert(std::make_pair(h, new_av));
        AFCHSigl& afch = AddAFSignal();
        afch.emit(h, old_av, new_av);
    }
}

Handle AttentionBank::getRandomAtomNotInAF(void)
{
    UnorderedHandleSet atoms_not_in_af = _importanceIndex.getHandleSet(0);

    {
        std::lock_guard<std::mutex> lock(AFMutex);
        for (const auto& hsp : attentionalFocus) {
            atoms_not_in_af.erase(hsp.first);
        }
    }

    if (atoms_not_in_af.empty())
        return Handle::UNDEFINED;

    auto seed = std::chrono::duration_cast<std::chrono::microseconds>(
            std::chrono::system_clock::now().time_since_epoch());
    MT19937RandGen rng(seed.count());

    auto it = atoms_not_in_af.cbegin();
    std::advance(it, rng.randint(atoms_not_in_af.size()));
    return *it;
}
<commit_msg>Use shared randonm generator instance<commit_after>/*
 * opencog/attentionbank/AttentionBank.cc
 *
 * Copyright (C) 2013,2017 Linas Vepstas <linasvepstas@gmail.com>
 * All Rights Reserved
 *
 * Written by Joel Pitt
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License v3 as
 * published by the Free Software Foundation and including the exceptions
 * at http://opencog.org/wiki/Licenses
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program; if not, write to:
 * Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

#include <functional>
#include <opencog/util/Config.h>
#include <opencog/util/mt19937ar.h>

#include <opencog/atoms/base/Handle.h>
#include <opencog/atomspace/AtomSpace.h>
#include "AttentionBank.h"
#include "AVUtils.h"

using namespace opencog;

AttentionBank::AttentionBank(AtomSpace* asp)
{
    startingFundsSTI = fundsSTI = config().get_double("STARTING_STI_FUNDS", 100000);
    startingFundsLTI = fundsLTI = config().get_double("STARTING_LTI_FUNDS", 100000);
    stiFundsBuffer = config().get_double("STI_FUNDS_BUFFER", 10000);
    ltiFundsBuffer = config().get_double("LTI_FUNDS_BUFFER", 10000);
    targetLTI = config().get_double("TARGET_LTI_FUNDS", 10000);
    targetSTI = config().get_double("TARGET_STI_FUNDS", 10000);
    STIAtomWage = config().get_double("ECAN_STARTING_ATOM_STI_WAGE", 10);
    LTIAtomWage = config().get_double("ECAN_STARTING_ATOM_LTI_WAGE", 10);
    maxAFSize = config().get_int("ECAN_MAX_AF_SIZE", 100);

    _remove_signal = &asp->atomRemovedSignal();
    _remove_connection = _remove_signal->connect(
            std::bind(&AttentionBank::remove_atom_from_bank, this,
                std::placeholders::_1));
}

AttentionBank::~AttentionBank()
{
    //_remove_signal->disconnect(_remove_connection);
}

void AttentionBank::remove_atom_from_bank(const AtomPtr& atom)
{
    AFMutex.lock();
    auto it = std::find_if(attentionalFocus.begin(), attentionalFocus.end(),
                [atom](std::pair<Handle, AttentionValuePtr> p)
                { return p.first == Handle(atom);});

    if (it != attentionalFocus.end())
        attentionalFocus.erase(it);
    AFMutex.unlock();

   _importanceIndex.removeAtom(Handle(atom));
}

void AttentionBank::set_sti(const Handle& h, AttentionValue::sti_t stiValue)
{
    AttentionValuePtr oldav = get_av(h);
    AttentionValuePtr newav = AttentionValue::createAV(
        stiValue, oldav->getLTI(), oldav->getVLTI());

    _importanceIndex.updateImportance(h, oldav, newav);
    AVChanged(h, oldav, newav);
}

void AttentionBank::set_lti(const Handle& h, AttentionValue::lti_t ltiValue)
{
    AttentionValuePtr old_av = get_av(h);
    AttentionValuePtr new_av = AttentionValue::createAV(
        old_av->getSTI(), ltiValue, old_av->getVLTI());

    AVChanged(h, old_av, new_av);
}

void AttentionBank::change_vlti(const Handle& h, int unit)
{
    AttentionValuePtr old_av = get_av(h);
    AttentionValuePtr new_av = AttentionValue::createAV(
        old_av->getSTI(),
        old_av->getLTI(),
        old_av->getVLTI() + unit);

    AVChanged(h, old_av, new_av);
}

void AttentionBank::change_av(const Handle& h, const AttentionValuePtr& new_av)
{
    AttentionValuePtr old_av = get_av(h);
    _importanceIndex.updateImportance(h, old_av, new_av);
    AVChanged(h, old_av, new_av);
}

void AttentionBank::AVChanged(const Handle& h,
                              const AttentionValuePtr& old_av,
                              const AttentionValuePtr& new_av)
{
    _mtx.lock();
    // First, update the atom's actual AV.
    set_av(h, new_av);

    AttentionValue::sti_t oldSti = old_av->getSTI();
    AttentionValue::sti_t newSti = new_av->getSTI();

    // Add the old attention values to the AttentionBank funds and
    // subtract the new attention values from the AttentionBank funds
    fundsSTI += (oldSti - newSti);
    fundsLTI += (old_av->getLTI() - new_av->getLTI());

    _importanceIndex.update();

    _mtx.unlock();

    logger().fine("AVChanged: fundsSTI = %d, old_av: %d, new_av: %d",
                   fundsSTI, oldSti, newSti);

    // Notify any interested parties that the AV changed.
    _AVChangedSignal.emit(h, old_av, new_av);

    // update AF
    updateAttentionalFocus(h, old_av, new_av);
}

void AttentionBank::stimulate(const Handle& h, double stimulus)
{
    // XXX This is not protected or made atomic in any way ...
    // If two different threads stimulate the same atom at the same
    // time, then the calculations will be bad. Does it matter?
    AttentionValuePtr oldav(get_av(h));
    AttentionValue::sti_t sti   = oldav->getSTI();
    AttentionValue::lti_t lti   = oldav->getLTI();
    AttentionValue::vlti_t vlti = oldav->getVLTI();

    AttentionValue::sti_t stiWage = calculateSTIWage() * stimulus;
    AttentionValue::lti_t ltiWage = calculateLTIWage() * stimulus;
    AttentionValuePtr newav = AttentionValue::createAV(
           sti + stiWage, lti + ltiWage, vlti);
    _importanceIndex.updateImportance(h, oldav, newav);
    AVChanged(h, oldav, newav);

#ifdef ECAN_EXPERIMENT
    if(stimulusRec.find(h) != stimulusRec.end()){
        stimulusRec[h] += stimulus;
    } else{
        stimulusRec[h] = stimulus;
    }
#endif
}

AttentionValue::sti_t AttentionBank::calculateSTIWage()
{
    AttentionValue::sti_t funds = getSTIFunds();
    AttentionValue::sti_t diff  = funds - targetSTI;
    AttentionValue::sti_t ndiff = diff / stiFundsBuffer;
    ndiff = std::min(ndiff, 1.0);
    ndiff = std::max(ndiff, -1.0);

    return STIAtomWage + (STIAtomWage * ndiff);
}

AttentionValue::lti_t AttentionBank::calculateLTIWage()
{
    AttentionValue::lti_t funds = getLTIFunds();
    AttentionValue::lti_t diff  = funds - targetLTI;
    AttentionValue::lti_t ndiff = diff / ltiFundsBuffer;
    ndiff = std::min(ndiff, 1.0);
    ndiff = std::max(ndiff, -1.0);

    return LTIAtomWage + (LTIAtomWage * ndiff);
}

double AttentionBank::getNormalisedSTI(AttentionValuePtr av,
                                   bool average, bool clip) const
{
    double val;
    // get normalizer (maxSTI - attention boundary)
    AttentionValue::sti_t s = av->getSTI();
    if (s > get_af_max_sti()) {
        int normaliser = (int) getMaxSTI(average) - get_af_max_sti();
        if (normaliser == 0) return 0.0;
        val = (s - get_af_max_sti()) / (double) normaliser;
    } else {
        int normaliser = -((int) getMinSTI(average) + get_af_max_sti());
        if (normaliser == 0) return 0.0;
        val = (s + get_af_max_sti()) / (double) normaliser;

    }

    if (clip) return std::max(-1.0, std::min(val, 1.0));
    return val;
}

double AttentionBank::getNormalisedSTI(AttentionValuePtr av) const
{
    AttentionValue::sti_t s = av->getSTI();
    auto normaliser =
            s > get_af_max_sti() ? getMaxSTI() : getMinSTI();

    return (s / normaliser);
}

double AttentionBank::getNormalisedZeroToOneSTI(AttentionValuePtr av,
                                    bool average, bool clip) const
{
    AttentionValue::sti_t s = av->getSTI();
    int normaliser = getMaxSTI(average) - getMinSTI(average);

    if (normaliser == 0) return 0.0;

    double val = (s - getMinSTI(average)) / (double) normaliser;
    if (clip) return std::max(0.0, std::min(val, 1.0));
    return val;
}

/** Unique singleton instance (for now) */
// This implementation is pretty hokey, and is a stop-gap until some
// sort of more elegant way of managing the attentionbank is found.
// One of the issues is that access via this function can be CPU-wasteful.
AttentionBank& opencog::attentionbank(AtomSpace* asp)
{
    static AttentionBank* _instance = nullptr;
    static AtomSpace* _as = nullptr;

    // Protect setting and getting against thread races.
    // This is probably not needed.
    static std::map<AtomSpace*, AttentionBank*> banksy;
    static std::mutex art;
    std::unique_lock<std::mutex> graffiti(art);

    if (_as != asp and _instance) {
        delete _instance;
        _instance = nullptr;
        _as = nullptr;
    }
    if (asp and nullptr == _instance) {
        _instance = new AttentionBank(asp);
        _as = asp;
    }
    return *_instance;
}

bool AttentionBank::atom_is_in_AF(const Handle& h)
{
    auto it = std::find_if(attentionalFocus.begin(), attentionalFocus.end(),
            [h](std::pair<Handle, AttentionValuePtr> p)
            {
               if (p.first == h) return true;
               return false;
            });
    return  (it != attentionalFocus.end());
}

/**
 *  Updates list of top K important atoms based on STI value.
 */
void AttentionBank::updateAttentionalFocus(const Handle& h,
                    const AttentionValuePtr& old_av,
                    const AttentionValuePtr& new_av)
{
    std::lock_guard<std::mutex> lock(AFMutex);
    AttentionValue::sti_t sti = new_av->getSTI();
    auto least = attentionalFocus.begin(); // Atom to be removed from the AF
    bool insertable = false;
    auto it = std::find_if(attentionalFocus.begin(), attentionalFocus.end(),
            [h](std::pair<Handle, AttentionValuePtr> p)
            { return p.first == h;});

    // Update the STI value if atoms was already in AF
    if (it != attentionalFocus.end())
    {
        attentionalFocus.erase(it);
        attentionalFocus.insert(std::make_pair(h, new_av));
        return;
    }

    // Simply insert the new Atom if AF is not full yet.
    else if (attentionalFocus.size() < maxAFSize)
    {
        insertable = true;
    }

    // Remove the least sti valued atom in the AF and replace
    // it with the new atom holding a higher STI value.
    else if (sti > (least->second)->getSTI())
    {
        Handle hrm = least->first;
        AttentionValuePtr hrm_new_av = get_av(hrm);
        // Value recorded when this atom entered into AF
        AttentionValuePtr hrm_old_av = least->second;

        attentionalFocus.erase(least);
        AFCHSigl& afch = RemoveAFSignal();
        afch.emit(hrm, hrm_old_av, hrm_new_av);
        insertable = true;
    }

    // Insert the new atom in to AF and emit the AddAFSignal.
    if (insertable)
    {
        attentionalFocus.insert(std::make_pair(h, new_av));
        AFCHSigl& afch = AddAFSignal();
        afch.emit(h, old_av, new_av);
    }
}

Handle AttentionBank::getRandomAtomNotInAF(void)
{
    UnorderedHandleSet atoms_not_in_af = _importanceIndex.getHandleSet(0);

    {
        std::lock_guard<std::mutex> lock(AFMutex);
        for (const auto& hsp : attentionalFocus) {
            atoms_not_in_af.erase(hsp.first);
        }
    }

    if (atoms_not_in_af.empty())
        return Handle::UNDEFINED;

    auto it = atoms_not_in_af.cbegin();
    std::advance(it, randGen().randint(atoms_not_in_af.size()));
    return *it;
}
<|endoftext|>


<commit_before>#include "LIBCD.H"

#include "EMULATOR_SETUP.H"
#include "EMULATOR.H"

#include <stdio.h>
#include <string.h>

int CD_Debug = 0;

FILE* openFile = NULL;

typedef struct commandQueue
{
	unsigned int mode;
	unsigned char* p;
	unsigned int processed;
	unsigned int count;
}commandQueue_s, *commandQueue_p;

#define COMMAND_QUEUE_SIZE 128

struct commandQueue comQueue[COMMAND_QUEUE_SIZE];
int comQueueIndex = 0;
int comQueueCount = 0;
int currentSector = 0;
int sectorSize = 2352;//TODO obtain properly from cue sheet
int CD_com = 0;

#pragma pack(push, 1)
struct TOC
{
	unsigned char tocEntryLength;
	unsigned char extEntryLength;
	unsigned int sectorPosition[2];
	unsigned int fileSize[2];
	unsigned char date[7];
	unsigned char flags;
	unsigned char fileUnitSize;
	unsigned char interleaveGapSize;
	unsigned short volSeqNum[2];
	unsigned char nameLength;
};

struct Sector
{
	unsigned char	sync[12];	/// Sync pattern (usually 00 FF FF FF FF FF FF FF FF FF FF 00)
	unsigned char	addr[3];	/// Sector address (see below for encoding details)
	unsigned char	mode;		/// Mode (usually 2 for Mode 2 Form 1/2 sectors)
	unsigned char	subHead[8];	/// Sub-header (00 00 08 00 00 00 08 00 for Form 1 data sectors)
	unsigned char	data[2048];	/// Data (form 1)
	unsigned char	edc[4];		/// Error-detection code (CRC32 of data area)
	unsigned char	ecc[276];	/// Error-correction code (uses Reed-Solomon ECC algorithm)
};
#pragma pack(pop)

CdlFILE* CdSearchFile(CdlFILE* fp, char* name)
{
	SDL_memset(fp, 0, sizeof(CdlFILE));

	if (name[0] == '\\')
	{
		name++;
	}

	if (openFile != NULL)
	{
		fseek(openFile, 22 * sectorSize, SEEK_SET);

		int tocLocalOffset = 0;
        struct Sector sector;
		fread(&sector, sizeof(struct Sector), 1, openFile);
        struct TOC* toc = (struct TOC*)&sector.data[0];
		while (toc->tocEntryLength != 0)
		{
			if (strcmp((char*)&sector.data[tocLocalOffset + sizeof(struct TOC)], name) == 0)
			{
				memcpy(&fp->name[0], (char*)&sector.data[tocLocalOffset + sizeof(struct TOC)], strlen(name));
				fp->size = toc->fileSize[0];
				fseek(openFile, toc->sectorPosition[0] * sectorSize, SEEK_SET);
				fread(&sector, sizeof(struct Sector), 1, openFile);
				fp->pos.minute = sector.addr[0];
				fp->pos.second = sector.addr[1];
				fp->pos.sector = sector.addr[2];

#if _DEBUG
				eprintf("Found %s\n", name);
#endif
				return fp;
			}
			tocLocalOffset += toc->tocEntryLength;
			toc = (struct TOC*)&sector.data[tocLocalOffset];
		}
	}

	return NULL;
}

CdlLOC* CdIntToPos(int i, CdlLOC* p)
{
	i += 150;
	p->sector = ENCODE_BCD(i % 75);
	int rem = i / 75;
	p->second = ENCODE_BCD(rem % 60);
	p->minute = ENCODE_BCD(rem / 60);
	return p;
}

int CdControl(u_char com, u_char * param, u_char * result)
{
	CdlFILE* cd = (CdlFILE*)param;

	CD_com = com;

	switch (com)
	{
	case CdlSetloc:
		fseek(openFile, CdPosToInt(&cd->pos)*sectorSize, SEEK_SET);
		break;
	default:
		eprinterr("Unhandled command 0x%02X!\n", com);
		break;
	}

	return 0;
}

int CdControlB(u_char com, u_char* param, u_char* result)
{
	CdlFILE* cd = (CdlFILE*)param;

	CD_com = com;

	switch (com)
	{
	case CdlSetloc:
		fseek(openFile, CdPosToInt(&cd->pos)*sectorSize, SEEK_SET);
		break;
	default:
		eprinterr("Unhandled command 0x%02X!\n", com);
		break;
	}

	return 0;
}

int CdControlF(u_char com, u_char * param)
{
	CdlFILE* cd = (CdlFILE*)param;

	CD_com = com;

	switch (com)
	{
	case CdlSetloc:
		fseek(openFile, CdPosToInt(&cd->pos)*sectorSize, SEEK_SET);
		break;
	case CdlSetfilter:
		//fseek(openFile, CdPosToInt(&cd->pos) * sectorSize, SEEK_SET);
		break;
	default:
		eprinterr("Unhandled command 0x%02X!\n", com);
		break;
	}

	return 0;
}

int CdPosToInt(CdlLOC* p)
{
	return (75 * (60 * DECODE_BCD(p->minute) + DECODE_BCD(p->second))) + DECODE_BCD(p->sector) - 150;
}

int CdRead(int sectors, u_long* buf, int mode)
{
	for (int i = 0; i < COMMAND_QUEUE_SIZE; i++)
	{
		if (comQueue[i].processed == 1)
		{
			comQueue[i].mode = CdlReadS;
			comQueue[i].p = (unsigned char*)buf;
			comQueue[i].processed = 0;
			comQueue[i].count = sectors;
			break;
		}
	}
	return 0;
}

int CdReadSync(int mode, u_char* result)
{
	for (int i = 0; i < COMMAND_QUEUE_SIZE; i++)
	{
		if (comQueue[i].processed == 0)
		{
            struct Sector sector;
			fread(&sector, sizeof(struct Sector), 1, openFile);

			memcpy(comQueue[i].p, &sector.data[0], 2048);
			comQueue[i].p += 2048;

			if (--comQueue[i].count == 0)
			{
				comQueue[i].processed = 1;
				break;
			}

			return 1;
		}
	}
	return 0;
}

int CdSetDebug(int level)
{
	int lastLevel = CD_Debug;
	CD_Debug = level;
	return lastLevel;
}

int CdSync(int mode, u_char * result)
{
	UNIMPLEMENTED();
	return 0;
}

int CdInit(void)
{
	SDL_memset(&comQueue, 0, sizeof(comQueue));
	currentSector = 0;
	openFile = fopen(DISC_IMAGE_FILENAME, "rb");

	if (openFile == NULL)
	{
		eprinterr("Failed to open disc image file! %s\n", DISC_IMAGE_FILENAME);
		return 0;
	}

	for (int i = 0; i < COMMAND_QUEUE_SIZE; i++)
	{
		comQueue[i].processed = 1;
	}

	return 1;
}

int CdLastCom(void)
{
	return CD_com;
}
<commit_msg>[Emu]: Implement CdSync.<commit_after>#include "LIBCD.H"

#include "EMULATOR_SETUP.H"
#include "EMULATOR.H"

#include <assert.h>
#include <stdio.h>
#include <string.h>

int CD_Debug = 0;

FILE* openFile = NULL;

typedef struct commandQueue
{
	unsigned int mode;
	unsigned char* p;
	unsigned int processed;
	unsigned int count;
}commandQueue_s, *commandQueue_p;

#define COMMAND_QUEUE_SIZE 128

struct commandQueue comQueue[COMMAND_QUEUE_SIZE];
int comQueueIndex = 0;
int comQueueCount = 0;
int currentSector = 0;
int sectorSize = 2352;//TODO obtain properly from cue sheet
int CD_com = 0;

#pragma pack(push, 1)
struct TOC
{
	unsigned char tocEntryLength;
	unsigned char extEntryLength;
	unsigned int sectorPosition[2];
	unsigned int fileSize[2];
	unsigned char date[7];
	unsigned char flags;
	unsigned char fileUnitSize;
	unsigned char interleaveGapSize;
	unsigned short volSeqNum[2];
	unsigned char nameLength;
};

struct Sector
{
	unsigned char	sync[12];	/// Sync pattern (usually 00 FF FF FF FF FF FF FF FF FF FF 00)
	unsigned char	addr[3];	/// Sector address (see below for encoding details)
	unsigned char	mode;		/// Mode (usually 2 for Mode 2 Form 1/2 sectors)
	unsigned char	subHead[8];	/// Sub-header (00 00 08 00 00 00 08 00 for Form 1 data sectors)
	unsigned char	data[2048];	/// Data (form 1)
	unsigned char	edc[4];		/// Error-detection code (CRC32 of data area)
	unsigned char	ecc[276];	/// Error-correction code (uses Reed-Solomon ECC algorithm)
};
#pragma pack(pop)

CdlFILE* CdSearchFile(CdlFILE* fp, char* name)
{
	SDL_memset(fp, 0, sizeof(CdlFILE));

	if (name[0] == '\\')
	{
		name++;
	}

	if (openFile != NULL)
	{
		fseek(openFile, 22 * sectorSize, SEEK_SET);

		int tocLocalOffset = 0;
        struct Sector sector;
		fread(&sector, sizeof(struct Sector), 1, openFile);
        struct TOC* toc = (struct TOC*)&sector.data[0];
		while (toc->tocEntryLength != 0)
		{
			if (strcmp((char*)&sector.data[tocLocalOffset + sizeof(struct TOC)], name) == 0)
			{
				memcpy(&fp->name[0], (char*)&sector.data[tocLocalOffset + sizeof(struct TOC)], strlen(name));
				fp->size = toc->fileSize[0];
				fseek(openFile, toc->sectorPosition[0] * sectorSize, SEEK_SET);
				fread(&sector, sizeof(struct Sector), 1, openFile);
				fp->pos.minute = sector.addr[0];
				fp->pos.second = sector.addr[1];
				fp->pos.sector = sector.addr[2];

#if _DEBUG
				eprintf("Found %s\n", name);
#endif
				return fp;
			}
			tocLocalOffset += toc->tocEntryLength;
			toc = (struct TOC*)&sector.data[tocLocalOffset];
		}
	}

	return NULL;
}

CdlLOC* CdIntToPos(int i, CdlLOC* p)
{
	i += 150;
	p->sector = ENCODE_BCD(i % 75);
	int rem = i / 75;
	p->second = ENCODE_BCD(rem % 60);
	p->minute = ENCODE_BCD(rem / 60);
	return p;
}

int CdControl(u_char com, u_char * param, u_char * result)
{
	CdlFILE* cd = (CdlFILE*)param;

	CD_com = com;

	switch (com)
	{
	case CdlSetloc:
		fseek(openFile, CdPosToInt(&cd->pos)*sectorSize, SEEK_SET);
		break;
	default:
		eprinterr("Unhandled command 0x%02X!\n", com);
		break;
	}

	return 0;
}

int CdControlB(u_char com, u_char* param, u_char* result)
{
	CdlFILE* cd = (CdlFILE*)param;

	CD_com = com;

	switch (com)
	{
	case CdlSetloc:
		fseek(openFile, CdPosToInt(&cd->pos)*sectorSize, SEEK_SET);
		break;
	default:
		eprinterr("Unhandled command 0x%02X!\n", com);
		break;
	}

	return 0;
}

int CdControlF(u_char com, u_char * param)
{
	CdlFILE* cd = (CdlFILE*)param;

	CD_com = com;

	switch (com)
	{
	case CdlSetloc:
		fseek(openFile, CdPosToInt(&cd->pos)*sectorSize, SEEK_SET);
		break;
	case CdlSetfilter:
		//fseek(openFile, CdPosToInt(&cd->pos) * sectorSize, SEEK_SET);
		break;
	default:
		eprinterr("Unhandled command 0x%02X!\n", com);
		break;
	}

	return 0;
}

int CdPosToInt(CdlLOC* p)
{
	return (75 * (60 * DECODE_BCD(p->minute) + DECODE_BCD(p->second))) + DECODE_BCD(p->sector) - 150;
}

int CdRead(int sectors, u_long* buf, int mode)
{
	for (int i = 0; i < COMMAND_QUEUE_SIZE; i++)
	{
		if (comQueue[i].processed == 1)
		{
			comQueue[i].mode = CdlReadS;
			comQueue[i].p = (unsigned char*)buf;
			comQueue[i].processed = 0;
			comQueue[i].count = sectors;
			break;
		}
	}
	return 0;
}

int CdReadSync(int mode, u_char* result)
{
	for (int i = 0; i < COMMAND_QUEUE_SIZE; i++)
	{
		if (comQueue[i].processed == 0)
		{
            struct Sector sector;
			fread(&sector, sizeof(struct Sector), 1, openFile);

			memcpy(comQueue[i].p, &sector.data[0], 2048);
			comQueue[i].p += 2048;

			if (--comQueue[i].count == 0)
			{
				comQueue[i].processed = 1;
				break;
			}

			return 1;
		}
	}
	return 0;
}

int CdSetDebug(int level)
{
	int lastLevel = CD_Debug;
	CD_Debug = level;
	return lastLevel;
}

int CdSync(int mode, u_char * result)
{
	switch (mode)
	{
	case 0:
		UNIMPLEMENTED();
		assert(FALSE);
		break;
	case 1:
		return CdlComplete;
		break;
	}

	return 0;
}

int CdInit(void)
{
	SDL_memset(&comQueue, 0, sizeof(comQueue));
	currentSector = 0;
	openFile = fopen(DISC_IMAGE_FILENAME, "rb");

	if (openFile == NULL)
	{
		eprinterr("Failed to open disc image file! %s\n", DISC_IMAGE_FILENAME);
		return 0;
	}

	for (int i = 0; i < COMMAND_QUEUE_SIZE; i++)
	{
		comQueue[i].processed = 1;
	}

	return 1;
}

int CdLastCom(void)
{
	return CD_com;
}
<|endoftext|>


<commit_before>//This is the macro to include the FMD analysis in the train.
//It depends on two libraries: libFMDanalysis.so in AliRoot and
//libPhysics.so in ROOT. It has been tested to work with the
//example scripts in the ANALYSIS webpages.
// Author: Hans Hjersing Dalsgaard, hans.dalsgaard@cern,ch

AliFMDAnalysisTaskSE* AddTaskFMD() {

  AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
  if (!mgr) {
    Error("AddTaskESDFilter", "No analysis manager to connect to.");
    return NULL;
  }

  AliFMDAnalysisTaskSE *taskfmd = new AliFMDAnalysisTaskSE("TaskFMD");
  mgr->AddTask(taskfmd);

  AliFMDAnaParameters* pars = AliFMDAnaParameters::Instance();
  pars->Init();
  pars->SetProcessPrimary(kFALSE);
  pars->SetProcessHits(kFALSE);
  pars->SetEnergy(AliFMDAnaParameters::k900);

  TString outputfile = AliAnalysisManager::GetCommonFileName();
  outputfile += Form(":%s",pars->GetDndetaAnalysisName());

  AliAnalysisDataContainer *cout_fmd = mgr->CreateContainer("BackgroundCorrected", TList::Class(), AliAnalysisManager::kOutputContainer,outputfile);
  mgr->ConnectInput(taskfmd, 0, mgr->GetCommonInputContainer());
  mgr->ConnectOutput(taskfmd, 1, cout_fmd);

  return taskfmd;
}
<commit_msg>Update to accept all collision candidates.<commit_after>//This is the macro to include the FMD analysis in the train.
//It depends on two libraries: libFMDanalysis.so in AliRoot and
//libPhysics.so in ROOT. It has been tested to work with the
//example scripts in the ANALYSIS webpages.
// Author: Hans Hjersing Dalsgaard, hans.dalsgaard@cern,ch

AliFMDAnalysisTaskSE* AddTaskFMD() {

  AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
  if (!mgr) {
    Error("AddTaskESDFilter", "No analysis manager to connect to.");
    return NULL;
  }

  AliFMDAnalysisTaskSE *taskfmd = new AliFMDAnalysisTaskSE("TaskFMD");
  mgr->AddTask(taskfmd);

  AliFMDAnaParameters* pars = AliFMDAnaParameters::Instance();
  pars->Init();
  pars->SetProcessPrimary(kFALSE);
  pars->SetProcessHits(kFALSE);
  pars->SetEnergy(AliFMDAnaParameters::k900);
  pars->SetCentralTriggerSelection(kTRUE);

  TString outputfile = AliAnalysisManager::GetCommonFileName();
  outputfile += Form(":%s",pars->GetDndetaAnalysisName());

  AliAnalysisDataContainer *cout_fmd = mgr->CreateContainer("BackgroundCorrected", TList::Class(), AliAnalysisManager::kOutputContainer,outputfile);
  mgr->ConnectInput(taskfmd, 0, mgr->GetCommonInputContainer());
  mgr->ConnectOutput(taskfmd, 1, cout_fmd);

  return taskfmd;
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: implcustomsprite.cxx,v $
 * $Revision: 1.9 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_cppcanvas.hxx"
#include <basegfx/polygon/b2dpolypolygon.hxx>

#include <implcustomsprite.hxx>
#include <implcanvas.hxx>

using namespace ::com::sun::star;

namespace cppcanvas
{
    namespace internal
    {
        ImplCustomSprite::ImplCustomSprite( const uno::Reference< rendering::XSpriteCanvas >&       rParentCanvas,
                                            const uno::Reference< rendering::XCustomSprite >&       rSprite,
                                            const ImplSpriteCanvas::TransformationArbiterSharedPtr& rTransformArbiter ) :
            ImplSprite( rParentCanvas,
                        uno::Reference< rendering::XSprite >(rSprite,
                                                             uno::UNO_QUERY),
                        rTransformArbiter ),
            mpLastCanvas(),
            mxCustomSprite( rSprite )
        {
            OSL_ENSURE( rParentCanvas.is(), "ImplCustomSprite::ImplCustomSprite(): Invalid canvas" );
            OSL_ENSURE( mxCustomSprite.is(), "ImplCustomSprite::ImplCustomSprite(): Invalid sprite" );
        }

        ImplCustomSprite::~ImplCustomSprite()
        {
        }

        CanvasSharedPtr ImplCustomSprite::getContentCanvas() const
        {
            OSL_ENSURE( mxCustomSprite.is(), "ImplCustomSprite::getContentCanvas(): Invalid sprite" );

            if( !mxCustomSprite.is() )
                return CanvasSharedPtr();

            uno::Reference< rendering::XCanvas > xCanvas( mxCustomSprite->getContentCanvas() );

            if( !xCanvas.is() )
                return CanvasSharedPtr();

            // cache content canvas C++ wrapper
            if( mpLastCanvas.get() == NULL ||
                mpLastCanvas->getUNOCanvas() != xCanvas )
            {
                mpLastCanvas = CanvasSharedPtr( new ImplCanvas( xCanvas ) );
            }

            return mpLastCanvas;
        }
    }
}
<commit_msg>INTEGRATION: CWS canvas05 (1.8.38); FILE MERGED 2008/04/21 07:50:39 thb 1.8.38.2: RESYNC: (1.8-1.9); FILE MERGED 2007/10/01 13:41:45 thb 1.8.38.1: #i79258# Merge from CWS picom<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: implcustomsprite.cxx,v $
 * $Revision: 1.10 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_cppcanvas.hxx"

#include <basegfx/polygon/b2dpolypolygon.hxx>

#include "implcustomsprite.hxx"
#include "implcanvas.hxx"

using namespace ::com::sun::star;

namespace cppcanvas
{
    namespace internal
    {
        ImplCustomSprite::ImplCustomSprite( const uno::Reference< rendering::XSpriteCanvas >&       rParentCanvas,
                                            const uno::Reference< rendering::XCustomSprite >&       rSprite,
                                            const ImplSpriteCanvas::TransformationArbiterSharedPtr& rTransformArbiter ) :
            ImplSprite( rParentCanvas,
                        uno::Reference< rendering::XSprite >(rSprite,
                                                             uno::UNO_QUERY),
                        rTransformArbiter ),
            mpLastCanvas(),
            mxCustomSprite( rSprite )
        {
            OSL_ENSURE( rParentCanvas.is(), "ImplCustomSprite::ImplCustomSprite(): Invalid canvas" );
            OSL_ENSURE( mxCustomSprite.is(), "ImplCustomSprite::ImplCustomSprite(): Invalid sprite" );
        }

        ImplCustomSprite::~ImplCustomSprite()
        {
        }

        CanvasSharedPtr ImplCustomSprite::getContentCanvas() const
        {
            OSL_ENSURE( mxCustomSprite.is(), "ImplCustomSprite::getContentCanvas(): Invalid sprite" );

            if( !mxCustomSprite.is() )
                return CanvasSharedPtr();

            uno::Reference< rendering::XCanvas > xCanvas( mxCustomSprite->getContentCanvas() );

            if( !xCanvas.is() )
                return CanvasSharedPtr();

            // cache content canvas C++ wrapper
            if( mpLastCanvas.get() == NULL ||
                mpLastCanvas->getUNOCanvas() != xCanvas )
            {
                mpLastCanvas = CanvasSharedPtr( new ImplCanvas( xCanvas ) );
            }

            return mpLastCanvas;
        }
    }
}
<|endoftext|>