summaryrefslogtreecommitdiff
path: root/src/modl.cpp
blob: dc6770ba1c1fe96346db944e986d13bf6c8fd4c3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
// class modl implementation.

#ifndef MODL_CXX
#define MODL_CXX

#include <limits.h>
#include <stdlib.h>
#include <dlfcn.h>
#include <stdio.h>

#include "s_mutx.h"
#include "modl.h"

using namespace std;

modl::modl(  )
{
  map_mods = new hmap<dynmod*,string>(80);
  pthread_mutex_init( &mut_map_mods, NULL );
}

modl::~modl()
{
  pthread_mutex_lock   ( &mut_map_mods );

  // dlclose all the_module's first!
  map_mods->run_func   ( &modl::dlclose_ );

  // then clean the hash map.
  map_mods->make_empty (               );

  pthread_mutex_unlock ( &mut_map_mods );
  pthread_mutex_destroy( &mut_map_mods );
}

void
modl::dlclose_( dynmod* mod )
{
  dlclose( mod->the_module );
}

dynmod*
modl::cache_module( string s_name )
{
  void     *the_module = NULL;
  function *the_func   = NULL;

  the_module = dlopen( s_name.c_str(), RTLD_NOW );

  if ( the_module == NULL )
  {
    pthread_mutex_lock  ( &s_mutx::get
                            ().mut_stdout );
    cerr << "dlerror: " << dlerror() << endl;
    pthread_mutex_unlock( &s_mutx::get
                            ().mut_stdout );
    return NULL;
  }

  the_func = (function*) dlsym( the_module, "extern_function" );

  if ( the_func == NULL )
  {
    pthread_mutex_lock  ( &s_mutx::get
                            ().mut_stdout );
    cerr << "dlerror: " << dlerror() << endl;
    pthread_mutex_unlock( &s_mutx::get
                            ().mut_stdout );
    return NULL;
  }

#ifdef VERBOSE
  pthread_mutex_lock  ( &s_mutx::get
                          ().mut_stdout );
  cout << MODULEC << s_name << endl;
  pthread_mutex_unlock( &s_mutx::get
                          ().mut_stdout );
#endif

  dynmod *mod     = new dynmod; // encapsulates the function and module handler.
  mod->the_func   = the_func  ; // the function to execute
  mod->the_module = the_module; // the module handler to close if function
  // is not needed anymore.
  pthread_mutex_lock  ( &mut_map_mods );
  map_mods->add_elem  ( mod, s_name  );
  pthread_mutex_unlock( &mut_map_mods );

  // DO NOT CLOSE AS LONG THERE EXIST A POINTER TO THE FUNCTION
  // dlclose( module );

  return mod;
}

dynmod*
modl::get_module( string s_name )
{
  pthread_mutex_lock  ( &mut_map_mods );
  dynmod* mod = map_mods->get_elem( s_name );
  pthread_mutex_unlock( &mut_map_mods );

  return ! mod ? cache_module( s_name ) : mod;
}

#endif