scide: refactor ide/language handshake
[supercollider.git] / include / lang / SC_LanguageClient.h
blob14eb87cb8cbce561e6a5f5ce9cf17e8cb11703b4
1 /* -*- c++ -*-
2 Abstract interpreter interface.
3 Copyright (c) 2003 2004 stefan kersten.
5 ====================================================================
7 SuperCollider real time audio synthesis system
8 Copyright (c) 2002 James McCartney. All rights reserved.
9 http://www.audiosynth.com
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 2 of the License, or
14 (at your option) any later version.
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
26 #ifndef SC_LANGUAGECLIENT_H_INCLUDED
27 #define SC_LANGUAGECLIENT_H_INCLUDED
29 #include "SC_StringBuffer.h"
30 #include "SC_Export.h"
31 #include "SC_Lock.h"
32 #include "SC_Win32Utils.h"
34 #include <pthread.h>
35 #include <stdarg.h>
36 #include <stdio.h>
37 #include <errno.h>
39 // =====================================================================
40 // SC_LanguageClient - abstract sclang client.
41 // =====================================================================
43 struct PyrSymbol;
44 struct VMGlobals;
46 extern bool compiledOK;
48 extern pthread_mutex_t gLangMutex;
49 extern VMGlobals* gMainVMGlobals;
52 // lock language,
53 // if shouldBeRunning == false, return EINTR
54 // if language has been locked, return 0
55 template <typename FlagType>
56 static inline int lockLanguageOrQuit(FlagType const & shouldBeRunning)
58 #ifdef __linux__
59 // we have pthread_mutex_timedlock
61 int status = pthread_mutex_trylock(&gLangMutex);
62 if (status == 0) {
63 if (shouldBeRunning == false) {
64 pthread_mutex_unlock(&gLangMutex);
65 return EINTR;
67 } else if (status == EBUSY) {
68 do {
69 struct timespec now;
70 clock_gettime(CLOCK_REALTIME, &now);
71 now.tv_sec += 1;
73 status = pthread_mutex_timedlock(&gLangMutex, &now);
74 if (shouldBeRunning == false) {
75 if (status == 0)
76 pthread_mutex_unlock(&gLangMutex);
77 return EINTR;
79 } while (status == ETIMEDOUT);
81 return status;
82 #else
83 int status;
84 do {
85 status = pthread_mutex_trylock (&gLangMutex);
86 if (shouldBeRunning == false) {
87 if (status == 0)
88 pthread_mutex_unlock(&gLangMutex);
89 return EINTR;
91 if (status == EBUSY) {
92 struct timespec sleepTime, remain;
93 sleepTime.tv_sec = 0;
94 sleepTime.tv_nsec = 100000;
95 nanosleep(&sleepTime, &remain);
97 } while (status);
98 return 0;
99 #endif
103 class SC_DLLEXPORT SC_LanguageClient
105 public:
106 struct Options
108 Options()
109 : mMemSpace(2*1024*1024),
110 mMemGrow(256*1024),
111 mPort(57120),
112 mRuntimeDir(0)
115 int mMemSpace; // memory space in bytes
116 int mMemGrow; // memory growth in bytes
117 int mPort; // network port number
118 char* mRuntimeDir; // runtime directory
121 public:
122 // create singleton instance
123 SC_LanguageClient(const char* name);
124 virtual ~SC_LanguageClient();
126 // singleton instance access locking
127 static void lockInstance() { gInstanceMutex.Lock(); }
128 static void unlockInstance() { gInstanceMutex.Unlock(); }
130 // return the singleton instance
131 static SC_LanguageClient* instance() { return gInstance; }
132 static SC_LanguageClient* lockedInstance() { lockInstance(); return gInstance; }
134 // initialize language runtime
135 void initRuntime(const Options& opt=Options());
136 void shutdownRuntime();
138 // return application name
139 const char* getName() const { return mName; }
141 // library startup/shutdown
142 bool isLibraryCompiled() { return compiledOK; }
143 void compileLibrary();
144 void shutdownLibrary();
145 void recompileLibrary();
147 // interpreter access
148 void lock() { pthread_mutex_lock(&gLangMutex); }
149 bool trylock() { return pthread_mutex_trylock(&gLangMutex) == 0; }
150 void unlock() { pthread_mutex_unlock(&gLangMutex); }
152 VMGlobals* getVMGlobals() { return gMainVMGlobals; }
154 void setCmdLine(const char* buf, size_t size);
155 void setCmdLine(const char* str);
156 void setCmdLine(const SC_StringBuffer& strBuf);
157 void setCmdLinef(const char* fmt, ...);
158 void runLibrary(PyrSymbol* pyrSymbol);
159 void runLibrary(const char* methodName);
160 void interpretCmdLine() { runLibrary(s_interpretCmdLine); }
161 void interpretPrintCmdLine() { runLibrary(s_interpretPrintCmdLine); }
162 void executeFile(const char* fileName);
163 void runMain() { runLibrary(s_run); }
164 void stopMain() { runLibrary(s_stop); }
166 // post file access
167 FILE* getPostFile() { return mPostFile; }
168 void setPostFile(FILE* file) { mPostFile = file; }
170 // post buffer output (subclass responsibility)
171 // should be thread-save.
172 virtual void postText(const char* str, size_t len) = 0;
173 virtual void postFlush(const char* str, size_t len) = 0;
174 virtual void postError(const char* str, size_t len) = 0;
175 // flush post buffer contents to screen.
176 // only called from the main language thread.
177 virtual void flush() = 0;
179 // common symbols
180 // only valid after the library has been compiled.
181 static PyrSymbol* s_interpretCmdLine;
182 static PyrSymbol* s_interpretPrintCmdLine;
183 static PyrSymbol* s_run;
184 static PyrSymbol* s_stop;
186 // command line argument handling utilities
187 static void snprintMemArg(char* dst, size_t size, int arg);
188 static bool parseMemArg(const char* arg, int* res);
189 static bool parsePortArg(const char* arg, int* res);
191 // AppClock driver
192 // to be called from client mainloop.
193 void tick();
194 // AppClock driver. WARNING: Must be called locked!
195 // Returns whether there is anything scheduled,
196 // and writes the scheduled absolute time, if any, into nextTime.
197 bool tickLocked( double * nextTime );
199 protected:
200 // language notifications, subclasses can override
202 // called after language runtime has been initialized
203 virtual void onInitRuntime();
204 // called after the library has been compiled
205 virtual void onLibraryStartup();
206 // called before the library is shut down
207 virtual void onLibraryShutdown();
208 // called after the interpreter has been started
209 virtual void onInterpStartup();
211 private:
212 friend void closeAllGUIScreens();
213 friend void initGUIPrimitives();
214 friend void initGUI();
216 private:
217 char* mName;
218 FILE* mPostFile;
219 SC_StringBuffer mScratch;
220 bool mRunning;
221 static SC_LanguageClient* gInstance;
222 static SC_Lock gInstanceMutex;
225 // =====================================================================
226 // library functions
227 // =====================================================================
229 extern void setPostFile(FILE* file);
230 extern "C" int vpost(const char *fmt, va_list vargs);
231 extern void post(const char *fmt, ...);
232 extern void postfl(const char *fmt, ...);
233 extern void postText(const char *text, long length);
234 extern void postChar(char c);
235 extern void error(const char *fmt, ...);
236 extern void flushPostBuf();
238 #endif // SC_LANGUAGECLIENT_H_INCLUDED