further fixes to bam loader ordering

This commit is contained in:
David Rose 2007-07-09 17:03:27 +00:00
parent 59916499a9
commit 0ebafd6c75
5 changed files with 83 additions and 48 deletions

View File

@ -623,7 +623,6 @@ fillin(DatagramIterator &scan, BamReader *manager, void *extra_data) {
} else {
// Now, the array data is just stored directly.
size_t size = scan.get_uint32();
_buffer.unclean_realloc(size);
const unsigned char *source_data =

View File

@ -1536,6 +1536,21 @@ complete_pointers(TypedWritable **p_list, BamReader *manager) {
return pi;
}
////////////////////////////////////////////////////////////////////
// Function: GeomVertexData::require_fully_complete
// Access: Public, Virtual
// Description: Some objects require all of their nested pointers to
// have been completed before the objects themselves can
// be completed. If this is the case, override this
// method to return true, and be careful with circular
// references (which would make the object unreadable
// from a bam file).
////////////////////////////////////////////////////////////////////
bool GeomVertexData::
require_fully_complete() const {
return true;
}
////////////////////////////////////////////////////////////////////
// Function: GeomVertexData::finalize
// Access: Public, Virtual
@ -1703,7 +1718,8 @@ complete_pointers(TypedWritable **p_list, BamReader *manager) {
// a SparseArray for each of them that reflects the complete
// number of rows in the data.
SparseArray all_rows;
all_rows.set_range(0, _arrays[0].get_read_pointer()->get_num_rows());
CPT(GeomVertexArrayData) adata = _arrays[0].get_read_pointer();
all_rows.set_range(0, adata->get_num_rows());
if (_slider_table != (SliderTable *)NULL) {
int num_sliders = _slider_table->get_num_sliders();

View File

@ -325,6 +325,7 @@ public:
static void register_with_read_factory();
virtual void write_datagram(BamWriter *manager, Datagram &dg);
virtual int complete_pointers(TypedWritable **plist, BamReader *manager);
virtual bool require_fully_complete() const;
virtual void finalize(BamReader *manager);

View File

@ -301,35 +301,11 @@ resolve() {
all_completed = true;
any_completed_this_pass = false;
// First do the PipelineCycler objects.
CyclerPointers::iterator ci;
ci = _cycler_pointers.begin();
while (ci != _cycler_pointers.end()) {
PipelineCyclerBase *cycler = (*ci).first;
const vector_int &pointer_ids = (*ci).second;
if (resolve_cycler_pointers(cycler, pointer_ids)) {
// Now remove this cycler from the list of things that need
// completion. We have to be a bit careful when deleting things
// from the STL container while we are traversing it.
CyclerPointers::iterator old = ci;
++ci;
_cycler_pointers.erase(old);
any_completed_this_pass = true;
} else {
// Couldn't complete this cycler yet; it'll wait for next time.
++ci;
all_completed = false;
}
}
// Now do the main objects.
ObjectPointers::iterator oi;
oi = _object_pointers.begin();
while (oi != _object_pointers.end()) {
int object_id = (*oi).first;
const vector_int &pointer_ids = (*oi).second;
PointerReference &pref = (*oi).second;
CreatedObjs::iterator ci = _created_objs.find(object_id);
nassertr(ci != _created_objs.end(), false);
@ -338,7 +314,7 @@ resolve() {
TypedWritable *object_ptr = created_obj._ptr;
if (resolve_object_pointers(object_ptr, pointer_ids)) {
if (resolve_object_pointers(object_ptr, pref)) {
// Now remove this object from the list of things that need
// completion. We have to be a bit careful when deleting things
// from the STL container while we are traversing it.
@ -574,12 +550,13 @@ read_pointer(DatagramIterator &scan) {
// Read the object ID, and associate it with the requesting object.
int object_id = read_object_id(scan);
PointerReference &pref = _object_pointers[requestor_id];
if (_reading_cycler == (PipelineCyclerBase *)NULL) {
// This is not being read within a read_cdata() call.
_object_pointers[requestor_id].push_back(object_id);
pref._objects.push_back(object_id);
} else {
// This *is* being read within a read_cdata() call.
_cycler_pointers[_reading_cycler].push_back(object_id);
pref._cycler_pointers[_reading_cycler].push_back(object_id);
}
// If the object ID is zero (which indicates a NULL pointer), we
@ -1054,7 +1031,39 @@ p_read_object() {
// and returns true; otherwise, returns false.
////////////////////////////////////////////////////////////////////
bool BamReader::
resolve_object_pointers(TypedWritable *object, const vector_int &pointer_ids) {
resolve_object_pointers(TypedWritable *object,
BamReader::PointerReference &pref) {
// Some objects further require all of their nested objects to have
// been completed (i.e. complete_pointers has been called on each
// nested object) before they can themselves be completed.
bool require_fully_complete = object->require_fully_complete();
// First do the PipelineCycler objects.
CyclerPointers::iterator ci;
ci = pref._cycler_pointers.begin();
while (ci != pref._cycler_pointers.end()) {
PipelineCyclerBase *cycler = (*ci).first;
const vector_int &pointer_ids = (*ci).second;
if (resolve_cycler_pointers(cycler, pointer_ids, require_fully_complete)) {
// Now remove this cycler from the list of things that need
// completion. We have to be a bit careful when deleting things
// from the STL container while we are traversing it.
CyclerPointers::iterator old = ci;
++ci;
pref._cycler_pointers.erase(old);
} else {
// Couldn't complete this cycler yet; it'll wait for next time.
++ci;
}
}
if (!pref._cycler_pointers.empty()) {
// If we didn't get all the cyclers, we have to wait.
return false;
}
// Now make sure we have all of the pointers this object is
// waiting for. If any of the pointers has not yet been read
// in, we can't resolve this object--we can't do anything for a
@ -1062,15 +1071,12 @@ resolve_object_pointers(TypedWritable *object, const vector_int &pointer_ids) {
// that object.
bool is_complete = true;
// Some objects further require all of their nested objects to have
// been completed (i.e. complete_pointers has been called on each
// nested object) before they can themselves be completed.
bool require_fully_complete = object->require_fully_complete();
vector_typedWritable references;
vector_int::const_iterator pi;
for (pi = pointer_ids.begin(); pi != pointer_ids.end() && is_complete; ++pi) {
for (pi = pref._objects.begin();
pi != pref._objects.end() && is_complete;
++pi) {
int child_id = (*pi);
if (child_id == 0) {
// A NULL pointer is a NULL pointer.
@ -1106,7 +1112,7 @@ resolve_object_pointers(TypedWritable *object, const vector_int &pointer_ids) {
if (is_complete) {
// Okay, here's the complete list of pointers for you!
nassertr(references.size() == pointer_ids.size(), false);
nassertr(references.size() == pref._objects.size(), false);
if (bam_cat.is_spam()) {
bam_cat.spam()
@ -1143,7 +1149,8 @@ resolve_object_pointers(TypedWritable *object, const vector_int &pointer_ids) {
////////////////////////////////////////////////////////////////////
bool BamReader::
resolve_cycler_pointers(PipelineCyclerBase *cycler,
const vector_int &pointer_ids) {
const vector_int &pointer_ids,
bool require_fully_complete) {
// Now make sure we have all of the pointers this cycler is
// waiting for. If any of the pointers has not yet been read
// in, we can't resolve this cycler--we can't do anything for a
@ -1175,8 +1182,15 @@ resolve_cycler_pointers(PipelineCyclerBase *cycler,
is_complete = false;
} else {
// Yes, it's ready.
references.push_back(child_obj._ptr);
if (require_fully_complete &&
_object_pointers.find(child_id) != _object_pointers.end()) {
// It's not yet complete itself.
is_complete = false;
} else {
// Yes, it's ready.
references.push_back(child_obj._ptr);
}
}
}
}

View File

@ -149,12 +149,15 @@ private:
INLINE static void create_factory();
private:
class PointerReference;
void free_object_ids(DatagramIterator &scan);
int read_object_id(DatagramIterator &scan);
int read_pta_id(DatagramIterator &scan);
int p_read_object();
bool resolve_object_pointers(TypedWritable *object, const vector_int &pointer_ids);
bool resolve_cycler_pointers(PipelineCyclerBase *cycler, const vector_int &pointer_ids);
bool resolve_object_pointers(TypedWritable *object, PointerReference &pref);
bool resolve_cycler_pointers(PipelineCyclerBase *cycler, const vector_int &pointer_ids,
bool require_fully_complete);
void finalize();
INLINE bool get_datagram(Datagram &datagram);
@ -215,12 +218,14 @@ private:
// completed, along with the object ID's of the pointers they need,
// in the order in which read_pointer() was called, so that we may
// call the appropriate complete_pointers() later.
typedef phash_map<int, vector_int, int_hash> ObjectPointers;
ObjectPointers _object_pointers;
// Ditto, for the PiplineCycler objects.
typedef phash_map<PipelineCyclerBase *, vector_int, pointer_hash> CyclerPointers;
CyclerPointers _cycler_pointers;
class PointerReference {
public:
vector_int _objects;
CyclerPointers _cycler_pointers;
};
typedef phash_map<int, PointerReference, int_hash> ObjectPointers;
ObjectPointers _object_pointers;
// This is the number of extra objects that must still be read (and
// saved in the _created_objs map) before returning from