summaryrefslogtreecommitdiff
path: root/ace/DLL_Manager.h
blob: 09a8a236b7c22cbd595a912558aef60636846ff6 (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
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
/* -*- C++ -*- */

//=============================================================================
/**
 *  @file    DLL_Manager.h
 *
 *  $Id$
 *
 *  @author Don Hinton <dhinton@ieee.org>
 */
//=============================================================================


#ifndef ACE_DLL_MANAGER_H
#define ACE_DLL_MANAGER_H
#include "ace/pre.h"

#include "ace/OS.h"
#include "ace/Singleton.h"
#include "ace/Synch_T.h"
#include "ace/Auto_Ptr.h"
#include "ace/SString.h"

#if !defined (ACE_LACKS_PRAGMA_ONCE)
# pragma once
#endif /* ACE_LACKS_PRAGMA_ONCE */

#define ACE_DEFAULT_DLL_MANAGER_SIZE 1024

/**
 * @class ACE_DLL_Handle
 *
 * @brief Provides an abstract interface for handling various DLL
 * operations.
 *
 * This class is an wrapper over the various methods for utilizing
 * a dynamically linked library (DLL), which is called a shared
 * library on some platforms.  It is refcounted and managed by
 * ACE_DLL_Manager, so there will only be a single instance of this
 * class for each dll loaded, no matter how many instances of ACE_DLL
 * an application has open.  Operations <open>, <close>, and
 * <symbol> have been implemented to help opening/closing and
 * extracting symbol information from a DLL, respectively.
 *
 * Most of this class came from the original ACE_DLL class.
 * ACE_DLL is now just an interface that passed all it's calls 
 * either directly or via ACE_DLL_Manager to this class for 
 * execution.  
 *
 */
class ACE_Export ACE_DLL_Handle
{
public:

  /// Default construtor.
  ACE_DLL_Handle (void);

  /// Destructor.
  ~ACE_DLL_Handle (void);

  /// Returns the name of the shared library (without prefixes or suffixes).
  const ACE_TCHAR *dll_name () const;

  /**
   * This method opens and dynamically links <dll_name>.  The default
   * mode is <RTLD_LAZY>, which loads identifier symbols but not the
   * symbols for functions, which are loaded dynamically on-demand.
   * Other supported modes include: <RTLD_NOW>, which performs all
   * necessary relocations when <dll_name> is first loaded and
   * <RTLD_GLOBAL>, which makes symbols available for relocation
   * processing of any other DLLs.  Returns -1 on failure and 0 on
   * success.
   */
  int open (const ACE_TCHAR *dll_name, 
            int open_mode,
            ACE_SHLIB_HANDLE handle);

  /// Call to close the DLL object.  If unload = 0, it only decrements
  /// the refcount, but if unload = 1, then it will actually unload 
  /// the library when the refcount == 0;
  int close (int unload = 0);

  /// Return the current refcount.
  const sig_atomic_t refcount (void) const;

  /// If <symbol_name> is in the symbol table of the DLL a pointer to
  /// the <symbol_name> is returned.  Otherwise, returns 0.
  void *symbol (const ACE_TCHAR *symbol_name);

  /**
   * Return the handle to the caller.  If <become_owner> is non-0 then
   * caller assumes ownership of the handle so we decrement the retcount.
   */
  ACE_SHLIB_HANDLE get_handle (int become_owner = 0);
 
private:
  /// Returns a pointer to a string explaining why <symbol> or <open>
  /// failed.  This is used internal to print out the error to the log,
  /// but since this object is shared, we can't store or return the error
  /// to the caller.
  auto_ptr <ACE_TString> error (void) const;

  // Keep track of how many ACE_DLL objects have a reference to this
  // dll.
  sig_atomic_t refcount_;

  /// Name of the shared library.
  ACE_TCHAR *dll_name_;

  /// Handle to the actual library loaded by the OS.
  volatile ACE_SHLIB_HANDLE handle_;

  /// Keeps track of whether or not open() has ever been called.  This
  /// helps get around problem on Linux, and perhaps other OS's, that
  /// seg-fault if dlerror() is called before the ld library has been
  /// initialized by a call to dlopen().
  static sig_atomic_t open_called_;

#if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0)
  /// Synchronization variable for the MT_SAFE Repository
  ACE_Thread_Mutex lock_;
#endif /* ACE_MT_SAFE */

  // = Disallow copying and assignment since we don't handle these.
  ACE_UNIMPLEMENTED_FUNC (ACE_DLL_Handle (const ACE_DLL_Handle &))
  ACE_UNIMPLEMENTED_FUNC (void operator= (const ACE_DLL_Handle &))

};


/**
 * @class ACE_DLL_Manager_Ex
 *
 * @brief This class serves as a factory and repository for 
 * instances of ACE_DLL_Handle.  It is implemented and typedef'd 
 * as a singleton, ACE_DLL_Manager, and is thus always available
 * via it's instance() method.
 *
 */
class ACE_Export ACE_DLL_Manager_Ex
{
public:
  enum
  {
    DEFAULT_SIZE = ACE_DEFAULT_DLL_MANAGER_SIZE
  };

  enum UNLOAD_STRATEGY
  {
    /// The default strategy is to use a per-process strategy
    /// and unload dlls eagerly, i.e., as soon as the refcount
    /// reaches zero.
    DEFAULT = 0,
    /// Use strategies on a per-dll basis.  If dll doesn't
    /// define a strategy, use the default one.
    PER_DLL = 1,

    /// Apply the unload_strategy hook method to decide when to 
    /// unload the dll, defaults to program exit.
    LAZY = PER_DLL << 1
  };

  /// Default constructor.
  ACE_DLL_Manager_Ex (int size = ACE_DLL_Manager_Ex::DEFAULT_SIZE);

  /// Destructor.
  ~ACE_DLL_Manager_Ex (void);

  /// Factory for ACE_DLL_Handle objects.  If one already exits, 
  /// its refcount is incremented.
  ACE_DLL_Handle *open_dll (const ACE_TCHAR *dll_name, 
                            int openmode, 
                            ACE_SHLIB_HANDLE handle);

  /// Close the underlying dll.  Decrements the refcount.
  int close_dll (const ACE_TCHAR *dll_name);

  /// Returns the current UNLOAD_STRATEGY.
  u_long unload_strategy (void) const;

  /// Set the UNLOAD_STRATEGY.  If the strategy is changed for 
  /// LAZY to EAGER, then it will also unload any dlls with zero
  /// refcounts.
  void unload_strategy (u_long unload_strategy = 0);

protected:
  // Allocate handle_vector_.
  int open (int size);

  // Close all open dlls and deallocate memory.
  int close (void);

  // Find dll in handle_vector_.
  ACE_DLL_Handle *find_dll (const ACE_TCHAR *dll_name) const;

  // Applies strategy for unloading dll.
  int unload_dll (ACE_DLL_Handle *dll_handle, int force_close = 0);

private:

  /// Vector containing all loaded handle objects.
  ACE_DLL_Handle **handle_vector_;

  /// Current number of handles.
  int current_size_;

  /// Maximum number of handles.
  int total_size_;

  /// Unload strategy.
  u_long unload_strategy_;

#if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0)
  /// Synchronization variable for the MT_SAFE Repository
  ACE_Thread_Mutex lock_;
#endif /* ACE_MT_SAFE */

 // = Disallow copying and assignment since we don't handle these.
  ACE_UNIMPLEMENTED_FUNC (ACE_DLL_Manager_Ex (const ACE_DLL_Manager_Ex &))
  ACE_UNIMPLEMENTED_FUNC (void operator= (const ACE_DLL_Manager_Ex &))
};

/// Global singleton.
typedef ACE_Singleton < ACE_DLL_Manager_Ex,
                        ACE_SYNCH_MUTEX > ACE_DLL_Manager;

#endif /* ACE_DLL_MANAGER_H */