SeExpr
ExprFunc.cpp
Go to the documentation of this file.
1 /*
2  Copyright Disney Enterprises, Inc. All rights reserved.
3 
4  Licensed under the Apache License, Version 2.0 (the "License");
5  you may not use this file except in compliance with the License
6  and the following modification to it: Section 6 Trademarks.
7  deleted and replaced with:
8 
9  6. Trademarks. This License does not grant permission to use the
10  trade names, trademarks, service marks, or product names of the
11  Licensor and its affiliates, except as required for reproducing
12  the content of the NOTICE file.
13 
14  You may obtain a copy of the License at
15  http://www.apache.org/licenses/LICENSE-2.0
16 */
17 #include <string>
18 #include <map>
19 #include <stdlib.h>
20 #include <iostream>
21 #ifndef SEEXPR_WIN32
22 #include <dlfcn.h>
23 #include <dirent.h>
24 #endif
25 
26 #include "Expression.h"
27 #include "ExprFunc.h"
28 #include "ExprNode.h"
29 #include "ExprBuiltins.h"
30 
31 #include "Mutex.h"
32 
33 namespace {
34 // FuncTable - table of pre-defined functions
35 class FuncTable {
36  public:
37  void define(const char* name, SeExpr2::ExprFunc f, const char* docString = 0) {
38  if (docString)
39  funcmap[name] = FuncMapItem(std::string(docString), f);
40  else
41  funcmap[name] = FuncMapItem(name, f);
42  }
43 
44  const SeExpr2::ExprFunc* lookup(const std::string& name) {
45  FuncMap::iterator iter;
46  if ((iter = funcmap.find(name)) != funcmap.end()) return &iter->second.second;
47  return 0;
48  }
49  void initBuiltins();
50 
51  void getFunctionNames(std::vector<std::string>& names) {
52  for (FuncMap::iterator i = funcmap.begin(); i != funcmap.end(); ++i) names.push_back(i->first);
53  }
54 
55  std::string getDocString(const char* functionName) {
56  FuncMap::iterator i = funcmap.find(functionName);
57  if (i == funcmap.end())
58  return "";
59  else
60  return i->second.first;
61  }
62 
63  size_t sizeInBytes() const {
64  size_t totalSize = 0;
65  for (FuncMap::const_iterator it = funcmap.begin(); it != funcmap.end(); ++it) {
66  totalSize += it->first.size() + sizeof(FuncMapItem);
67  const SeExpr2::ExprFunc& function = it->second.second;
68  if (const SeExpr2::ExprFuncX* funcx = function.funcx()) {
69  totalSize += funcx->sizeInBytes();
70  }
71  }
72  return totalSize;
73  }
74 
75  SeExpr2::Statistics statistics() const {
76  SeExpr2::Statistics statisticsDump;
77  size_t totalSize = 0;
78  for (FuncMap::const_iterator it = funcmap.begin(); it != funcmap.end(); ++it) {
79  totalSize += it->first.size() + sizeof(FuncMapItem);
80  const SeExpr2::ExprFunc& function = it->second.second;
81  if (const SeExpr2::ExprFuncX* funcx = function.funcx()) {
82  funcx->statistics(statisticsDump);
83  }
84  }
85  return statisticsDump;
86  }
87 
88  private:
89  typedef std::pair<std::string, SeExpr2::ExprFunc> FuncMapItem;
90  typedef std::map<std::string, FuncMapItem> FuncMap;
91  FuncMap funcmap;
92 };
93 
94 FuncTable* Functions = 0;
95 }
96 
97 // ExprType ExprFuncX::prep(ExprFuncNode* node, bool scalarWanted, ExprVarEnv & env) const
98 //{
99 // /* call base node prep by default:
100 // this passes wantVec to all the children and sets isVec true if any
101 // child is a vec */
102 // /* TODO: check that this is correct behavior */
103 // return node->ExprNode::prep(scalarWanted, env);
104 //}
105 
106 namespace SeExpr2 {
107 
109 
112  initInternal();
113 }
114 
117  delete Functions;
118  Functions = nullptr;
119 }
120 
121 const ExprFunc* ExprFunc::lookup(const std::string& name) {
122  mutex.lock();
123  if (!Functions) initInternal();
124  const ExprFunc* ret = Functions->lookup(name);
125  mutex.unlock();
126  return ret;
127 }
128 
129 inline static void defineInternal(const char* name, ExprFunc f) {
130  // THIS FUNCTION IS NOT THREAD SAFE, it assumes you have a mutex from callee
131  // ALSO YOU MUST BE VERY CAREFUL NOT TO CALL ANYTHING THAT TRIES TO REACQUIRE MUTEX!
132  Functions->define(name, f);
133 }
134 
135 inline static void defineInternal3(const char* name, ExprFunc f, const char* docString) {
136  // THIS FUNCTION IS NOT THREAD SAFE, it assumes you have a mutex from callee
137  // ALSO YOU MUST BE VERY CAREFUL NOT TO CALL ANYTHING THAT TRIES TO REACQUIRE MUTEX!
138  Functions->define(name, f, docString);
139 }
140 
142  // THIS FUNCTION IS NOT THREAD SAFE, it assumes you have a mutex from callee
143  // ALSO YOU MUST BE VERY CAREFUL NOT TO CALL ANYTHING THAT TRIES TO REACQUIRE MUTEX!
144 
145  // TODO: make thread safe
146  if (Functions) return;
147  Functions = new FuncTable;
149  const char* path = getenv("SE_EXPR_PLUGINS");
150  if (path) loadPlugins(path);
151 }
152 
153 void ExprFunc::define(const char* name, ExprFunc f) {
154  mutex.lock();
155  if (!Functions) initInternal();
156  defineInternal(name, f);
157  mutex.unlock();
158 }
159 
160 void ExprFunc::define(const char* name, ExprFunc f, const char* docString) {
161  mutex.lock();
162  if (!Functions) initInternal();
163  defineInternal3(name, f, docString);
164  mutex.unlock();
165 }
166 
167 void ExprFunc::getFunctionNames(std::vector<std::string>& names) {
168  mutex.lock();
169  if (!Functions) initInternal();
170  Functions->getFunctionNames(names);
171  mutex.unlock();
172 }
173 
174 std::string ExprFunc::getDocString(const char* functionName) {
175  mutex.lock();
176  if (!Functions) initInternal();
177  std::string ret = Functions->getDocString(functionName);
178  mutex.unlock();
179  return ret;
180 }
181 
184  if (!Functions) initInternal();
185  return Functions->sizeInBytes();
186 }
187 
190  if (!Functions) initInternal();
191  return Functions->statistics();
192 }
193 
194 #ifndef SEEXPR_WIN32
195 
196 #if defined(__APPLE__) && !defined(__MAC_10_9)
197 static int MatchPluginName(const struct dirent* dir)
198 #else
199 static int MatchPluginName(const struct dirent* dir)
200 #endif
201 {
202  const char* name = dir->d_name;
203  // return true if name matches SeExpr*.so
204  return !strncmp(name, "SeExpr", 6) && !strcmp(name + strlen(name) - 3, ".so");
205 }
206 #endif
207 
208 void ExprFunc::loadPlugins(const char* path) {
209 #ifdef SEEXPR_WIN32
210 
211 #else
212  // first split path into individual entries
213  char* pathdup = strdup(path);
214  char* state = 0;
215  char* entry = strtok_r(pathdup, ":", &state);
216  while (entry) {
217  // if entry ends with ".so", load directly
218  if ((!strcmp(entry + strlen(entry) - 3, ".so")))
219  loadPlugin(entry);
220  else {
221  // assume it's a dir - search it for plugins
222  struct dirent** matches = 0;
223  int numMatches = scandir(entry, &matches, MatchPluginName, alphasort);
224  for (int i = 0; i < numMatches; i++) {
225  std::string fullpath = entry;
226  fullpath += "/";
227  fullpath += matches[i]->d_name;
228  loadPlugin(fullpath.c_str());
229  }
230  if (matches)
231  free(matches);
232  else {
233  std::cerr << "No plugins found matching " << path << "/SeExpr*.so" << std::endl;
234  }
235  }
236 
237  entry = strtok_r(0, ":", &state);
238  }
239  free(pathdup);
240 #endif
241 }
242 
243 void ExprFunc::loadPlugin(const char* path) {
244 #ifdef SEEXPR_WIN32
245  std::cerr << "SeExpr: warning Plugins are not supported on windows currently" << std::endl;
246 #else
247  void* handle = dlopen(path, RTLD_LAZY);
248  if (!handle) {
249  std::cerr << "Error reading expression plugin: " << path << std::endl;
250  const char* err = dlerror();
251  if (err) std::cerr << err << std::endl;
252  return;
253  }
254 
255  typedef void (*initfn_v3)(ExprFunc::Define3);
256  initfn_v3 init_v3 = (initfn_v3)dlsym(handle, "SeExpr2PluginInit");
257 
258  if (init_v3)
259  init_v3(defineInternal3);
260  else {
261  void* init_v2 = dlsym(handle, "SeExprPluginInitV2");
262  void* init_v1 = dlsym(handle, "SeExprPluginInit");
263  if (!init_v1 && !init_v2) {
264  std::cerr << "Error reading expression plugin: " << path << std::endl;
265  std::cerr << "No functions named SeExprPluginInit and SeExprPluginInitV2 called" << std::endl;
266  }
267  dlclose(handle);
268  return;
269  }
270 #endif
271 }
272 }
static std::string getDocString(const char *functionName)
Get doc string for a specific function.
Definition: ExprFunc.cpp:174
void(* Define3)(const char *name, ExprFunc f, const char *docString)
Definition: ExprFunc.h:65
static SeExprInternal2::Mutex mutex
Definition: ExprFunc.cpp:108
static void defineInternal3(const char *name, ExprFunc f, const char *docString)
Definition: ExprFunc.cpp:135
static void getFunctionNames(std::vector< std::string > &names)
Get a list of registered builtin and DSO generated functions.
Definition: ExprFunc.cpp:167
static size_t sizeInBytes()
Get the total size estimate of all plugins.
Definition: ExprFunc.cpp:182
void defineBuiltins(ExprFunc::Define define, ExprFunc::Define3 define3)
Function Definition, used in parse tree and func table.
Definition: ExprFunc.h:44
static Statistics statistics()
Dump statistics.
Definition: ExprFunc.cpp:188
static void define(const char *name, ExprFunc f, const char *docString)
Definition: ExprFunc.cpp:160
with numParticles numAttributes A variable block contains variable names and types but doesn t care what the values are< pre > void f(const std::string &s, MyParticleData *p, int outputDim=3)
Definition: varblocks.txt:35
static int MatchPluginName(const struct dirent *dir)
Definition: ExprFunc.cpp:199
static void loadPlugins(const char *path)
load all plugins in a given path
Definition: ExprFunc.cpp:208
static void loadPlugin(const char *path)
load a given plugin
Definition: ExprFunc.cpp:243
static const ExprFunc * lookup(const std::string &name)
Lookup a builtin function by name.
Definition: ExprFunc.cpp:121
static void initInternal()
Definition: ExprFunc.cpp:141
static void defineInternal(const char *name, ExprFunc f)
Definition: ExprFunc.cpp:129
Extension function spec, used for complicated argument custom functions.
Definition: ExprFuncX.h:35
static void cleanup()
cleanup all functions
Definition: ExprFunc.cpp:115
std::map< std::string, double > Statistics
Definition: ExprFuncX.h:27
static void init()
call to define built-in funcs and load standard plugins
Definition: ExprFunc.cpp:110
you may not use this file except in compliance with the License and the following modification to it
Definition: license.txt:10