317 lines
5.8 KiB
C++
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 */)
|
|
{
|
|
|
|
}
|
|
|
|
/*****************************************************************************/
|