1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181
|
//
// $Id$
//
//
// Original author: Darren Kessner <darren@proteowizard.org>
//
// Copyright 2008 Spielberg Family Center for Applied Proteomics
// Cedars Sinai Medical Center, Los Angeles, California 90048
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#define PWIZ_SOURCE
#include "Std.hpp"
#include "IterationListener.hpp"
#include <ctime>
namespace pwiz {
namespace util {
//
// IterationListenerRegistry::Impl
//
class IterationListenerRegistry::Impl
{
public:
void addListener(const IterationListenerPtr& listener, size_t iterationPeriod)
{
listeners_[listener] = iterationPeriod;
}
void addListenerWithTimer(const IterationListenerPtr& listener, double timePeriod)
{
listeners_[listener] = CallbackInfo(timePeriod, true);
}
void removeListener(const IterationListenerPtr& listener)
{
listeners_.erase(listener);
}
IterationListener::Status broadcastUpdateMessage(
const IterationListener::UpdateMessage& updateMessage) const
{
IterationListener::Status result = IterationListener::Status_Ok;
for (Listeners::const_iterator itr = listeners_.begin(); itr != listeners_.end(); ++itr)
{
time_t now;
time(&now);
const IterationListenerPtr& listener = itr->first;
const CallbackInfo& callbackInfo = itr->second;
CallbackInfo::PeriodType periodType = callbackInfo.periodType;
bool shouldUpdate =
updateMessage.iterationIndex == 0 || // always update on iteration 0
((updateMessage.iterationIndex > callbackInfo.lastIterationIndex || // only update in PeriodType_Iteration mode if the iteration has incremented or the message has changed
&updateMessage.message != callbackInfo.lastMessage) &&
((updateMessage.iterationCount > 0 && updateMessage.iterationIndex+1 >= updateMessage.iterationCount) ||
(periodType == CallbackInfo::PeriodType_Iteration && (updateMessage.iterationIndex+1) % callbackInfo.iterationPeriod == 0))) ||
(periodType == CallbackInfo::PeriodType_Time && difftime(now, callbackInfo.timestamp) >= callbackInfo.timePeriod);
if (shouldUpdate)
{
IterationListener::Status status = listener->update(updateMessage);
if (status == IterationListener::Status_Cancel) result = status;
if (periodType == CallbackInfo::PeriodType_Time)
callbackInfo.timestamp = now;
else
callbackInfo.lastIterationIndex = updateMessage.iterationIndex;
callbackInfo.lastMessage = &updateMessage.message;
}
}
return result;
}
private:
struct CallbackInfo
{
enum PeriodType {PeriodType_Iteration, PeriodType_Time};
PeriodType periodType;
size_t iterationPeriod;
double timePeriod; // seconds
mutable time_t timestamp;
mutable size_t lastIterationIndex;
mutable const string* lastMessage; // never dereference this, only compare pointer values
CallbackInfo(size_t _iterationPeriod = 1)
: periodType(PeriodType_Iteration),
iterationPeriod(_iterationPeriod),
timePeriod(0),
lastIterationIndex(0),
lastMessage(NULL)
{}
CallbackInfo(double _timePeriod, bool mustBeTrue)
: periodType(PeriodType_Time),
iterationPeriod(0),
timePeriod(_timePeriod),
lastIterationIndex(0),
lastMessage(NULL)
{
if (mustBeTrue != true)
throw runtime_error("[IterationListenerRegistry::CallbackInfo] Wrong constructor.");
}
};
typedef map<IterationListenerPtr, CallbackInfo> Listeners;
mutable Listeners listeners_;
};
PWIZ_API_DECL std::string IterationListener::no_message;
//
// IterationListenerRegistry
//
PWIZ_API_DECL IterationListenerRegistry::IterationListenerRegistry()
: impl_(new Impl)
{}
PWIZ_API_DECL
void IterationListenerRegistry::addListener(const IterationListenerPtr& listener,
size_t iterationPeriod)
{
impl_->addListener(listener, iterationPeriod);
}
PWIZ_API_DECL
void IterationListenerRegistry::addListenerWithTimer(const IterationListenerPtr& listener,
double timePeriod)
{
impl_->addListenerWithTimer(listener, timePeriod);
}
PWIZ_API_DECL void IterationListenerRegistry::removeListener(const IterationListenerPtr& listener)
{
impl_->removeListener(listener);
}
PWIZ_API_DECL IterationListener::Status
IterationListenerRegistry::broadcastUpdateMessage(
const IterationListener::UpdateMessage& updateMessage) const
{
return impl_->broadcastUpdateMessage(updateMessage);
}
} // namespace util
} // namespace pwiz
|