Fix unregister issue
This commit is contained in:
@@ -28,8 +28,12 @@ static void WriteWindowsEventLog(const char* message, WORD eventType = EVENTLOG_
|
||||
// ReleaseANSALPRHandle is called while inference is still running.
|
||||
// refcount: starts at 1 on Register. AcquireALPRHandle increments,
|
||||
// ReleaseALPRHandleRef decrements. Object is destroyed when refcount hits 0.
|
||||
static std::unordered_map<ANSCENTER::ANSALPR*, int>& ALPRHandleRegistry() {
|
||||
static std::unordered_map<ANSCENTER::ANSALPR*, int> s;
|
||||
// destructionStarted: set by the first Unregister caller; blocks new Acquires
|
||||
// and makes subsequent Unregister calls return false without deleting.
|
||||
// Prevents double-free when Release is raced on the same handle.
|
||||
struct ALPREntry { int refcount; bool destructionStarted; };
|
||||
static std::unordered_map<ANSCENTER::ANSALPR*, ALPREntry>& ALPRHandleRegistry() {
|
||||
static std::unordered_map<ANSCENTER::ANSALPR*, ALPREntry> s;
|
||||
return s;
|
||||
}
|
||||
static std::mutex& ALPRHandleRegistryMutex() {
|
||||
@@ -43,46 +47,48 @@ static std::condition_variable& ALPRHandleRegistryCV() {
|
||||
|
||||
static void RegisterALPRHandle(ANSCENTER::ANSALPR* h) {
|
||||
std::lock_guard<std::mutex> lk(ALPRHandleRegistryMutex());
|
||||
ALPRHandleRegistry()[h] = 1; // refcount = 1
|
||||
ALPRHandleRegistry()[h] = { 1, false };
|
||||
}
|
||||
|
||||
// Acquire a handle for use (increment refcount). Returns the handle
|
||||
// if valid, nullptr if already released.
|
||||
// if valid, nullptr if already released or being destroyed.
|
||||
static ANSCENTER::ANSALPR* AcquireALPRHandle(ANSCENTER::ANSALPR* h) {
|
||||
std::lock_guard<std::mutex> lk(ALPRHandleRegistryMutex());
|
||||
auto it = ALPRHandleRegistry().find(h);
|
||||
if (it == ALPRHandleRegistry().end()) return nullptr;
|
||||
it->second++;
|
||||
if (it->second.destructionStarted) return nullptr;
|
||||
it->second.refcount++;
|
||||
return h;
|
||||
}
|
||||
|
||||
// Release a use of the handle (decrement refcount).
|
||||
// Returns true if this was the last reference (caller should destroy).
|
||||
// Release a use of the handle (decrement refcount). Only signals the CV;
|
||||
// the object is always deleted by Unregister, never by a stray ref-drop.
|
||||
static bool ReleaseALPRHandleRef(ANSCENTER::ANSALPR* h) {
|
||||
std::lock_guard<std::mutex> lk(ALPRHandleRegistryMutex());
|
||||
auto it = ALPRHandleRegistry().find(h);
|
||||
if (it == ALPRHandleRegistry().end()) return false;
|
||||
it->second--;
|
||||
if (it->second <= 0) {
|
||||
ALPRHandleRegistry().erase(it);
|
||||
it->second.refcount--;
|
||||
if (it->second.refcount <= 0) {
|
||||
ALPRHandleRegistryCV().notify_all();
|
||||
return true; // Caller should destroy
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Unregister and wait for all in-flight uses to finish.
|
||||
// Decrements the creation refcount and blocks until refcount hits 0.
|
||||
// Returns true if caller should destroy the object.
|
||||
// First caller takes ownership of destruction; subsequent calls return false.
|
||||
static bool UnregisterALPRHandle(ANSCENTER::ANSALPR* h) {
|
||||
std::unique_lock<std::mutex> lk(ALPRHandleRegistryMutex());
|
||||
auto it = ALPRHandleRegistry().find(h);
|
||||
if (it == ALPRHandleRegistry().end()) return false;
|
||||
it->second--; // Remove creation ref
|
||||
// Wait for in-flight inferences to finish (30s timeout as safety net)
|
||||
if (it->second.destructionStarted) {
|
||||
// Another thread already owns the delete — back off.
|
||||
return false;
|
||||
}
|
||||
it->second.destructionStarted = true;
|
||||
it->second.refcount--; // Remove creation ref
|
||||
bool ok = ALPRHandleRegistryCV().wait_for(lk, std::chrono::seconds(30), [&]() {
|
||||
auto it2 = ALPRHandleRegistry().find(h);
|
||||
return it2 == ALPRHandleRegistry().end() || it2->second <= 0;
|
||||
return it2 == ALPRHandleRegistry().end() || it2->second.refcount <= 0;
|
||||
});
|
||||
if (!ok) {
|
||||
OutputDebugStringA("WARNING: UnregisterALPRHandle timed out waiting for in-flight inference\n");
|
||||
|
||||
Reference in New Issue
Block a user