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
108 std::vector<void*> ExprFunc::dynlib;
109
110 static SeExprInternal2::Mutex mutex;
111
112 void ExprFunc::init() {
113 SeExprInternal2::AutoMutex locker(mutex);
114 initInternal();
115 }
116
117 void ExprFunc::cleanup() {
118 SeExprInternal2::AutoMutex locker(mutex);
119 delete Functions;
120 Functions = nullptr;
121 #ifdef SEEXPR_WIN32
122 #else
123 for(size_t i=0; i<dynlib.size(); i++){
124 dlclose(dynlib[i]);
125 }
126 #endif
127
128 }
129
130 const ExprFunc* ExprFunc::lookup(const std::string& name) {
131 mutex.lock();
132 if (!Functions) initInternal();
133 const ExprFunc* ret = Functions->lookup(name);
134 mutex.unlock();
135 return ret;
136 }
137
138 inline static void defineInternal(const char* name, ExprFunc f) {
139 // THIS FUNCTION IS NOT THREAD SAFE, it assumes you have a mutex from callee
140 // ALSO YOU MUST BE VERY CAREFUL NOT TO CALL ANYTHING THAT TRIES TO REACQUIRE MUTEX!
141 Functions->define(name, f);
142 }
143
144 inline static void defineInternal3(const char* name, ExprFunc f, const char* docString) {
145 // THIS FUNCTION IS NOT THREAD SAFE, it assumes you have a mutex from callee
146 // ALSO YOU MUST BE VERY CAREFUL NOT TO CALL ANYTHING THAT TRIES TO REACQUIRE MUTEX!
147 Functions->define(name, f, docString);
148 }
149
150 void ExprFunc::initInternal() {
151 // THIS FUNCTION IS NOT THREAD SAFE, it assumes you have a mutex from callee
152 // ALSO YOU MUST BE VERY CAREFUL NOT TO CALL ANYTHING THAT TRIES TO REACQUIRE MUTEX!
153
154 // TODO: make thread safe
155 if (Functions) return;
156 Functions = new FuncTable;
157 SeExpr2::defineBuiltins(defineInternal, defineInternal3);
158 const char* path = getenv("SE_EXPR_PLUGINS");
159 if (path) loadPlugins(path);
160 }
161
162 void ExprFunc::define(const char* name, ExprFunc f) {
163 mutex.lock();
164 if (!Functions) initInternal();
165 defineInternal(name, f);
166 mutex.unlock();
167 }
168
169 void ExprFunc::define(const char* name, ExprFunc f, const char* docString) {
170 mutex.lock();
171 if (!Functions) initInternal();
172 defineInternal3(name, f, docString);
173 mutex.unlock();
174 }
175
176 void ExprFunc::getFunctionNames(std::vector<std::string>& names) {
177 mutex.lock();
178 if (!Functions) initInternal();
179 Functions->getFunctionNames(names);
180 mutex.unlock();
181 }
182
183 std::string ExprFunc::getDocString(const char* functionName) {
184 mutex.lock();
185 if (!Functions) initInternal();
186 std::string ret = Functions->getDocString(functionName);
187 mutex.unlock();
188 return ret;
189 }
190
191 size_t ExprFunc::sizeInBytes() {
192 SeExprInternal2::AutoMutex locker(mutex);
193 if (!Functions) initInternal();
194 return Functions->sizeInBytes();
195 }
196
197 SeExpr2::Statistics ExprFunc::statistics() {
198 SeExprInternal2::AutoMutex locker(mutex);
199 if (!Functions) initInternal();
200 return Functions->statistics();
201 }
202
203 #ifndef SEEXPR_WIN32
204
205 #if defined(__APPLE__) && !defined(__MAC_10_9)
206 static int MatchPluginName(const struct dirent* dir)
207 #else
208 static int MatchPluginName(const struct dirent* dir)
209 #endif
210 {
211 const char* name = dir->d_name;
212 // return true if name matches SeExpr*.so
213 return !strncmp(name, "SeExpr", 6) && !strcmp(name + strlen(name) - 3, ".so");
214 }
215 #endif
216
217 void ExprFunc::loadPlugins(const char* path) {
218 #ifdef SEEXPR_WIN32
219
220 #else
221 // first split path into individual entries
222 char* pathdup = strdup(path);
223 char* state = 0;
224 char* entry = strtok_r(pathdup, ":", &state);
225 while (entry) {
226 // if entry ends with ".so", load directly
227 if ((!strcmp(entry + strlen(entry) - 3, ".so")))
228 loadPlugin(entry);
229 else {
230 // assume it's a dir - search it for plugins
231 struct dirent** matches = 0;
232 int numMatches = scandir(entry, &matches, MatchPluginName, alphasort);
233 for (int i = 0; i < numMatches; i++) {
234 std::string fullpath = entry;
235 fullpath += "/";
236 fullpath += matches[i]->d_name;
237 loadPlugin(fullpath.c_str());
238 }
239 if (matches)
240 free(matches);
241 else {
242 std::cerr << "No plugins found matching " << path << "/SeExpr*.so" << std::endl;
243 }
244 }
245
246 entry = strtok_r(0, ":", &state);
247 }
248 free(pathdup);
249 #endif
250 }
251
252 void ExprFunc::loadPlugin(const char* path) {
253 #ifdef SEEXPR_WIN32
254 std::cerr << "SeExpr: warning Plugins are not supported on windows currently" << std::endl;
255 #else
256 void* handle = dlopen(path, RTLD_LAZY);
257 if (!handle) {
258 std::cerr << "Error reading expression plugin: " << path << std::endl;
259 const char* err = dlerror();
260 if (err) std::cerr << err << std::endl;
261 return;
262 }
263
264 typedef void (*initfn_v3)(ExprFunc::Define3);
265 initfn_v3 init_v3 = (initfn_v3)dlsym(handle, "SeExpr2PluginInit");
266
267 if (init_v3) {
268 init_v3(defineInternal3);
269 dynlib.push_back(handle);
270 } else {
271 std::cerr << "Error reading expression plugin: " << path << std::endl;
272 std::cerr << "No function named SeExpr2PluginInit defined" << std::endl;
273 dlclose(handle);
274 }
275 return;
276 #endif
277 }
278 }
SeExprInternal2::DebugLock::unlock
void unlock()
Definition: Mutex.h:35
f
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
SeExpr2::defineInternal3
static void defineInternal3(const char *name, ExprFunc f, const char *docString)
Definition: ExprFunc.cpp:144
SeExpr2::ExprFunc::cleanup
static void cleanup()
cleanup all functions
Definition: ExprFunc.cpp:117
SeExpr2::ExprFunc::init
static void init()
call to define built-in funcs and load standard plugins
Definition: ExprFunc.cpp:112
SeExpr2::ExprFunc::Define3
void(* Define3)(const char *name, ExprFunc f, const char *docString)
Definition: ExprFunc.h:65
SeExpr2::ExprFunc::getFunctionNames
static void getFunctionNames(std::vector< std::string > &names)
Get a list of registered builtin and DSO generated functions.
Definition: ExprFunc.cpp:176
SeExpr2::mutex
static SeExprInternal2::Mutex mutex
Definition: ExprFunc.cpp:110
SeExpr2::ExprFunc::sizeInBytes
static size_t sizeInBytes()
Get the total size estimate of all plugins.
Definition: ExprFunc.cpp:191
SeExpr2::defineBuiltins
void defineBuiltins(ExprFunc::Define define, ExprFunc::Define3 define3)
Definition: ExprBuiltins.cpp:1603
SeExpr2::MatchPluginName
static int MatchPluginName(const struct dirent *dir)
Definition: ExprFunc.cpp:208
SeExpr2::ExprFuncX
Extension function spec, used for complicated argument custom functions.
Definition: ExprFuncX.h:35
ExprFunc.h
SeExpr2::ExprFunc
Function Definition, used in parse tree and func table.
Definition: ExprFunc.h:44
SeExpr2
Definition: Context.h:22
SeExpr2::ExprFunc::statistics
static Statistics statistics()
Dump statistics.
Definition: ExprFunc.cpp:197
ExprNode.h
SeExpr2::ExprFunc::dynlib
static std::vector< void * > dynlib
Definition: ExprFunc.h:132
ExprBuiltins.h
SeExpr2::defineInternal
static void defineInternal(const char *name, ExprFunc f)
Definition: ExprFunc.cpp:138
it
you may not use this file except in compliance with the License and the following modification to it
Definition: license.txt:10
SeExprInternal2::AutoLock
Definition: Mutex.h:49
Mutex.h
SeExpr2::ExprFunc::loadPlugins
static void loadPlugins(const char *path)
load all plugins in a given path
Definition: ExprFunc.cpp:217
SeExpr2::ExprFunc::lookup
static const ExprFunc * lookup(const std::string &name)
Lookup a builtin function by name.
Definition: ExprFunc.cpp:130
SeExprInternal2::DebugLock
Definition: Mutex.h:28
SeExpr2::ExprFunc::define
static void define(const char *name, ExprFunc f, const char *docString)
Definition: ExprFunc.cpp:169
SeExpr2::ExprFunc::initInternal
static void initInternal()
Definition: ExprFunc.cpp:150
SeExpr2::ExprFunc::getDocString
static std::string getDocString(const char *functionName)
Get doc string for a specific function.
Definition: ExprFunc.cpp:183
Expression.h
SeExpr2::Statistics
std::map< std::string, double > Statistics
Definition: ExprFuncX.h:27
SeExpr2::ExprFunc::loadPlugin
static void loadPlugin(const char *path)
load a given plugin
Definition: ExprFunc.cpp:252
SeExprInternal2::DebugLock::lock
void lock()
Definition: Mutex.h:31