103 строки
3.3 KiB
C++
103 строки
3.3 KiB
C++
//
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
//
|
|
#include "pal/PAL.hpp"
|
|
#include "InformationProviderImpl.hpp"
|
|
#include <vector>
|
|
|
|
#ifdef _WIN32
|
|
// Add SEH handling to callbacks to avoid crashes on Windows 10 Phone as a temporary
|
|
// solution to cover unknown Windows 10 Phone scenarios, where app goes to background,
|
|
// being shutdown or unloaded. And callback (power or network) fires at this time,
|
|
// resulting in invalid pointer read from OnChanged. Worst case is instead of a crash
|
|
// we would not refresh the actual network
|
|
#include <exception>
|
|
#include <excpt.h>
|
|
#endif
|
|
|
|
namespace PAL_NS_BEGIN {
|
|
|
|
InformatonProviderImpl::InformatonProviderImpl() :m_registeredCount(0)
|
|
{
|
|
}
|
|
|
|
InformatonProviderImpl::~InformatonProviderImpl()
|
|
{
|
|
}
|
|
|
|
// IInformationProvider API
|
|
int InformatonProviderImpl::RegisterInformationChangedCallback(IPropertyChangedCallback* pCallback)
|
|
{
|
|
std::lock_guard<std::mutex> lock(m_lock);
|
|
|
|
// Use (index + 1) as the token.
|
|
m_callbacks.push_back(pCallback);
|
|
int token = (int)m_callbacks.size();
|
|
m_registeredCount++;
|
|
return token;
|
|
}
|
|
|
|
void InformatonProviderImpl::UnRegisterInformationChangedCallback(int callbackToken)
|
|
{
|
|
// The callbackToken cannot be less than 1.
|
|
if (callbackToken < 1)
|
|
{
|
|
return;
|
|
}
|
|
|
|
size_t index = static_cast<size_t>(callbackToken - 1);
|
|
|
|
std::lock_guard<std::mutex> lock(m_lock);
|
|
size_t count = m_callbacks.size();
|
|
if (index < count)
|
|
{
|
|
// Don't ever delete the item from the vector.
|
|
// Just set it to NULL.
|
|
m_callbacks[index] = NULL;
|
|
--m_registeredCount;
|
|
}
|
|
}
|
|
|
|
void InformatonProviderImpl::OnChanged(std::string const& propertyName, std::string const& propertyValue)
|
|
{
|
|
try {
|
|
// OnChange shouldn't block new callbacks to be registered.
|
|
// However, those newly registered callbacks are not called by
|
|
// this current notification.
|
|
//
|
|
// OnChange shouldn't block unregistration of callbacks. However,
|
|
// those callbacks will be called by this current notification?
|
|
// TODO: This means that after calling UnRegisterInformationChangedCallback
|
|
// the client code is not sure if the IPropertyChangedCallback can
|
|
// be deleted. The current design is that IPropertyChangedCallback is
|
|
// not refcount'ed. Should we refcount it?
|
|
|
|
std::vector<IPropertyChangedCallback*> local_callbacks;
|
|
{
|
|
std::lock_guard<std::mutex> lock(m_lock);
|
|
if (m_registeredCount > 0)
|
|
{
|
|
local_callbacks.insert(local_callbacks.end(), m_callbacks.begin(), m_callbacks.end());
|
|
}
|
|
}
|
|
|
|
size_t count = local_callbacks.size();
|
|
for (size_t index = 0; index < count; ++index)
|
|
{
|
|
IPropertyChangedCallback* cur_callback = local_callbacks[index];
|
|
if (cur_callback != NULL)
|
|
{
|
|
cur_callback->OnChanged(propertyName, propertyValue);
|
|
}
|
|
}
|
|
}
|
|
catch (...)
|
|
{
|
|
|
|
}
|
|
}
|
|
|
|
} PAL_NS_END
|
|
|