Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -511,6 +511,10 @@ public void onDebugEvent(DebugEvent evt) {

ListenForFilter listener = new ListenForFilter();
manager.addEventListener(DebugEventType.EVT_FILTERED, listener);
long listenerIdentity = listener.nativeIdentity;
assertThat(listenerIdentity, is(not(-1L)));
manager.addEventListener(DebugEventType.EVT_REJECTED, listener);
assertThat(listener.nativeIdentity, is(listenerIdentity));
logger.logEvent("noprops");
manager.uploadNow();
try {
Expand All @@ -531,6 +535,9 @@ public void onDebugEvent(DebugEvent evt) {
assertThat(listener.filteredCount, is(1L));
}
manager.removeEventListener(DebugEventType.EVT_FILTERED, listener);
assertThat(listener.nativeIdentity, is(listenerIdentity));
manager.removeEventListener(DebugEventType.EVT_REJECTED, listener);
assertThat(listener.nativeIdentity, is(-1L));
int[] everything = { DiagLevel.DIAG_LEVEL_REQUIRED.value(), DiagLevel.DIAG_LEVEL_OPTIONAL.value() };
manager.setLevelFilter(DiagLevel.DIAG_LEVEL_OPTIONAL.value(), everything);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -272,11 +272,13 @@ public void addEventListener(DebugEventType eventType, DebugEventListener listen
listener.nativeIdentity = nativeAddEventListener(nativeLogManager, eventType.value(), listener, listener.nativeIdentity);
}

public native void nativeRemoveEventListener(long nativeLogManager, long eventType, long identity);
public native long nativeRemoveEventListener(
long nativeLogManager, long eventType, long identity, DebugEventListener listener);

@Override
public void removeEventListener(DebugEventType eventType, DebugEventListener listener) {
nativeRemoveEventListener(nativeLogManager, eventType.value(), listener.nativeIdentity);
listener.nativeIdentity = nativeRemoveEventListener(
nativeLogManager, eventType.value(), listener.nativeIdentity, listener);
}

private native boolean nativeRegisterPrivacyGuard(long nativeLogManager);
Expand Down
81 changes: 78 additions & 3 deletions lib/callbacks/DebugSource.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,88 @@
// SPDX-License-Identifier: Apache-2.0
//
#include "mat/config.h"
#include "callbacks/DebugSourceInternal.hpp"
#include "DebugEvents.hpp"
#include "utils/Utils.hpp"
#include "pal/PAL.hpp"

#include <atomic>
#include <iterator>

namespace MAT_NS_BEGIN {

namespace
{
thread_local std::vector<DebugEventListener*> pendingListeners;
std::atomic<DebugEventListenerPendingReleaseCallback>
pendingReleaseCallback{nullptr};

class PendingListenersScope
{
public:
explicit PendingListenersScope(const std::vector<DebugEventListener*>& listeners) :
remaining(listeners)
{
pendingListeners.insert(
pendingListeners.end(),
listeners.begin(),
listeners.end());
}

~PendingListenersScope()
{
for (auto listener : remaining)
{
RemovePending(listener);
auto callback = pendingReleaseCallback.load();
if (callback != nullptr)
{
callback(listener);
}
}
}

void BeginCallback(DebugEventListener* listener)
{
auto current = std::find(remaining.begin(), remaining.end(), listener);
if (current != remaining.end())
{
remaining.erase(current);
}
RemovePending(listener);
}

private:
static void RemovePending(DebugEventListener* listener)
{
auto pending = std::find(
pendingListeners.rbegin(),
pendingListeners.rend(),
listener);
if (pending != pendingListeners.rend())
{
pendingListeners.erase(std::next(pending).base());
}
}

std::vector<DebugEventListener*> remaining;
};
}

bool IsDebugEventListenerPending(const DebugEventListener* listener) noexcept
{
return std::find(
pendingListeners.begin(),
pendingListeners.end(),
listener) != pendingListeners.end();
}

void SetDebugEventListenerPendingReleaseCallback(
DebugEventListenerPendingReleaseCallback callback) noexcept
{
pendingReleaseCallback.store(callback);
}

/// <summary>Add event listener for specific debug event type.</summary>
void DebugEventSource::AddEventListener(DebugEventType type, DebugEventListener &listener)
{
Expand Down Expand Up @@ -45,8 +119,10 @@ namespace MAT_NS_BEGIN {

if (listeners.size()) {
// Events filter handlers list
auto &v = listeners[evt.type];
for (auto listener : v) {
auto eventListeners = listeners[evt.type];
PendingListenersScope pendingScope(eventListeners);
for (auto listener : eventListeners) {
pendingScope.BeginCallback(listener);
listener->OnDebugEvent(evt);
dispatched = true;
}
Expand Down Expand Up @@ -85,4 +161,3 @@ namespace MAT_NS_BEGIN {
}

} MAT_NS_END

18 changes: 18 additions & 0 deletions lib/callbacks/DebugSourceInternal.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
//
// Copyright (c) Microsoft Corporation. All rights reserved.
// SPDX-License-Identifier: Apache-2.0
//
#pragma once

#include "DebugEvents.hpp"

namespace MAT_NS_BEGIN
{
using DebugEventListenerPendingReleaseCallback =
void (*)(DebugEventListener*);

bool IsDebugEventListenerPending(const DebugEventListener* listener) noexcept;
void SetDebugEventListenerPendingReleaseCallback(
DebugEventListenerPendingReleaseCallback callback) noexcept;
}
MAT_NS_END
18 changes: 16 additions & 2 deletions lib/jni/JniConvertors.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -196,12 +196,26 @@ EventProperties GetEventProperties(JNIEnv* env, const jstring& jstrEventName, co
std::vector<std::string> ConvertJObjectArrayToStdStringVector(JNIEnv* env, const jobjectArray& jArrayToConvert)
{
std::vector<std::string> stringVector;
stringVector.reserve(env->GetArrayLength(jArrayToConvert));
auto length = env->GetArrayLength(jArrayToConvert);
if (env->ExceptionCheck())
{
return stringVector;
}
stringVector.reserve(length);

for(int i = 0; i < env->GetArrayLength(jArrayToConvert); i++)
for(int i = 0; i < length; i++)
{
auto jStringValue = static_cast<jstring>(env->GetObjectArrayElement(jArrayToConvert, i));
if (env->ExceptionCheck())
{
return stringVector;
}
auto stringValue = JStringToStdString(env, jStringValue);
if (env->ExceptionCheck())
{
env->DeleteLocalRef(jStringValue);
return stringVector;
}
if(!stringValue.empty())
{
stringVector.emplace_back(std::move(stringValue));
Expand Down
Loading
Loading