summaryrefslogtreecommitdiff
path: root/synth/shared_object_manager.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'synth/shared_object_manager.cpp')
-rw-r--r--synth/shared_object_manager.cpp65
1 files changed, 65 insertions, 0 deletions
diff --git a/synth/shared_object_manager.cpp b/synth/shared_object_manager.cpp
new file mode 100644
index 0000000..045f409
--- /dev/null
+++ b/synth/shared_object_manager.cpp
@@ -0,0 +1,65 @@
+#include <dlfcn.h>
+#include <map>
+#include <string>
+
+#include "util.h"
+#include "shared_object_manager.h"
+
+using namespace std;
+
+map<void*, int> dl_ref_count;
+
+void* my_dlopen(string file)
+{
+ void* handle;
+
+ if (file.find('/')==string::npos)
+ file="./"+file;
+
+ handle=dlopen(file.c_str(),RTLD_NOW);
+
+ if (handle==NULL)
+ throw string("could not open shared object (")+string(dlerror())+string(")");
+
+ if (dl_ref_count[handle]!=0) //the library is already opened
+ {
+ output_verbose("the requested shared object '"+file+"' is already opened, reusing the handle #"+IntToStr(int(handle)));
+ dlclose(handle); //we don't need it opened twice
+ }
+ else
+ {
+ output_verbose("the requested shared object '"+file+"' has been loaded with handle #"+IntToStr(int(handle)));
+ }
+
+ dl_ref_count[handle]++;
+
+ return handle;
+}
+
+void dlref_inc(void* handle)
+{
+ if (handle==NULL)
+ throw string("dlref_inc: tried to increment the ref-count for NULL");
+
+ if (dl_ref_count[handle]==0)
+ throw string("dlref_inc: tried to increment the ref-count for a nonexistent handle");
+
+ dl_ref_count[handle]++;
+}
+
+void dlref_dec(void* handle)
+{
+ if (handle==NULL)
+ throw string("dlref_inc: tried to increment the ref-count for NULL");
+
+ if (dl_ref_count[handle]==0)
+ throw string("dlref_inc: tried to decrement the ref-count for a nonexistent handle");
+
+ dl_ref_count[handle]--;
+
+ if (dl_ref_count[handle]==0)
+ {
+ output_verbose("noone uses dl-handle "+IntToStr(int(handle))+", unloading the shared object...");
+ dlclose(handle);
+ }
+}