Commit 932638ed authored by Soemin Tjong's avatar Soemin Tjong Committed by Dan Mihai

Add completion callback to IPCACloseHandle().

This addresses the scenario where the app needs to be certain when all
callbacks related to the handle it is closing are completed.

Change-Id: I75b211d477405be27c6c804bc89e529088aa1a90
Signed-off-by: default avatarSoemin Tjong <stjong@microsoft.com>
Reviewed-on: https://gerrit.iotivity.org/gerrit/18217Tested-by: default avatarjenkins-iotivity <jenkins@iotivity.org>
Reviewed-by: default avatarDan Mihai <Daniel.Mihai@microsoft.com>
parent 1dcb85b9
......@@ -365,6 +365,15 @@ typedef void (IPCA_CALL *IPCACreateResourceComplete)(
*/
typedef void (IPCA_CALL *IPCADeleteResourceComplete)(IPCAStatus result, void* context);
/**
* Callback from IPCA when a handle is completely closed.
*
* @param[in] context Caller's context set in IPCACloseHandle().
*
*/
typedef void (IPCA_CALL *IPCACloseHandleComplete)(void* context);
/**
* Discovery status in IPCADiscoverDeviceCallback.
*/
......@@ -748,14 +757,22 @@ IPCAStatus IPCA_CALL IPCAObserveResource(
* For handle returned by IPCAObserveResource(), IPCACloseHandle unsubscribes server's resource
* change notification.
*
* @param[in] handle Handle returned in the following methods:
* IPCAGetProperties()
* IPCASetProperties()
* IPCAObserveResource()
* IPCADiscoverDevices()
* @param[in] handle Handle returned in the following methods:
* IPCAGetProperties(), IPCASetProperties(), IPCAObserveResource()
* IPCADiscoverDevices(), IPCACreateResource() and
* IPCARequestAccess().
* @param[in] closeHandleComplete Optional callback when handle is completely closed.
* Upon receiving this callback, an application can safely perform
* any needed cleanup for resources related to the handle closed.
* @param[in] context Application's context that is passed back as argument in the
* closeHandleComplete callback.
*
* @return IPCA_OK if successful.
* IPCA_FAIL if handle is already closed, closeHandleComplete will not be called.
*/
void IPCA_CALL IPCACloseHandle(IPCAHandle handle);
IPCAStatus IPCA_CALL IPCACloseHandle(IPCAHandle handle,
IPCACloseHandleComplete closeHandleComplete,
void* context);
/**
* Perform factory reset.
......
......@@ -74,7 +74,7 @@ IPCAStatus RequestObserve()
{
if (g_observeHandle != nullptr)
{
IPCACloseHandle(g_observeHandle);
IPCACloseHandle(g_observeHandle, nullptr, 0);
g_observeHandle = nullptr;
}
......@@ -539,7 +539,7 @@ bool DiscoverElevator(bool freeRun, size_t timeOutMs)
g_deviceDiscoveredCV.wait_for(lock, std::chrono::milliseconds{ timeOutMs });
// Stop discovery.
IPCACloseHandle(g_discoverDeviceHandle);
IPCACloseHandle(g_discoverDeviceHandle, nullptr, 0);
}
return g_targetElevatorDiscovered;
......
......@@ -650,6 +650,6 @@ int main()
g_OCFDeviceList.clear();
IPCACloseHandle(discoverDeviceHandle);
IPCACloseHandle(discoverDeviceHandle, nullptr, 0);
IPCAClose(g_ipcaAppHandle);
}
......@@ -31,7 +31,9 @@ App::App(const IPCAAppInfo* ipcaAppInfo, IPCAVersion ipcaVersion) :
m_isStopped(false),
m_passwordInputCallbackHandle(nullptr),
m_passwordDisplayCallbackHandle(nullptr),
m_ipcaVersion(ipcaVersion)
m_ipcaVersion(ipcaVersion),
m_passwordInputCallbackInfo(nullptr),
m_passwordDisplayCallbackInfo(nullptr)
{
m_ipcaAppInfo.appId = ipcaAppInfo->appId;
m_ipcaAppInfo.appName = ipcaAppInfo->appName;
......@@ -106,6 +108,19 @@ void App::Stop()
ocfFramework.Stop(m_passwordInputCallbackHandle, m_passwordDisplayCallbackHandle);
m_passwordInputCallbackHandle = nullptr;
m_passwordDisplayCallbackHandle = nullptr;
// Deregister the callback info.
if (m_passwordInputCallbackInfo != nullptr)
{
DeleteAndUnregisterCallbackInfo(m_passwordInputCallbackInfo->mapKey);
m_passwordInputCallbackInfo = nullptr;
}
if (m_passwordDisplayCallbackInfo != nullptr)
{
DeleteAndUnregisterCallbackInfo(m_passwordDisplayCallbackInfo->mapKey);
m_passwordDisplayCallbackInfo = nullptr;
}
}
void App::AppWorkerThread(App* app)
......@@ -366,6 +381,10 @@ IPCAStatus App::SetPasswordCallbacks(
ocfFramework.SetInputPasswordCallback(inputCallbackInfo, &m_passwordInputCallbackHandle);
ocfFramework.SetDisplayPasswordCallback(displayCallbackInfo, &m_passwordDisplayCallbackHandle);
// The CallbackInfo to be deregistered in Stop().
m_passwordInputCallbackInfo = inputCallbackInfo;
m_passwordDisplayCallbackInfo = displayCallbackInfo;
return IPCA_OK;
}
......@@ -661,7 +680,9 @@ IPCAStatus App::DeleteResource(
return status;
}
void App::CloseIPCAHandle(IPCAHandle handle)
IPCAStatus App::CloseIPCAHandle(IPCAHandle handle,
IPCACloseHandleComplete closeHandleComplete,
const void* context)
{
size_t mapKey = reinterpret_cast<size_t>(handle);
......@@ -682,7 +703,7 @@ void App::CloseIPCAHandle(IPCAHandle handle)
}
}
DeleteAndUnregisterCallbackInfo(mapKey);
return DeleteAndUnregisterCallbackInfo(mapKey, closeHandleComplete, context);
}
IPCAStatus App::CreateAndRegisterNewCallbackInfo(
......@@ -734,7 +755,10 @@ IPCAStatus App::CreateAndRegisterNewCallbackInfo(
return status;
}
void App::DeleteAndUnregisterCallbackInfo(size_t mapKey)
IPCAStatus App::DeleteAndUnregisterCallbackInfo(
size_t mapKey,
IPCACloseHandleComplete closeHandleComplete,
const void* context)
{
m_callback->RemoveCallbackInfo(mapKey);
return m_callback->RemoveCallbackInfo(mapKey, closeHandleComplete, context);
}
......@@ -57,7 +57,7 @@ void Callback::Stop()
m_stopCalled = true;
// Wait some amount of time for all callbacks in progress to complete.
const int WaitTimeSeconds = 3;
const int WaitTimeSeconds = 30;
int i = 0;
while (i < WaitTimeSeconds)
{
......@@ -93,10 +93,25 @@ void Callback::Stop()
if (allStopped == false)
{
OIC_LOG_V(WARNING, TAG, "Stop() time out waiting for pending callbacks to complete.");
std::cout << "Stop() timed out: m_callbackInfoList count = " << m_callbackInfoList.size();
std::cout << " m_expiredCallbacksInprogress = " << m_expiredCallbacksInprogress;
OIC_LOG_V(
ERROR,
TAG,
"Stop() timed out: m_callbackInfoList count = [%d] m_expiredCallbacksInprogress = [%d]",
m_callbackInfoList.size(),
m_expiredCallbacksInprogress);
throw timeoutException;
}
}
void Callback::CommonInitializeCallbackInfo(CallbackInfo::Ptr cbInfo)
{
cbInfo->app = m_app;
cbInfo->callbackInProgressCount = 0;
cbInfo->markedToBeRemoved = false;
cbInfo->requestSentTimestamp = 0;
cbInfo->closeHandleCompleteCallback = nullptr;
}
CallbackInfo::Ptr Callback::CreatePasswordCallbackInfo(
......@@ -119,11 +134,9 @@ CallbackInfo::Ptr Callback::CreatePasswordCallbackInfo(
return nullptr;
}
cbInfo->app = m_app;
CommonInitializeCallbackInfo(cbInfo);
cbInfo->type = cbType;
cbInfo->callbackContext = context;
cbInfo->callbackInProgressCount = 0;
cbInfo->markedToBeRemoved = false;
switch (cbType)
{
......@@ -152,12 +165,10 @@ CallbackInfo::Ptr Callback::CreateRequestAccessCompletionCallbackInfo(
return nullptr;
}
cbInfo->app = m_app;
CommonInitializeCallbackInfo(cbInfo);
cbInfo->device = device;
cbInfo->type = Callbacktype_RequestAccessCompletionCallback;
cbInfo->callbackContext = context;
cbInfo->callbackInProgressCount = 0;
cbInfo->markedToBeRemoved = false;
cbInfo->requestAccessCompletionCallback = completionCallback;
if (resourcePath != nullptr)
......@@ -187,13 +198,10 @@ CallbackInfo::Ptr Callback::CreateCallbackInfo(
return nullptr;
}
cbInfo->app = m_app;
CommonInitializeCallbackInfo(cbInfo);
cbInfo->device = device;
cbInfo->type = cbType;
cbInfo->callbackContext = context;
cbInfo->callbackInProgressCount = 0;
cbInfo->markedToBeRemoved = false;
cbInfo->requestSentTimestamp = 0;
cbInfo->resourcePath = std::string(resourcePath ? resourcePath : "");
cbInfo->resourceInterface = std::string(resourceInterface ? resourceInterface : "");
......@@ -356,6 +364,17 @@ bool Callback::SetCallbackInProgress(size_t mapKey)
}
}
void Callback::CallCloseHandleComplete(IPCACloseHandleComplete closeHandleComplete,
const void* context)
{
if (closeHandleComplete != nullptr)
{
std::thread callbackThread = std::thread(closeHandleComplete,
const_cast<void*>(context));
callbackThread.detach();
}
}
bool Callback::ClearCallbackInProgress(size_t mapKey)
{
std::lock_guard<std::mutex> lock(m_callbackMutex);
......@@ -364,30 +383,72 @@ bool Callback::ClearCallbackInProgress(size_t mapKey)
// must complete.
if (m_callbackInfoList.find(mapKey) != m_callbackInfoList.end())
{
m_callbackInfoList[mapKey]->callbackInProgressCount--;
CallbackInfo::Ptr cbInfo = m_callbackInfoList[mapKey];
// There should be one ClearCallbackInProgress() for each SetCallbackInProgress().
assert(cbInfo->callbackInProgressCount > 0);
// One less in progress callback.
cbInfo->callbackInProgressCount--;
// closeHandleCompleteCallback is set if IPCACloseHandle() is called when callback
// for the handle that the app is closing is already in progress.
// Call it if this is the last callback that has completed.
if ((cbInfo->closeHandleCompleteCallback != nullptr) &&
(cbInfo->callbackInProgressCount == 0))
{
CallCloseHandleComplete(
cbInfo->closeHandleCompleteCallback,
cbInfo->closeHandleCompletecontext);
cbInfo->closeHandleCompleteCallback = nullptr;
}
return true;
}
OIC_LOG_V(INFO, TAG, "ClearCallbackInProgress() mapKey [%d] is not found", mapKey);
OIC_LOG_V(WARNING, TAG, "ClearCallbackInProgress() mapKey [%d] is not found", mapKey);
assert(false); // In progress callback is not expected to be removed from the list.
return false;
}
void Callback::RemoveCallbackInfo(size_t mapKey)
IPCAStatus Callback::RemoveCallbackInfo(size_t mapKey,
IPCACloseHandleComplete closeHandleComplete,
const void* context)
{
CallbackInfo::Ptr callbackInfo = nullptr;
std::lock_guard<std::mutex> lock(m_callbackMutex);
if (m_callbackInfoList.find(mapKey) != m_callbackInfoList.end())
{
if (m_callbackInfoList[mapKey]->callbackInProgressCount == 0)
{
m_callbackInfoList.erase(mapKey);
}
else
{
m_callbackInfoList[mapKey]->markedToBeRemoved = true;
}
callbackInfo = m_callbackInfoList[mapKey];
}
if ((callbackInfo == nullptr) || (callbackInfo->markedToBeRemoved == true))
{
// Handle is already closed (no longer in the list) or closing (marked to be removed).
return IPCA_FAIL;
}
// callbackInProgress count is 0 when there's no in progress callback to app's code.
if (callbackInfo->callbackInProgressCount == 0)
{
// Remove the reference to the CallbackInfo object and call closeHandleComplete
// to app if requested.
m_callbackInfoList.erase(mapKey);
CallCloseHandleComplete(closeHandleComplete, context);
}
else
{
// There's at least one in progress callback to app's code.
callbackInfo->markedToBeRemoved = true;
// Call to closeHandleComplete will happen when all the callbacks are completed.
callbackInfo->closeHandleCompleteCallback = closeHandleComplete;
callbackInfo->closeHandleCompletecontext = context;
}
return IPCA_OK;
}
void Callback::CompleteAndRemoveExpiredCallbackInfo(std::vector<CallbackInfo::Ptr>& cbInfoList)
......@@ -408,8 +469,9 @@ void Callback::CompleteAndRemoveExpiredCallbackInfo(std::vector<CallbackInfo::Pt
for(auto const& entry : m_callbackInfoList)
{
// Opportunistic removal of callback that couldn't be removed during
// RemoveCallbackInfo().
if (entry.second->markedToBeRemoved == true)
// RemoveCallbackInfo() and if by now it has completed the callback.
if ((entry.second->markedToBeRemoved == true) &&
(entry.second->callbackInProgressCount == 0))
{
m_expiredCallbacksInprogress++;
cbInfoList.push_back(entry.second);
......@@ -751,6 +813,7 @@ void Callback::DeleteResourceCallback(IPCAStatus status, CallbackInfo::Ptr cbInf
const_cast<void*>(cbInfo->callbackContext));
ClearCallbackInProgress(cbInfo->mapKey);
RemoveCallbackInfo(cbInfo->mapKey);
}
void Callback::PasswordInputCallback(std::string deviceId,
......@@ -846,4 +909,5 @@ void Callback::RequestAccessCompletionCallback(IPCAStatus status, CallbackInfo::
}
ClearCallbackInProgress(cbInfo->mapKey);
RemoveCallbackInfo(cbInfo->mapKey);
}
......@@ -127,10 +127,12 @@ class App
void* context,
IPCAHandle* handle);
// Close handle returned in DiscoverDevices(), GetProperties(), SetProperties(), or
// ObserveResource().
void CloseIPCAHandle(IPCAHandle handle);
// Close handle returned in DiscoverDevices(), GetProperties(), SetProperties(),
// ObserveResource(), CreateResource() and RequestAccess().
IPCAStatus CloseIPCAHandle(
IPCAHandle handle,
IPCACloseHandleComplete closeHandleComplete,
const void* context);
private:
std::mutex m_appMutex;
......@@ -166,7 +168,10 @@ class App
const char* resourceType);
// Delete the CallbackInfo and unregister from Callback object list.
void DeleteAndUnregisterCallbackInfo(size_t mapKey);
IPCAStatus DeleteAndUnregisterCallbackInfo(
size_t mapKey,
IPCACloseHandleComplete closeHandleComplete = nullptr,
const void* context = nullptr);
// Thread performing periodic discovery.
static void AppWorkerThread(App* app);
......@@ -177,6 +182,8 @@ class App
// Password callback registration
InputPinCallbackHandle m_passwordInputCallbackHandle;
CallbackInfo::Ptr m_passwordInputCallbackInfo;
DisplayPinCallbackHandle m_passwordDisplayCallbackHandle;
CallbackInfo::Ptr m_passwordDisplayCallbackInfo;
};
#endif // APP_H_
......@@ -42,40 +42,47 @@ typedef std::shared_ptr<Device> DevicePtr;
// Structure contains information to make callbacks to app.
struct CallbackInfo
{
public:
CallbackInfo() { /* std::cout << "+ CallbackInfo " << this << std::endl; */ }
~CallbackInfo() { /* std::cout << "- CallbackInfo " << this << " mapKey: ";
std::cout << mapKey << std::endl; */ }
typedef std::shared_ptr<CallbackInfo> Ptr;
size_t mapKey; // key to m_callbackInfoList map. Initialized in AddCallbackInfo().
App* app; // the app that creates this callback.
DevicePtr device; // the device expected to respond to the callback.
CallbackType type;
union
{
IPCADiscoverDeviceCallback discoveryCallback;
IPCAResourceChangeCallback resourceChangeCallback;
IPCAGetPropertiesComplete getCallback;
IPCASetPropertiesComplete setCallback;
IPCACreateResourceComplete createResourceCallback;
IPCADeleteResourceComplete deleteResourceCallback;
IPCAProvidePasswordCallback passwordInputCallback;
IPCADisplayPasswordCallback passwordDisplayCallback;
IPCARequestAccessCompletionCallback requestAccessCompletionCallback;
};
const void* callbackContext; // app's callback context.
std::vector<std::string> resourceTypeList; // Parameter for Discovery.
std::string resourcePath; // Parameters for for Get, Set, Observe request.
std::string resourceInterface;
std::string resourceType;
size_t callbackInProgressCount; // Non zero if callback is in progress.
bool markedToBeRemoved; // Set to true when this object can't be removed in
// RemoveCallbackInfo(). It'll be removed opportunistically.
std::vector<std::string> discoveredDevicesList; // List of device ids that were indicated to
// app with IPCA_DEVICE_DISCOVERED.
std::shared_ptr<OC::OCResource> ocResource; // The OCResource this callback works with.
uint64_t requestSentTimestamp; // when the request was sent to the server.
CallbackInfo() { /* std::cout << "+ CallbackInfo " << this << std::endl; */ }
~CallbackInfo() { /* std::cout << "- CallbackInfo " << this << " mapKey: ";
std::cout << mapKey << std::endl; */ }
typedef std::shared_ptr<CallbackInfo> Ptr;
size_t mapKey; // key to m_callbackInfoList map. Initialized in AddCallbackInfo().
App* app; // the app that creates this callback.
DevicePtr device; // the device expected to respond to the callback.
CallbackType type;
union
{
IPCADiscoverDeviceCallback discoveryCallback;
IPCAResourceChangeCallback resourceChangeCallback;
IPCAGetPropertiesComplete getCallback;
IPCASetPropertiesComplete setCallback;
IPCACreateResourceComplete createResourceCallback;
IPCADeleteResourceComplete deleteResourceCallback;
IPCAProvidePasswordCallback passwordInputCallback;
IPCADisplayPasswordCallback passwordDisplayCallback;
IPCARequestAccessCompletionCallback requestAccessCompletionCallback;
};
const void* callbackContext; // app's callback context.
std::vector<std::string> resourceTypeList; // Parameter for Discovery.
std::string resourcePath; // Parameters for for Get, Set, Observe request.
std::string resourceInterface;
std::string resourceType;
size_t callbackInProgressCount; // Non zero if callback is in progress.
bool markedToBeRemoved; // Set to true when this object can't be removed in
// RemoveCallbackInfo(). It'll be removed opportunistically.
// closeHandleCompleteCallback is from argument in IPCACloseHandle().
// It will be set in this structure if IPCACloseHandle() is called when the callback
// for this CallbackInfo is in progress.
IPCACloseHandleComplete closeHandleCompleteCallback;
const void* closeHandleCompletecontext;
std::vector<std::string> discoveredDevicesList; // List of device ids that were indicated to
// app with IPCA_DEVICE_DISCOVERED.
std::shared_ptr<OC::OCResource> ocResource; // The OCResource this callback works with.
uint64_t requestSentTimestamp; // when the request was sent to the server.
};
// Represent IPCAResourceChangeCallback, IPCAGetPropertiesComplete, IPCASetPropertiesComplete.
......@@ -136,7 +143,10 @@ class Callback
// Remove the CallbackInfo matching mapKey. This function sets markedToBeRemoved if the
// callback is in the middle of calling back.
void RemoveCallbackInfo(size_t mapKey);
// Function returns IPCA_FAIL if callback is already closed.
IPCAStatus RemoveCallbackInfo(size_t mapKey,
IPCACloseHandleComplete closeHandleComplete = nullptr,
const void* context = nullptr);
// Complete the callback for expired CallbackInfo and remove them from the
// m_callbackInfoList. Caller receives a list of them.
......@@ -189,6 +199,13 @@ class Callback
bool MatchAllRequiredResourceTypes(const std::vector<std::string>& requiredResourceTypes,
const std::vector<std::string>& deviceResourceTypes);
// Callback to app's closeHandleComplete() that is set in IPCACloseHandle().
void CallCloseHandleComplete(IPCACloseHandleComplete closeHandleComplete,
const void* context);
// Common initialization for new CallbackInfo object.
void CommonInitializeCallbackInfo(CallbackInfo::Ptr callbackInfo);
private:
// Mutex for synchronization use.
std::mutex m_callbackMutex;
......
......@@ -290,13 +290,17 @@ IPCAStatus IPCA_CALL IPCADeleteResource(
handle);
}
void IPCA_CALL IPCACloseHandle(IPCAHandle handle)
IPCAStatus IPCA_CALL IPCACloseHandle(IPCAHandle handle,
IPCACloseHandleComplete closeHandleComplete,
void* context)
{
std::lock_guard<std::mutex> lock(g_ipcaAppMutex);
if (g_app != nullptr)
{
g_app->CloseIPCAHandle(handle);
return (g_app->CloseIPCAHandle(handle, closeHandleComplete, context));
}
return IPCA_FAIL;
}
typedef struct
......
......@@ -26,6 +26,7 @@
#include "iotivity_config.h"
#include "ocrandom.h"
#include "octypes.h"
#include "oic_time.h"
#include "ipca.h"
#include "ipcatestdata.h"
#include "ipcaelevatorclient.h"
......@@ -90,7 +91,7 @@ bool IPCAElevatorClient::GetElevatorProperties()
m_getDataCompleteCbCV.wait_for(
lock,
std::chrono::seconds(10),
[this ] { return m_getPropertiesCallbackCalled; });
[this] { return m_getPropertiesCallbackCalled; });
return m_getPropertiesCallbackCalled;
}
......@@ -178,7 +179,7 @@ bool IPCAElevatorClient::DeleteElevatorResource()
{
m_deleteResourceCallbackCalled = false;
// Set properties.
// Delete resource.
EXPECT_EQ(IPCA_OK, IPCADeleteResource(
m_deviceHandle,
&C_DeleteResourceCb,
......@@ -286,7 +287,7 @@ void IPCAElevatorClient::StopObserve()
{
if (m_observeHandle)
{
IPCACloseHandle(m_observeHandle);
IPCACloseHandle(m_observeHandle, nullptr, 0);
}
}
......@@ -382,7 +383,7 @@ void IPCAElevatorClient::TearDown()
{
if (m_observeHandle != nullptr)
{
IPCACloseHandle(m_observeHandle);
IPCACloseHandle(m_observeHandle, nullptr, 0);
m_observeHandle = nullptr;
}
......@@ -394,7 +395,7 @@ void IPCAElevatorClient::TearDown()
if (m_deviceDiscoveryHandle != nullptr)
{
IPCACloseHandle(m_deviceDiscoveryHandle);
IPCACloseHandle(m_deviceDiscoveryHandle, nullptr, 0);
m_deviceDiscoveryHandle = nullptr;
}
......@@ -646,7 +647,8 @@ void IPCAElevatorClient::DiscoverElevator1()
m_discoveredElevator1DeviceId.c_str(), &m_deviceHandle));
}
void IPCAElevatorClient::SetPropertiesCallback(IPCAStatus result,
void IPCAElevatorClient::SetPropertiesCallback(
IPCAStatus result,
void* context,
IPCAPropertyBagHandle propertyBagHandle)
{
......@@ -658,7 +660,8 @@ void IPCAElevatorClient::SetPropertiesCallback(IPCAStatus result,
m_setPropertiesCompleteCV.notify_all();
}
void IPCAElevatorClient::GetPropertiesCallback(IPCAStatus result,
void IPCAElevatorClient::GetPropertiesCallback(
IPCAStatus result,
void* context,
IPCAPropertyBagHandle propertyBagHandle)
{
......@@ -680,7 +683,8 @@ void IPCAElevatorClient::GetPropertiesCallback(IPCAStatus result,
m_getDataCompleteCbCV.notify_all();
}
void IPCAElevatorClient::CreateResourceCallback(IPCAStatus result,
void IPCAElevatorClient::CreateResourceCallback(
IPCAStatus result,
const char* newResourcePath,
IPCAPropertyBagHandle propertyBagHandle)
{
......@@ -715,3 +719,375 @@ void IPCAElevatorClient::ResourceChangeNotificationCallback(
m_resourceChangeCbCV.notify_all();
}
// This data structure is used to coordinate between C_ControlledRequestCompleteCallback() and
// RunCloseHandleTest().
typedef struct
{
bool isInCallback; // Set to true when callback for request is called.
bool isTimeToCompleteCallback; // Set to true when callback should complete.
uint64_t completeCallbackTimestamp; // Timestamp when isTimeToCompleteCallback is set.
uint64_t closeHandleCompleteTimestamp; // When IPCACloseHandleComplete() is called.
} ContextForCloseHandleTest;
// This callback coordinates with RunCloseHandleTest() on when to complete the callback.
void IPCA_CALL C_ControlledRequestCompleteCallback(
IPCAStatus result,
void* context,
IPCAPropertyBagHandle propertyBagHandle)
{
OC_UNUSED(propertyBagHandle);
ContextForCloseHandleTest* testContext = reinterpret_cast<ContextForCloseHandleTest*>(context);
testContext->isInCallback = true;
if (result != IPCA_OK)
{
std::cout << "C_ControlledRequestCompleteCallback(): unsuccessful. result = " << result;
std::cout << std::endl;
return;
}
// Hang on here until the RunCloseHandleTest() indicates that it's time to complete
// this callback.
while (testContext->isTimeToCompleteCallback == false)
{
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
}
void IPCA_CALL C_ControlledCreateResourceCallback(
IPCAStatus result,
void* context,
const char* newResourcePath,
IPCAPropertyBagHandle propertyBagHandle)
{
OC_UNUSED(newResourcePath);
C_ControlledRequestCompleteCallback(result, context, propertyBagHandle);
}
void IPCA_CALL C_ControlledDeleteResourceCallback(IPCAStatus result, void* context)