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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3971 - (hide 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 schoenebeck 2611 /*
2 schoenebeck 3971 * Copyright (c) 2014-2021 Christian Schoenebeck
3 schoenebeck 2611 *
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 schoenebeck 3971 /**
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 schoenebeck 3733 struct ScriptKey {
48     String code; ///< Script's source code.
49     std::map<String,String> patchVars; ///< Patch variables being overridden by instrument.
50 schoenebeck 3971 EngineChannel* engineChannel; ///< Unique owning engine channel on which the compiled script is/was loaded onto.
51 schoenebeck 3733 bool wildcardPatchVars; ///< Seldom use: Allows lookup for consumers of a specific script by ignoring all (overridden) patch variables.
52 schoenebeck 3971 bool wildcardEngineChannel; ///< Seldom use: Allows lookup for consumers of a specific script by ignoring on which engine channel it was loaded.
53 schoenebeck 3733
54     inline bool operator<(const ScriptKey& o) const {
55 schoenebeck 3971 if (wildcardPatchVars && wildcardEngineChannel)
56 schoenebeck 3733 return code < o.code;
57 schoenebeck 3971 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 schoenebeck 3733 else
62 schoenebeck 3971 return code < o.code || (code == o.code && (patchVars < o.patchVars || (patchVars == o.patchVars && engineChannel < o.engineChannel)));
63 schoenebeck 3733 }
64    
65     inline bool operator>(const ScriptKey& o) const {
66 schoenebeck 3971 if (wildcardPatchVars && wildcardEngineChannel)
67 schoenebeck 3733 return code > o.code;
68 schoenebeck 3971 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 schoenebeck 3733 else
73 schoenebeck 3971 return code > o.code || (code == o.code && (patchVars > o.patchVars || (patchVars == o.patchVars && engineChannel > o.engineChannel)));
74 schoenebeck 3733 }
75    
76     inline bool operator==(const ScriptKey& o) const {
77 schoenebeck 3971 if (wildcardPatchVars && wildcardEngineChannel)
78 schoenebeck 3733 return code == o.code;
79 schoenebeck 3971 else if (wildcardPatchVars)
80     return code == o.code && engineChannel == o.engineChannel;
81     else if (wildcardEngineChannel)
82     return code == o.code && patchVars == o.patchVars;
83 schoenebeck 3733 else
84 schoenebeck 3971 return code == o.code && patchVars == o.patchVars && engineChannel == o.engineChannel;
85 schoenebeck 3733 }
86    
87     inline bool operator!=(const ScriptKey& o) const {
88     return !(operator==(o));
89     }
90     };
91    
92 schoenebeck 2611 class AbstractInstrumentManager : public InstrumentManager {
93     public:
94     AbstractInstrumentManager() { }
95     virtual ~AbstractInstrumentManager() { }
96    
97 schoenebeck 2902 /**
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 schoenebeck 3733 * 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 schoenebeck 2902 */
107 schoenebeck 3733 class ScriptResourceManager : public ResourceManager<ScriptKey, VMParserContext> {
108 schoenebeck 2611 public:
109     ScriptResourceManager() {}
110     virtual ~ScriptResourceManager() {}
111     protected:
112     // implementation of derived abstract methods from 'ResourceManager'
113 schoenebeck 3733 virtual VMParserContext* Create(ScriptKey key, InstrumentScriptConsumer* pConsumer, void*& pArg);
114 schoenebeck 2611 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