~ubuntu-branches/ubuntu/saucy/kopete/saucy-proposed

« back to all changes in this revision

Viewing changes to protocols/jabber/googletalk/libjingle/talk/base/latebindingsymboltable.h

  • Committer: Package Import Robot
  • Author(s): Jonathan Riddell
  • Date: 2013-06-21 02:22:39 UTC
  • Revision ID: package-import@ubuntu.com-20130621022239-63l3zc8p0nf26pt6
Tags: upstream-4.10.80
ImportĀ upstreamĀ versionĀ 4.10.80

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * libjingle
 
3
 * Copyright 2004--2010, Google Inc.
 
4
 *
 
5
 * Redistribution and use in source and binary forms, with or without
 
6
 * modification, are permitted provided that the following conditions are met:
 
7
 *
 
8
 *  1. Redistributions of source code must retain the above copyright notice,
 
9
 *     this list of conditions and the following disclaimer.
 
10
 *  2. Redistributions in binary form must reproduce the above copyright notice,
 
11
 *     this list of conditions and the following disclaimer in the documentation
 
12
 *     and/or other materials provided with the distribution.
 
13
 *  3. The name of the author may not be used to endorse or promote products
 
14
 *     derived from this software without specific prior written permission.
 
15
 *
 
16
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
 
17
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 
18
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
 
19
 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 
20
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 
21
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 
22
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 
23
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 
24
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 
25
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
26
 */
 
27
 
 
28
#ifndef TALK_BASE_LATEBINDINGSYMBOLTABLE_H_
 
29
#define TALK_BASE_LATEBINDINGSYMBOLTABLE_H_
 
30
 
 
31
#include <string.h>
 
32
 
 
33
#include "talk/base/common.h"
 
34
#include "talk/base/logging.h"
 
35
 
 
36
// This file provides macros for creating "symbol table" classes to simplify the
 
37
// dynamic loading of symbols from DLLs. Currently the implementation only
 
38
// supports Linux and pure C symbols.
 
39
// See talk/sound/pulseaudiosymboltable.(h|cc) for an example.
 
40
 
 
41
namespace talk_base {
 
42
 
 
43
#ifdef LINUX
 
44
typedef void *DllHandle;
 
45
 
 
46
const DllHandle kInvalidDllHandle = NULL;
 
47
#else
 
48
#error Not implemented
 
49
#endif
 
50
 
 
51
// These are helpers for use only by the class below.
 
52
DllHandle InternalLoadDll(const char dll_name[]);
 
53
 
 
54
void InternalUnloadDll(DllHandle handle);
 
55
 
 
56
bool InternalLoadSymbols(DllHandle handle,
 
57
                         int num_symbols,
 
58
                         const char *const symbol_names[],
 
59
                         void *symbols[]);
 
60
 
 
61
template <int SYMBOL_TABLE_SIZE,
 
62
          const char kDllName[],
 
63
          const char *const kSymbolNames[]>
 
64
class LateBindingSymbolTable {
 
65
 public:
 
66
  LateBindingSymbolTable()
 
67
      : handle_(kInvalidDllHandle),
 
68
        undefined_symbols_(false) {
 
69
    memset(symbols_, 0, sizeof(symbols_));
 
70
  }
 
71
 
 
72
  ~LateBindingSymbolTable() {
 
73
    Unload();
 
74
  }
 
75
 
 
76
  static int NumSymbols() {
 
77
    return SYMBOL_TABLE_SIZE;
 
78
  }
 
79
 
 
80
  // We do not use this, but we offer it for theoretical convenience.
 
81
  static const char *GetSymbolName(int index) {
 
82
    ASSERT(index < NumSymbols());
 
83
    return kSymbolNames[index];
 
84
  }
 
85
 
 
86
  bool IsLoaded() const {
 
87
    return handle_ != kInvalidDllHandle;
 
88
  }
 
89
 
 
90
  // Loads the DLL and the symbol table. Returns true iff the DLL and symbol
 
91
  // table loaded successfully.
 
92
  bool Load() {
 
93
    if (IsLoaded()) {
 
94
      return true;
 
95
    }
 
96
    if (undefined_symbols_) {
 
97
      // We do not attempt to load again because repeated attempts are not
 
98
      // likely to succeed and DLL loading is costly.
 
99
      LOG(LS_ERROR) << "We know there are undefined symbols";
 
100
      return false;
 
101
    }
 
102
    handle_ = InternalLoadDll(kDllName);
 
103
    if (!IsLoaded()) {
 
104
      return false;
 
105
    }
 
106
    if (!InternalLoadSymbols(handle_, NumSymbols(), kSymbolNames, symbols_)) {
 
107
      undefined_symbols_ = true;
 
108
      Unload();
 
109
      return false;
 
110
    }
 
111
    return true;
 
112
  }
 
113
 
 
114
  void Unload() {
 
115
    if (!IsLoaded()) {
 
116
      return;
 
117
    }
 
118
    InternalUnloadDll(handle_);
 
119
    handle_ = kInvalidDllHandle;
 
120
    memset(symbols_, 0, sizeof(symbols_));
 
121
  }
 
122
 
 
123
  // Retrieves the given symbol. NOTE: Recommended to use LATESYM_GET below
 
124
  // instead of this.
 
125
  void *GetSymbol(int index) const {
 
126
    ASSERT(IsLoaded());
 
127
    ASSERT(index < NumSymbols());
 
128
    return symbols_[index];
 
129
  }
 
130
 
 
131
 private:
 
132
  DllHandle handle_;
 
133
  bool undefined_symbols_;
 
134
  void *symbols_[SYMBOL_TABLE_SIZE];
 
135
 
 
136
  DISALLOW_COPY_AND_ASSIGN(LateBindingSymbolTable);
 
137
};
 
138
 
 
139
// This macro must be invoked in a header to declare a symbol table class.
 
140
#define LATE_BINDING_SYMBOL_TABLE_DECLARE_BEGIN(ClassName) \
 
141
enum {
 
142
 
 
143
// This macro must be invoked in the header declaration once for each symbol
 
144
// (recommended to use an X-Macro to avoid duplication).
 
145
// This macro defines an enum with names built from the symbols, which
 
146
// essentially creates a hash table in the compiler from symbol names to their
 
147
// indices in the symbol table class.
 
148
#define LATE_BINDING_SYMBOL_TABLE_DECLARE_ENTRY(ClassName, sym) \
 
149
  ClassName##_SYMBOL_TABLE_INDEX_##sym,
 
150
 
 
151
// This macro completes the header declaration.
 
152
#define LATE_BINDING_SYMBOL_TABLE_DECLARE_END(ClassName) \
 
153
  ClassName##_SYMBOL_TABLE_SIZE \
 
154
}; \
 
155
\
 
156
extern const char ClassName##_kDllName[]; \
 
157
extern const char *const \
 
158
    ClassName##_kSymbolNames[ClassName##_SYMBOL_TABLE_SIZE]; \
 
159
\
 
160
typedef ::talk_base::LateBindingSymbolTable<ClassName##_SYMBOL_TABLE_SIZE, \
 
161
                                            ClassName##_kDllName, \
 
162
                                            ClassName##_kSymbolNames> \
 
163
    ClassName;
 
164
 
 
165
// This macro must be invoked in a .cc file to define a previously-declared
 
166
// symbol table class.
 
167
#define LATE_BINDING_SYMBOL_TABLE_DEFINE_BEGIN(ClassName, dllName) \
 
168
const char ClassName##_kDllName[] = dllName; \
 
169
const char *const ClassName##_kSymbolNames[ClassName##_SYMBOL_TABLE_SIZE] = {
 
170
 
 
171
// This macro must be invoked in the .cc definition once for each symbol
 
172
// (recommended to use an X-Macro to avoid duplication).
 
173
// This would have to use the mangled name if we were to ever support C++
 
174
// symbols.
 
175
#define LATE_BINDING_SYMBOL_TABLE_DEFINE_ENTRY(ClassName, sym) \
 
176
  #sym,
 
177
 
 
178
#define LATE_BINDING_SYMBOL_TABLE_DEFINE_END(ClassName) \
 
179
};
 
180
 
 
181
// Index of a given symbol in the given symbol table class.
 
182
#define LATESYM_INDEXOF(ClassName, sym) \
 
183
  (ClassName##_SYMBOL_TABLE_INDEX_##sym)
 
184
 
 
185
// Returns a reference to the given late-binded symbol, with the correct type.
 
186
#define LATESYM_GET(ClassName, inst, sym) \
 
187
  (*reinterpret_cast<typeof(&sym)>( \
 
188
      (inst)->GetSymbol(LATESYM_INDEXOF(ClassName, sym))))
 
189
 
 
190
}  // namespace talk_base
 
191
 
 
192
#endif  // TALK_BASE_LATEBINDINGSYMBOLTABLE_H_