Carsten Neumann wrote:
>       Hi,
> 
> I'm currently working on ticket #124 and thought I'll let you know what
> I intend to do, so you can stop me from introducing any unmaintainable
> garbage ;)
> My current design should be able to deliver the same features as the
> current OSB loader, but without the static member variables. I do not
> have much code yet, just enough to convince myself that the rest can be
> done in a similar fashion (I've attached a file with sketches of the
> main classes).
> 
> With the current NFIO classes there is one for each FieldContainer that
> requires special handling and one (NFIOGeneric) that handles all others.
> Global state of the loader is stored in static member variables so that
> the individual objects have access to it. Loader objects are created by
> NFIOFactory which chooses the proper one from the type name of the
> container to load.
> The basics will remain quite similar, but there'll be the notion of a
> root element that reads/writes the file header, holds the global state
> and drives the i/o process. Every i/o object will hold a pointer to the
> root element. The i/o objects should be lightweight enough to allow
> rapid creation, but maybe the factory will need to be outfitted with a
> pool or use a special allocator.
> 
> I'm aware this is a quite terse description, but I'll be happy to give
> more details if you are interested, so comments, ideas and questions are
> very welcome.

This sounds reasonable to me and describes similar thoughts I had when I 
looked into that code.

A couple of ideas that may be worth thinking about:

- Using boost::shared_ptr's for the backreferences.  I would very much 
like to see the memory handling in OpenSG become a little more robust. 
One way that I have used in my own code is to use boost::shared_ptr and 
boost::weak_ptr to make sure everything is collected correctly.  This 
may be useful here to make sure nothing gets deleted early.

- Is there any way to look at the NFIOElement's as implementations of a 
strategy pattern that simply take a reference to a per-file global 
state.  In more detail.

What if the factory held a set of lightweight strategy objects.  One 
instance per element type that needs custom handling.  When a file needs 
to be written or read, the system creates a file-state object that track 
the global state needed for that single IO.  Then as the process 
progresses the read/write algorithm core (possibly implemented inside 
the state tracking object) asks the factory object for the correct 
strategy to use for the encountered fc type.  The factory will either 
return the generic strategy or a custom strategy.  Then the algorithm 
still calls the read/postRead/preWrite/write methods but does so with an 
additional parameter, namely the file-state object.

This would remove the threading issues because all data would be stored 
in the file-state object and it would make it so only one instance of 
the strategies for each custom fc type would ever need to be created. 
The strategies themselves would be thread-safe and re-entrant (ie. 
multiple read/writes could use the same strategy in parallel) because 
all the state would be held in the file-state object.

Note: I have not taken a look at the NFIO code based on this idea.  I am 
just thinking of this from memory.  So feel free to ignore the idea if 
it can't be realized with the current codebase.

Thanks for taking on this challenge.  It is very nice to have someone 
investing so much time in the 2.0 code.

-Allen

> 
>       Cheers,
>               Carsten
> 
> 
> ------------------------------------------------------------------------
> 
> 
> // Base for elments
> class NFIOElementBase
> {
>   public:
>     virtual void read    (const std::string &typeName) = 0;
>     virtual void postRead(      void                 ) = 0;
> 
>     virtual void preWrite(const FieldContainerPtr &fc) = 0;
>     virtual void write   (const FieldContainerPtr &fc) = 0;
> 
>   protected:
>     struct PtrFieldInfo
>     {
>         FieldContainerPtr    _fc;
>         UInt32               _fieldId;
>         std::vector<UInt32>  _ptrIds;
>     };
> 
>   private:
>     FieldContainerPtr  _container;    // container read by this element
>     NFIORootElement   *_rootElement;  // root
>     UInt16             _version;      // version supported by this element
> };
> 
> // Holds global state for i/o, drives the reading/writing process.
> class NFIORootElement : public NFIOElementBase
> {
>   public:
>     // read file header - trigger reading of FCs in file - fill _elements
>     virtual void read    (const std::string &typeName);
> 
>     // call postRead for all _elements - afterwards map file ptr ids to real 
> ptrs
>     virtual void postRead(      void                 );
> 
>     // count/determine FCs that need to be written - fill _writeFCList
>     virtual void preWrite(const FieldContainerPtr &fc);
> 
>     // write out containers
>     virtual void write   (const FieldContainerPtr &fc);
> 
>   protected:
>     BinaryReadHandler           *_readHandler;
>     BinaryWriteHandler          *_writeHandler;
> 
>     NFIOOptions                  _options;
>     std::list<NFIOElementBase *> _elements;
> 
>     UInt16                       _readHeaderVersion;
>     std::map <UInt32, UInt32>    _readIdMap;
>     std::list<PtrFieldInfo  >    _readPtrFields;
> 
>     std::list<FieldContainerPtr> _writeFCList;
>     std::set <UInt32           > _writeIdSet;
> };
> 
> class NFIOCommonElement : public NFIOElementBase
> {
>     // helper methods that are useful for implementing a specific loader
> };
> 
> // loader for all FCs that do not need special handling
> class NFIOGeneric : public NFIOCommonElement
> {
>   public:
>     virtual void read    (const std::string &typeName);
>     virtual void postRead(      void                 );
> 
>     virtual void preWrite(const FieldContainerPtr &fc);
>     virtual void write   (const FieldContainerPtr &fc);
> };
> 
> 
> // Factory singleton for the loader/writer elements - should probably use
> // some sort of pool or special purpose allocator to allow rapid creation of
> // the objects.
> class NFIOFactory
> {
>     // singleton access
>     static NFIOFactory *the(void);
> 
>     NFIOElementBase *acquire(const std::string &typeName, NFIORootElement 
> *root);
>     void             release(NFIOElementBase *elem);
> };
> 
> 
> ------------------------------------------------------------------------
> 
> -------------------------------------------------------------------------
> Take Surveys. Earn Cash. Influence the Future of IT
> Join SourceForge.net's Techsay panel and you'll get the chance to share your
> opinions on IT & business topics through brief surveys - and earn cash
> http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
> 
> 
> ------------------------------------------------------------------------
> 
> _______________________________________________
> Opensg-core mailing list
> [email protected]
> https://lists.sourceforge.net/lists/listinfo/opensg-core


-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys - and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
_______________________________________________
Opensg-core mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/opensg-core

Reply via email to