/* Web Polygraph http://www.web-polygraph.org/
* (C) 2003-2006 The Measurement Factory
* Licensed under the Apache License, Version 2.0 */
#include "base/polygraph.h"
#include "base/UniqId.h"
#include "runtime/StatPhase.h"
#include "runtime/StatPhaseMgr.h"
#include "runtime/StatPhaseSync.h"
class StatPhaseGroup {
public:
StatPhaseGroup(const UniqId &aGroup): theGroup(aGroup), thePhaseSyncPos(-1) {}
const UniqId &group() const { return theGroup; }
int phaseSyncPos() const { return thePhaseSyncPos; }
void phaseSyncPos(int aPos) { thePhaseSyncPos = aPos; }
protected:
UniqId theGroup;
int thePhaseSyncPos;
};
StatPhaseSync TheStatPhaseSync;
// XXX: we need to grow this map on-demand basis!
StatPhaseSync::StatPhaseSync(): theIndex(37), theCount(0), thePhaseSyncPosMin(-1) {
}
StatPhaseSync::~StatPhaseSync() {
while (theIndex.count())
delete theIndex.pop();
}
int StatPhaseSync::phaseSyncPos() const {
return Min(thePhaseSyncPosMin, TheStatPhaseMgr.phaseSyncPos());
}
int StatPhaseSync::waitGroupCount() const {
const int ourPos = TheStatPhaseMgr.phaseSyncPos();
int cnt = 0;
for (int i = 0; i < capacity(); ++i) {
if (StatPhaseGroup *r = theIndex[i]) {
if (r->phaseSyncPos() < ourPos)
cnt++;
}
}
return cnt;
}
void StatPhaseSync::notePhaseSync(const UniqId &group, int pos) {
int idx = -1;
if (!find(group, idx)) {
addAt(idx, group);
Assert(pos >= 0);
thePhaseSyncPosMin = -1; // will force sync check below
}
StatPhaseGroup *grp = theIndex[idx];
const int oldPos = grp->phaseSyncPos();
// ignore stale information
if (pos <= oldPos)
return;
grp->phaseSyncPos(pos);
if (thePhaseSyncPosMin < pos) {
thePhaseSyncPosMin = -1;
bool inited = false;
for (int i = 0; i < capacity(); ++i) {
if (StatPhaseGroup *r = theIndex[i]) {
if (!inited || r->phaseSyncPos() < thePhaseSyncPosMin) {
thePhaseSyncPosMin = r->phaseSyncPos();
inited = true;
}
}
}
}
if (TheStatPhaseMgr->unlockToStop() && TheStatPhaseMgr.phaseSyncPos() <= thePhaseSyncPosMin)
TheStatPhaseMgr->unlock();
}
bool StatPhaseSync::find(const UniqId &group, int &idx) const {
if (!capacity())
return false;
// start with a hash and then try linear search
idx = group.hash() % capacity();
for (int i = capacity(); i; --i) {
bool res = false;
if (endSearch(group, idx, res))
return res;
idx++;
idx %= capacity();
}
Assert(false); // no empty slots left!
return false;
}
StatPhaseGroup *StatPhaseSync::addAt(int idx, const UniqId &group) {
Assert(group);
Assert(!theIndex[idx]);
theIndex.put(new StatPhaseGroup(group), idx);
theCount++;
return theIndex[idx];
}
// returns true if there is no reason to search further (match or empty)
bool StatPhaseSync::endSearch(const UniqId &group, int idx, bool &res) const {
if (StatPhaseGroup *h = theIndex[idx]) {
if (h->group() == group)
return res = true;
return res = false;
}
// found empty slot
res = false;
return true;
}
syntax highlighted by Code2HTML, v. 0.9.1