Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

/ray/src/lib/module/pool.cc

Go to the documentation of this file.
00001 /*
00002  * lib/module/pool.cc
00003  * 
00004  * Implementing shared objects loadable at runtime (.so, .dll, ...)
00005  * 
00006  * Copyright (c) 2004 by Wolfgang Wieser ] wwieser (a) gmx <*> de [ 
00007  * 
00008  * This file may be distributed and/or modified under the terms of the 
00009  * GNU General Public License version 2 as published by the Free Software 
00010  * Foundation. (See COPYING.GPL for details.)
00011  * 
00012  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
00013  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
00014  * 
00015  */
00016 
00017 #include "pool.h"
00018 
00019 #include <stdio.h>     
00020 
00021 
00022 // Initializing static data: 
00023 ModulePool *ModulePool::pool=NULL;
00024 
00025 
00026 _ISharedObject *ModulePool::_FindObjectByName(const char *name,bool requeue)
00027 {
00028     _ISharedObject *res=NULL;
00029     
00030     pool_mutex.lock();
00031     for(_ISharedObject *so=so_list.first(); so; so=so->next)
00032     {
00033         if(!strcmp(so->mname,name))
00034         {
00035             res=so;
00036             if(requeue && so->prev)
00037             {
00038                 // Re-queue at the beginning (if not already there). 
00039                 so_list.dequeue(so);
00040                 so_list.insert(so);
00041             }
00042             break;
00043         }
00044     }
00045     pool_mutex.unlock();
00046     
00047     return(res);
00048 }
00049 
00050 
00051 SharedObject ModulePool::_load(const char *name,int flags)
00052 {
00053     if(!this || !name)  return SharedObject();
00054     
00055     // First, see if we have already loaded this object: 
00056     _ISharedObject *so=_FindObjectByName(name,/*requeue=*/1);
00057     if(so)
00058     {  return(SharedObject(so));  }
00059     
00060     // so=NULL; here. Good. 
00061     
00062     // We need to load the object. 
00063     pool_mutex.lock();  // We lock here for correct g_module_error reporting. 
00064     GModule *module=g_module_open(name,(GModuleFlags)flags);
00065     if(!module)
00066     {
00067         // Failure. Compose SharedObject which indicated failure by 
00068         // setting the module to NULL and storing the error string 
00069         // as the name: 
00070         so=new _ISharedObject(NULL,g_module_error());
00071         // This has module=NULL; do NOT insert into so_list. 
00072     }
00073     else
00074     {
00075         so=new _ISharedObject(module,name);
00076         // Insert into list (at the beginning!)
00077         so_list.insert(so);
00078     }
00079     pool_mutex.unlock();
00080     
00081     return(SharedObject(so));
00082 }
00083 
00084 
00085 int ModulePool::_unload(const char *name)
00086 {
00087     if(!this)  return(2);
00088     if(!name)  return(0);
00089     
00090     _ISharedObject *so=_FindObjectByName(name,/*requeue=*/0);
00091     if(!so)  return(1);
00092     
00093     _unregister(so);
00094     
00095     return(0);
00096 }
00097 
00098 
00099 void ModulePool::_unregister(_ISharedObject *iso)
00100 {
00101     if(!this || !iso)  return;
00102     
00103     pool_mutex.lock();
00104     so_list.dequeue(iso);
00105     pool_mutex.unlock();
00106     
00107     // It is important to set the module pointer to NULL after 
00108     // having removed the object from the so_list since 
00109     // _unregister() is also used by _unload(). 
00110     GModule *module=iso->module;
00111     iso->module=NULL;
00112     
00113     // Unload the module: 
00114     if(!g_module_close(module))
00115     {
00116         // Closing the module failed. Hmm...
00117         fprintf(stderr,"OOPS: Failed to unload module %s\n",iso->name());
00118     }
00119 }
00120 
00121 
00122 int ModulePool::init()
00123 {
00124     // If modules are not supported, return immediately. 
00125     // The pool pointer will stay NULL. Members check for this==NULL. 
00126     if(!g_module_supported())
00127     {  return(1);  }
00128     
00129     // Initialize the pool. 
00130     new ModulePool();    // <-- Constructor will set ModulePool::pool. 
00131     
00132     return(0);
00133 }
00134 
00135 
00136 void ModulePool::cleanup()
00137 {
00138     if(pool)
00139     {  delete pool;  }
00140     // pool=NULL here by destructor of ModulePool. 
00141 }
00142 
00143 
00144 ModulePool::ModulePool() : 
00145     so_list(),
00146     pool_mutex()
00147 {
00148     Assert(!pool);
00149     pool=this;
00150 }
00151 
00152 
00153 ModulePool::~ModulePool()
00154 {
00155     Assert(pool==this);
00156     
00157     // Well, what should we do with these loaded modules?
00158     pool_mutex.lock();
00159     Assert(so_list.IsEmpty());
00160     while(!so_list.IsEmpty())
00161     {  _unregister(so_list.first());  }
00162     pool_mutex.unlock();
00163     
00164     pool=NULL;
00165 }
00166 
00167 
00168 #if 0
00169 // Example implementation. 
00170 
00171 #include <lib/module/pool.h>
00172 #include <lib/module/symbol.h>
00173 
00174 int main()
00175 {
00176     if(ModulePool::init())
00177     {  fprintf(stderr,"Modules not supported.\n");  exit(1);  }
00178     
00179     // Start your threads...
00180     // One of them calls "foo"
00181     
00182     ModulePool::cleanup();
00183     return(0);
00184 }
00185 
00186 void foo()
00187 {
00188     ModuleSymbol sym;
00189     
00190     {
00191         // We need to load a module: 
00192         SharedObject so=ModulePool::load("mymodule.so");
00193         if(so->error())  // Note: "pointer feeling" :) [overloaded operator!]
00194         { fprintf(stderr,"Failed to load module: %s\n",so->error()); return; }
00195         
00196         // Loading was success. Get a symbol: 
00197         ModuleSymbol sym_bar=so->lookup("bar");
00198         if(!sym_bar)  // equiv: if(!sym_bar.ptr())
00199         { fprintf(stderr,"OOPS: Symbol bar not present in module.\n"); return; }
00200         
00201         // You can use ModuleSymbol and SharedObject just like any other 
00202         // safe type (like PODs e.g.); just do not use pointers on them: 
00203         sym=sym_bar;
00204         
00205         // SharedObject "so" and ModuleSymbol "sym_bar" get destroyed but 
00206         // module will NOT be unloaded here since "sym" still holds a 
00207         // reference. 
00208     }
00209     
00210     typedef int (*bar_fptr)(double);
00211     // Call the function "bar" (which is provided by the module / shared 
00212     // object): 
00213     (*(bar_fptr)sym.ptr())( 3.14 );
00214     
00215     // Or, we can use the more convenient ModuleFunction class which is 
00216     // also a safe type and can be used like a function pointer: 
00217     ModuleFunction<int(*)(double)> bar=sym;  // or ModuleFunction<bar_fptr> ...
00218     (*bar)( 3.14 );
00219     
00220     // This will unload the module as we explicitly delete the last reference 
00221     // to it. 
00222     sym=ModuleSymbol();
00223     
00224     // NOTE that you can explicitly de-reference a shared object (i.e. 
00225     // make it a NULL reference) using: 
00226     //   SharedObject::deref(), i.e. so.deref() above (NOT so->deref()) 
00227     // or by assigning a NULL ref: 
00228     //   so = SharedObject();     (with so from above)
00229 }
00230 #endif

Generated on Sat Feb 19 22:33:45 2005 for Ray by doxygen 1.3.5