2222
2323namespace swift {
2424
25+ // / Represent a "resolved" exectuable plugin.
26+ // /
27+ // / Plugin clients usually deal with this object to communicate with the actual
28+ // / plugin implementation.
29+ // / This object has a file path of the plugin executable, and is responsible to
30+ // / launch it and manages the process. When the plugin process crashes, this
31+ // / should automatically relaunch the process so the clients can keep using this
32+ // / object as the interface.
2533class LoadedExecutablePlugin {
26- const llvm::sys::procid_t pid;
34+
35+ // / Represents the current process of the executable plugin.
36+ struct PluginProcess {
37+ const llvm::sys::procid_t pid;
38+ const int inputFileDescriptor;
39+ const int outputFileDescriptor;
40+ bool isStale = false ;
41+
42+ PluginProcess (llvm::sys::procid_t pid, int inputFileDescriptor,
43+ int outputFileDescriptor);
44+
45+ ~PluginProcess ();
46+
47+ ssize_t write (const void *buf, size_t nbyte) const ;
48+ ssize_t read (void *buf, size_t nbyte) const ;
49+ };
50+
51+ // / Launched current process.
52+ std::unique_ptr<PluginProcess> Process;
53+
54+ // / Path to the plugin executable.
55+ const std::string ExecutablePath;
56+
57+ // / Last modification time of the `ExecutablePath` when this is initialized.
2758 const llvm::sys::TimePoint<> LastModificationTime;
28- const int inputFileDescriptor;
29- const int outputFileDescriptor;
3059
3160 // / Opaque value of the protocol capability of the pluugin. This is a
3261 // / value from ASTGen.
3362 const void *capability = nullptr ;
3463
64+ // / Callbacks to be called when the connection is restored.
65+ llvm::SmallVector<std::function<void (void )> *, 0 > onReconnect;
66+
67+ // / Flag to dump plugin messagings.
68+ bool dumpMessaging = false ;
69+
3570 // / Cleanup function to call ASTGen.
3671 std::function<void (void )> cleanup;
3772
3873 std::mutex mtx;
3974
40- ssize_t write (const void *buf, size_t nbyte) const ;
41- ssize_t read (void *buf, size_t nbyte) const ;
42-
4375public:
44- LoadedExecutablePlugin (llvm::sys::procid_t pid,
45- llvm::sys::TimePoint<> LastModificationTime,
46- int inputFileDescriptor, int outputFileDescriptor);
76+ LoadedExecutablePlugin (llvm::StringRef ExecutablePath,
77+ llvm::sys::TimePoint<> LastModificationTime)
78+ : ExecutablePath(ExecutablePath),
79+ LastModificationTime (LastModificationTime){};
4780 ~LoadedExecutablePlugin ();
81+
82+ // / The last modification time of 'ExecutablePath' when this object is
83+ // / created.
4884 llvm::sys::TimePoint<> getLastModificationTime () const {
4985 return LastModificationTime;
5086 }
5187
88+ // / Indicates that the current process is usable.
89+ bool isAlive () const { return Process != nullptr && !Process->isStale ; }
90+
91+ // / Mark the current process "stale".
92+ void setStale () const { Process->isStale = true ; }
93+
5294 void lock () { mtx.lock (); }
5395 void unlock () { mtx.unlock (); }
5496
97+ // Launch the plugin if it's not already running, or it's stale. Return an
98+ // error if it's fails to execute it.
99+ llvm::Error spawnIfNeeded ();
100+
55101 // / Send a message to the plugin.
56102 llvm::Error sendMessage (llvm::StringRef message) const ;
57103
@@ -63,10 +109,23 @@ class LoadedExecutablePlugin {
63109 this ->cleanup = cleanup;
64110 }
65111
66- llvm::sys::procid_t getPid () { return pid; }
112+ // / Add "on reconnect" callback.
113+ // / These callbacks are called when `spawnIfNeeded()` relaunched the plugin.
114+ void addOnReconnect (std::function<void (void )> *fn) {
115+ onReconnect.push_back (fn);
116+ }
117+
118+ // / Remove "on reconnect" callback.
119+ void removeOnReconnect (std::function<void (void )> *fn) {
120+ llvm::erase_value (onReconnect, fn);
121+ }
122+
123+ llvm::sys::procid_t getPid () { return Process->pid ; }
67124
68125 const void *getCapability () { return capability; };
69126 void setCapability (const void *newValue) { capability = newValue; };
127+
128+ void setDumpMessaging (bool flag) { dumpMessaging = flag; }
70129};
71130
72131class PluginRegistry {
@@ -77,14 +136,22 @@ class PluginRegistry {
77136 llvm::StringMap<std::unique_ptr<LoadedExecutablePlugin>>
78137 LoadedPluginExecutables;
79138
139+ // / Flag to dump plugin messagings.
140+ bool dumpMessaging = false ;
141+
142+ std::mutex mtx;
143+
80144public:
145+ PluginRegistry ();
146+
147+ // / Load a dynamic link library specified by \p path.
148+ // / If \p path plugin is already loaded, this returns the cached object.
81149 llvm::Expected<void *> loadLibraryPlugin (llvm::StringRef path);
150+
151+ // / Load an executable plugin specified by \p path .
152+ // / If \p path plugin is already loaded, this returns the cached object.
82153 llvm::Expected<LoadedExecutablePlugin *>
83154 loadExecutablePlugin (llvm::StringRef path);
84-
85- const llvm::StringMap<void *> &getLoadedLibraryPlugins () const {
86- return LoadedPluginLibraries;
87- }
88155};
89156
90157} // namespace swift
0 commit comments