/[svn]/linuxsampler/trunk/src/engines/common/AbstractInstrumentManager.h
ViewVC logotype

Contents of /linuxsampler/trunk/src/engines/common/AbstractInstrumentManager.h

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3971 - (show annotations) (download) (as text)
Fri Jun 25 09:26:00 2021 UTC (2 years, 9 months ago) by schoenebeck
File MIME type: text/x-c++hdr
File size: 5642 byte(s)
* Fix: Do not share compiled instrument scripts among multiple engine
  channels (sampler parts) as this can lead to crashes and would allow the
  same global script variables to be accessible from multiple engine
  channels which would not be the expected behaviour by instrument script
  authors.

* Bumped version (2.2.0.svn5).

1 /*
2 * Copyright (c) 2014-2021 Christian Schoenebeck
3 *
4 * http://www.linuxsampler.org
5 *
6 * This file is part of LinuxSampler and released under the same terms.
7 * See README file for details.
8 */
9
10 #ifndef LS_ABSTRACTINSTRUMENTMANAGER_H
11 #define LS_ABSTRACTINSTRUMENTMANAGER_H
12
13 #include "../InstrumentManager.h"
14 #include "../../common/ResourceManager.h"
15 #include "../../common/global_private.h"
16 #include "InstrumentScriptVM.h"
17
18 namespace LinuxSampler {
19
20 typedef ResourceConsumer<VMParserContext> InstrumentScriptConsumer;
21
22 /**
23 * Identifies uniquely a compiled script.
24 *
25 * Note: every engine channel now has its own compiled script object
26 * (a.k.a. VMParserContext). Originally a compiled script was shared by
27 * multiple engine channels. This was wrong: we cannot share compiled
28 * script instances among multiple engine channels (parts), for two
29 * reasons:
30 *
31 * 1. VMParserContext not only encompasses the compiled tree
32 * presentation of the requested script, but also global variables
33 * and we don't want those global variables to be modified by
34 * different sampler parts, as this would not be expected behaviour
35 * by instrument script authors.
36 *
37 * 2. If there is more than one sampler engine instance (e.g. if there
38 * are multiple audio output device instances) this would even crash,
39 * because each sampler engine instance has its own ScriptVM
40 * instance, and a (VM)ParserContext is always tied to exactly one
41 * ScriptVM instance.
42 *
43 * We would not be buying much by sharing compiled scripts anyway, as a
44 * script usually compiles in couple microseconds and RAM usage is also
45 * neglectable.
46 */
47 struct ScriptKey {
48 String code; ///< Script's source code.
49 std::map<String,String> patchVars; ///< Patch variables being overridden by instrument.
50 EngineChannel* engineChannel; ///< Unique owning engine channel on which the compiled script is/was loaded onto.
51 bool wildcardPatchVars; ///< Seldom use: Allows lookup for consumers of a specific script by ignoring all (overridden) patch variables.
52 bool wildcardEngineChannel; ///< Seldom use: Allows lookup for consumers of a specific script by ignoring on which engine channel it was loaded.
53
54 inline bool operator<(const ScriptKey& o) const {
55 if (wildcardPatchVars && wildcardEngineChannel)
56 return code < o.code;
57 else if (wildcardPatchVars)
58 return code < o.code || (code == o.code && engineChannel < o.engineChannel);
59 else if (wildcardEngineChannel)
60 return code < o.code || (code == o.code && patchVars < o.patchVars);
61 else
62 return code < o.code || (code == o.code && (patchVars < o.patchVars || (patchVars == o.patchVars && engineChannel < o.engineChannel)));
63 }
64
65 inline bool operator>(const ScriptKey& o) const {
66 if (wildcardPatchVars && wildcardEngineChannel)
67 return code > o.code;
68 else if (wildcardPatchVars)
69 return code > o.code || (code == o.code && engineChannel > o.engineChannel);
70 else if (wildcardEngineChannel)
71 return code > o.code || (code == o.code && patchVars > o.patchVars);
72 else
73 return code > o.code || (code == o.code && (patchVars > o.patchVars || (patchVars == o.patchVars && engineChannel > o.engineChannel)));
74 }
75
76 inline bool operator==(const ScriptKey& o) const {
77 if (wildcardPatchVars && wildcardEngineChannel)
78 return code == o.code;
79 else if (wildcardPatchVars)
80 return code == o.code && engineChannel == o.engineChannel;
81 else if (wildcardEngineChannel)
82 return code == o.code && patchVars == o.patchVars;
83 else
84 return code == o.code && patchVars == o.patchVars && engineChannel == o.engineChannel;
85 }
86
87 inline bool operator!=(const ScriptKey& o) const {
88 return !(operator==(o));
89 }
90 };
91
92 class AbstractInstrumentManager : public InstrumentManager {
93 public:
94 AbstractInstrumentManager() { }
95 virtual ~AbstractInstrumentManager() { }
96
97 /**
98 * Resource manager for loading and sharing the parsed (executable) VM
99 * presentation of real-time instrument scripts. The key used here, and
100 * associated with each script resource, is not as one might expect the
101 * script name or something equivalent, instead the key used is
102 * actually the entire script's source code text (and additionally
103 * potentially patched variables). The value (the actual resource) is of
104 * type @c VMParserContext, which is the parsed (executable) VM
105 * representation of the respective script.
106 */
107 class ScriptResourceManager : public ResourceManager<ScriptKey, VMParserContext> {
108 public:
109 ScriptResourceManager() {}
110 virtual ~ScriptResourceManager() {}
111 protected:
112 // implementation of derived abstract methods from 'ResourceManager'
113 virtual VMParserContext* Create(ScriptKey key, InstrumentScriptConsumer* pConsumer, void*& pArg);
114 virtual void Destroy(VMParserContext* pResource, void* pArg);
115 virtual void OnBorrow(VMParserContext* pResource, InstrumentScriptConsumer* pConsumer, void*& pArg) {} // ignore
116 } scripts;
117 };
118
119 } // namespace LinuxSampler
120
121 #endif // LS_ABSTRACTINSTRUMENTMANAGER_H

  ViewVC Help
Powered by ViewVC