#include <simgear/bucket/newbucket.hxx>
#include <simgear/misc/sg_path.hxx>
#include <simgear/misc/strutils.hxx>
+#include <simgear/threads/SGThread.hxx>
+#include <simgear/threads/SGGuard.hxx>
#include <Main/globals.hxx>
#include "markerbeacon.hxx"
namespace flightgear
{
+/**
+ * Thread encapsulating a cache rebuild. This is not used to parallelise
+ * the rebuild - we must still wait until completion before doing other
+ * startup, since many things rely on a complete cache. The thread is used
+ * so we don't block the main event loop for an unacceptable duration,
+ * which causes 'not responding' / spinning beachballs on Windows & Mac
+ */
+class RebuildThread : public SGThread
+{
+public:
+ RebuildThread(NavDataCache* cache) :
+ _cache(cache),
+ _isFinished(false)
+ {
+
+ }
+
+ bool isFinished() const
+ {
+ SGGuard<SGMutex> g(_lock);
+ return _isFinished;
+ }
+
+ virtual void run()
+ {
+ SGTimeStamp st;
+ st.stamp();
+ _cache->doRebuild();
+ SG_LOG(SG_GENERAL, SG_INFO, "cache rebuild took:" << st.elapsedMSec() << "msec");
+
+ SGGuard<SGMutex> g(_lock);
+ _isFinished = true;
+ }
+private:
+ NavDataCache* _cache;
+ mutable SGMutex _lock;
+ bool _isFinished;
+};
+
+////////////////////////////////////////////////////////////////////////////
+
typedef std::map<PositionedID, FGPositionedRef> PositionedCache;
class AirportTower : public FGPositioned
int range = sqlite3_column_int(loadCommStation, 0);
int freqKhz = sqlite3_column_int(loadCommStation, 1);
- CommStation* c = new CommStation(rowId, id, ty, pos, freqKhz, range);
+ CommStation* c = new CommStation(rowId, name, ty, pos, freqKhz, range);
c->setAirport(airport);
return c;
}
StmtVec prepared;
std::set<Octree::Branch*> deferredOctreeUpdates;
+
+ // if we're performing a rebuild, the thread that is doing the work.
+ // otherwise, NULL
+ std::auto_ptr<RebuildThread> rebuilder;
};
//////////////////////////////////////////////////////////////////////
// reached this point with no exception, success
break;
} catch (sg_exception& e) {
- SG_LOG(SG_NAVCACHE, SG_WARN, "NavCache: init failed:" << e.what()
+ SG_LOG(SG_NAVCACHE, t == 0 ? SG_WARN : SG_ALERT, "NavCache: init failed:" << e.what()
<< " (attempt " << t << ")");
- homePath.remove();
d.reset();
+ homePath.remove();
}
} // of retry loop
return false;
}
-void NavDataCache::rebuild()
+bool NavDataCache::rebuild()
+{
+ if (!d->rebuilder.get()) {
+ d->rebuilder.reset(new RebuildThread(this));
+ d->rebuilder->start();
+ }
+
+// poll the rebuild thread
+ bool fin = d->rebuilder->isFinished();
+ if (fin) {
+ d->rebuilder.reset(); // all done!
+ }
+ return fin;
+}
+
+void NavDataCache::doRebuild()
{
try {
d->runSQL("BEGIN");
sqlite3_bind_double(d->findCommByFreq, 5, cartPos.y());
sqlite3_bind_double(d->findCommByFreq, 6, cartPos.z());
- if (!d->execSelect(d->findCommByFreq)) {
- return NULL;
+ while (d->execSelect(d->findCommByFreq)) {
+ FGPositioned* p = loadById(sqlite3_column_int64(d->findCommByFreq, 0));
+ if (aFilter && !aFilter->pass(p)) {
+ continue;
+ }
+
+ return p;
}
- return loadById(sqlite3_column_int64(d->findCommByFreq, 0));
+ return NULL;
}
PositionedIDVec