Files
pictureConvert/dng/dng_abort_sniffer.cpp
T
2019-10-31 17:22:20 +01:00

317 lines
5.8 KiB
C++

/*****************************************************************************/
// Copyright 2006-2019 Adobe Systems Incorporated
// All Rights Reserved.
//
// NOTICE: Adobe permits you to use, modify, and distribute this file in
// accordance with the terms of the Adobe license agreement accompanying it.
/*****************************************************************************/
#include "dng_abort_sniffer.h"
#include "dng_assertions.h"
#include "dng_mutex.h"
/*****************************************************************************/
#if qDNGThreadSafe
/*****************************************************************************/
// TO DO: This priority-based wait mechanism is not compatible with thread
// pools. Putting worker threads to sleep may result in deadlock because
// higher priority work may not make progress (the pool may not be able to
// spin up any new threads).
class dng_priority_manager
{
private:
// Use lower-level mutex and condition_variable for priority manager
// since we don't want to include these in our priority tracking.
dng_mutex fMutex;
dng_condition fCondition;
uint32 fCounter [dng_priority_count];
public:
dng_priority_manager ();
void Increment (dng_priority priority,
const char *name);
void Decrement (dng_priority priority,
const char *name);
void Wait (dng_abort_sniffer *sniffer);
private:
dng_priority MinPriority ()
{
// Assumes mutex is locked.
for (uint32 level = dng_priority_maximum;
level > dng_priority_minimum;
level--)
{
if (fCounter [level])
{
return (dng_priority) level;
}
}
return dng_priority_minimum;
}
};
/*****************************************************************************/
dng_priority_manager::dng_priority_manager ()
: fMutex ("dng_priority_manager::fMutex")
, fCondition ()
{
for (uint32 level = dng_priority_minimum;
level <= dng_priority_maximum;
level++)
{
fCounter [level] = 0;
}
}
/*****************************************************************************/
void dng_priority_manager::Increment (dng_priority priority,
const char *name)
{
dng_lock_mutex lock (&fMutex);
fCounter [priority] += 1;
#if 0
printf ("increment priority %d (%s) (%d, %d, %d)\n",
(int) priority,
name,
fCounter [dng_priority_low],
fCounter [dng_priority_medium],
fCounter [dng_priority_high]);
#else
(void) name;
#endif
}
/*****************************************************************************/
void dng_priority_manager::Decrement (dng_priority priority,
const char *name)
{
dng_priority oldMin = dng_priority_minimum;
dng_priority newMin = dng_priority_minimum;
{
dng_lock_mutex lock (&fMutex);
oldMin = MinPriority ();
fCounter [priority] -= 1;
newMin = MinPriority ();
#if 0
printf ("decrement priority %d (%s) (%d, %d, %d)\n",
(int) priority,
name,
fCounter [dng_priority_low],
fCounter [dng_priority_medium],
fCounter [dng_priority_high]);
#else
(void) name;
#endif
}
if (newMin < oldMin)
{
fCondition.Broadcast ();
}
}
/*****************************************************************************/
void dng_priority_manager::Wait (dng_abort_sniffer *sniffer)
{
if (!sniffer)
{
return;
}
const dng_priority priority = sniffer->Priority ();
if (priority < dng_priority_maximum)
{
dng_lock_mutex lock (&fMutex);
while (priority < MinPriority ())
{
fCondition.Wait (fMutex);
}
}
}
/*****************************************************************************/
static dng_priority_manager gPriorityManager;
/*****************************************************************************/
#endif // qDNGThreadSafe
/*****************************************************************************/
dng_set_minimum_priority::dng_set_minimum_priority (dng_priority priority,
const char *name)
: fPriority (priority)
{
#if qDNGThreadSafe
gPriorityManager.Increment (fPriority, name);
#endif
fName.Set (name);
}
/*****************************************************************************/
dng_set_minimum_priority::~dng_set_minimum_priority ()
{
#if qDNGThreadSafe
gPriorityManager.Decrement (fPriority, fName.Get ());
#endif
}
/*****************************************************************************/
dng_abort_sniffer::dng_abort_sniffer ()
: fPriority (dng_priority_maximum)
{
}
/*****************************************************************************/
dng_abort_sniffer::~dng_abort_sniffer ()
{
}
/*****************************************************************************/
void dng_abort_sniffer::SetPriority (dng_priority priority)
{
fPriority = priority;
}
/*****************************************************************************/
bool dng_abort_sniffer::SupportsPriorityWait () const
{
return false;
}
/*****************************************************************************/
void dng_abort_sniffer::SniffForAbort (dng_abort_sniffer *sniffer)
{
if (sniffer)
{
#if qDNGThreadSafe
if (sniffer->SupportsPriorityWait ())
{
gPriorityManager.Wait (sniffer);
}
#endif
sniffer->Sniff ();
}
}
/*****************************************************************************/
void dng_abort_sniffer::StartTask (const char * /* name */,
real64 /* fract */)
{
}
/*****************************************************************************/
void dng_abort_sniffer::EndTask ()
{
}
/*****************************************************************************/
void dng_abort_sniffer::UpdateProgress (real64 /* fract */)
{
}
/*****************************************************************************/