+ bbtkDebugMessage("object",2,"==> Package::~Package(\""<<mName<<"\")"<<bbtkendl);
+ bbtkDebugMessage("object",2,"<== Package::~Package(\""<<mName<<"\")"<<bbtkendl);
+ }
+ //==========================================================================
+
+
+ //==========================================================================
+ void PackageReleaseBlackBoxDescriptorInternal(Package::WeakPointer pack,
+ const std::string& descname)
+ {
+ // Try to release descriptor
+ std::string packname = pack.lock()->GetName();
+
+ bbtkDebugMessage("package",5,"--- Releasing descriptor '"
+ <<packname<<"::"<<descname<<"'"<<bbtkendl);
+
+
+ Package::BlackBoxMapType::iterator desc =
+ pack.lock()->GetBlackBoxMap().find(descname);
+ if (desc == pack.lock()->GetBlackBoxMap().end())
+ {
+ bbtkDebugMessage("package",5,
+ " Descriptor has already been released"
+ <<bbtkendl);
+ return;
+ }
+ // bbtkDebugMessage("package",3,
+ // " Trying unreferencing it ... "<<std::endl);
+ BlackBoxDescriptor::WeakPointer pdesc = desc->second;
+ desc->second.reset();
+ // if it is dead : remove it
+ if (pdesc.expired())
+ {
+ bbtkDebugMessage("package",2," ==> '"<<packname<<"::"<<descname<<"' Descriptor expired"<<bbtkendl);
+ if (pack.expired())
+ {
+ bbtkDebugMessage("package",2,
+ " ... and caused its package death"
+ <<bbtkendl);
+ return;
+ }
+ desc = pack.lock()->GetBlackBoxMap().find(descname);
+ if (desc != pack.lock()->GetBlackBoxMap().end())
+ pack.lock()->GetBlackBoxMap().erase(desc);
+ }
+ else
+ {
+ bbtkDebugMessage("package",5," ... Descriptor still alive ("
+ <<pdesc.use_count()<<" refs)"
+ <<bbtkendl);
+ pack.lock()->GetBlackBoxMap()[descname] = pdesc.lock();
+ }
+ }
+ //==========================================================================
+
+
+ //==========================================================================
+ /// Release
+ void Package::Release(Package::WeakPointer pack)
+ {
+ std::string packname = pack.lock()->mName;
+ bbtkDebugMessage("package",1,"==> Package::Release('"<<
+ packname<<"')"<<bbtkendl);
+
+ long dyn = pack.lock()->mDynamicLibraryHandler ? 1:0;
+ long ndesc = pack.lock()->GetBlackBoxMap().size();
+ long nrefs = pack.use_count();
+
+ bbtkDebugMessage("package",5," "<<nrefs<<" refs / "
+ <<ndesc<<" descr / dyn="
+ <<dyn<<std::endl);
+
+ // A package is "free" from any external reference iff :
+ // i) It is not dynamically loaded and nrefs == ndesc
+ // (each desc references its package) or
+ // ii) It is dynamically loaded and nrefs == ndesc + 1
+ // (A dynamic library holds a static pointer on the package it contains
+ // which is allocated when the PACKAGENAMEGetPackage() func is called,
+ // and descallocated (reset) by PACKAGENAMEDeletePackage())
+ if (nrefs == ndesc + dyn)
+ {
+ bbtkDebugMessage("package",5,
+ " -> No more external ref : checking descriptors"
+ <<bbtkendl);
+ // We must take care that removing refs on descriptors
+ // can lead to their deletion which can in turn unref
+ // internal boxes which can release their descriptors hence
+ // call Package::ReleaseBlackBoxDescriptor
+ // As a consequence during descriptors release :
+ // 1) The map can change dynamically : we cannot iterate over it
+ // as any iterator can become invalid
+ // 2) The package can auto-destruct : we must test its existence
+ // after each release
+ // We must also take care of not locking the package pointer
+ // or any ref count check in Package::ReleaseBlackBoxDescriptor
+ // would be wrong
+
+ // The list of descriptors names at start
+ std::vector<std::string> descnamelist;
+ BlackBoxMapType::iterator i;
+ for (i=pack.lock()->mBlackBoxMap.begin();
+ i!= pack.lock()->mBlackBoxMap.end();
+ ++i)
+ descnamelist.push_back(i->first);
+
+ // Iterator over the initial names
+ std::vector<std::string>::iterator descname;
+ for (descname=descnamelist.begin();
+ descname!=descnamelist.end();
+ ++descname)
+ {
+ // Is package still alive ?
+ if (pack.expired())
+ {
+ bbtkDebugMessage("package",1,"--- Package::Release('"<<
+ packname
+ <<"') : package expired during release : bailing out"<<bbtkendl);
+ break;
+ }
+
+ PackageReleaseBlackBoxDescriptorInternal(pack,*descname);
+
+ }
+
+ //
+ UnLoadDynamicLibrary(pack);
+ // Unload orphan dl packages
+ Package::UnLoadReleasedDynamicallyLoadedPackages();
+
+
+
+
+ }
+
+#ifdef BBTK_COMPILE_DEBUG_MESSAGES
+
+ bbtkDebugMessage("package",2,"<== Package::Release('"<<
+ packname<<"')"<<bbtkendl);
+
+ if (!pack.expired())
+ {
+ long dyn = pack.lock()->mDynamicLibraryHandler ? 1:0;
+ long ndesc = pack.lock()->GetBlackBoxMap().size();
+ long nrefs = pack.use_count();
+
+ bbtkDebugMessage("package",1," ... Package still alive ("
+ <<nrefs<<" refs / "
+ <<ndesc<<" descr / dyn="
+ <<dyn<<")"<<std::endl);
+ }
+ else
+ {
+ bbtkDebugMessage("package",1," ... Package has been released"
+ <<std::endl);
+ }
+#endif
+ }
+ //==========================================================================
+
+ //==========================================================================
+ /// "Releases" the package
+ /// Signals the package that it can free the given descriptor
+ /// if they are no more used and free itself if it is no
+ /// more used
+ /// Note : Any non-weak pointer on the package must have been freed
+ void Package::ReleaseBlackBoxDescriptor(Package::WeakPointer pack,
+ BlackBoxDescriptor::WeakPointer descr)
+ {
+ std::string packname = pack.lock()->mName;
+ std::string dname = descr.lock()->GetTypeName();
+ bbtkDebugMessage("package",3,"==> Package::ReleaseBlackBoxDescriptor('"<<
+ packname<<"','"<<dname<<"') : refs="
+ <<descr.use_count()<<bbtkendl);
+
+ long dyn = pack.lock()->mDynamicLibraryHandler ? 1:0;
+ long ndesc = pack.lock()->GetBlackBoxMap().size();
+ long nrefs = pack.use_count();
+
+ bbtkDebugMessage("package",5," "<<nrefs<<" refs / "
+ <<ndesc<<" descr / dynamically loaded = "
+ <<dyn<<std::endl);
+
+ // A package is "free" from any external reference iff :
+ // i) It is not dynamically loaded and nrefs == ndesc
+ // (each desc references its package) or
+ // ii) It is dynamically loaded and nrefs == ndesc + 1
+ // (A dynamic library holds a static pointer on the package it contains
+ // which is allocated when the PACKAGENAMEGetPackage() func is called,
+ // and descallocated (reset) by PACKAGENAMEDeletePackage())
+ if (nrefs == ndesc + dyn)
+ {
+ PackageReleaseBlackBoxDescriptorInternal(pack,dname);
+ }
+
+ // If the package is released and dynamically loaded
+ // then put it in the static list mReleasedDynamicallyLoadedPackages
+ UnLoadDynamicLibrary(pack,false);
+
+ bbtkDebugMessage("package",4,"<== Package::ReleaseBlackBoxDescriptor('"<<
+ packname<<"','"<<dname<<"'): refs="
+ <<descr.use_count()<<bbtkendl);